Variables and Data Types

Imagine you're cooking in the kitchen: variables are labeled storage boxes — the label is the name, and the box contains data; data types are the shapes of the boxes — round boxes hold soup, square boxes hold dishes, and you can't mix them up. Go is very strict about "box" management: you must declare what box (type) you need, what content to put in (assignment), and even empty boxes have default contents (zero values).


1. Core Concepts

1.1 Variable Declaration: var vs :=

Go provides two ways to declare variables:

Method Syntax Use Case Scope
var var name int Package-level variables, explicit types needed Inside/outside functions
Short declaration := name := 10 Local variables, type inference Inside functions only

Key differences:

1.2 Basic Data Types

Category Type Description Example
Integer int, int8, int16, int32, int64 Signed integers var a int = 42
Unsigned integer uint, uint8, uint16, uint32, uint64 Non-negative integers var b uint = 100
Floating point float32, float64 Decimals (default float64) var c float64 = 3.14
Boolean bool true / false var d bool = true
String string Immutable byte sequence var e string = "hello"
Byte byte Alias for uint8, represents one byte var f byte = 'A'
Unicode character rune Alias for int32, represents one Unicode code point var g rune = '€'

Platform-dependent types: int and uint are 32-bit on 32-bit systems and 64-bit on 64-bit systems. In daily development, int is sufficient in most cases.

1.3 Zero Value Mechanism

When a variable is declared but not assigned in Go, it is automatically initialized to a zero value, not null or undefined:

Type Zero Value
Integer (int, uint, etc.) 0
Floating point (float32, float64) 0.0
Boolean (bool) false
String (string) "" (empty string)
Pointer, slice, map, channel, function, interface nil

This is Go's safety mechanism — you never get a variable with "no value", avoiding many null pointer errors.

1.4 Constants and iota

1.5 Type Conversion

Go does not support implicit type conversion; different types must be explicitly converted:

GO
var i int = 42
var f float64 = float64(i) // int → float64
var u uint = uint(f)        // float64 → uint

1.6 fmt Package Formatted Output

fmt is Go's most commonly used formatting package. Key functions:

Function Purpose Example
fmt.Println Print with newline fmt.Println("hello")
fmt.Printf Formatted print (no newline) fmt.Printf("value=%d", 42)
fmt.Sprintf Format to string (no print) s := fmt.Sprintf("%d", 42)

Common format specifiers: %d (integer), %f (float), %s (string), %t (boolean), %T (type), %v (generic value), %q (quoted string).


2. Basic Syntax/Usage

Variable Declaration

GO
// Method 1: var declaration (inside/outside functions)
var name string       // Declaration, zero value ""
var age int = 25      // Declaration with assignment
var score = 98.5      // Type inference as float64

// Method 2: short declaration := (inside functions only)
city := "Beijing"     // Declaration with assignment, inferred as string
count := 100          // Type inference as int

// Batch declaration
var (
    width  int     = 10
    height int     = 20
    area   float64
)
💡 Tip: If you declare a variable with var but don't use it, the Go compiler will report declared and not used. This is Go's design philosophy: no dead code allowed. Same applies to short declaration :=.

Constant Declaration

GO
// Single constant
const Pi = 3.14159
const Language string = "Go"

// Batch constants + iota enumeration
const (
    Sunday    = iota // 0
    Monday           // 1
    Tuesday          // 2
    Wednesday        // 3
    Thursday         // 4
    Friday           // 5
    Saturday         // 6
)
💡 Tip: iota is only valid within a const block and auto-increments by 1 for each new line. If a line uses _ to skip, iota still increments.

Type Conversion

GO
var i int = 100
var f float64 = float64(i)  // Explicit conversion: int → float64
var s string = string(rune(i)) // int → rune → string (note: doesn't turn number to string)
// Correct way to convert number to string:
s2 := fmt.Sprintf("%d", i)  // "100"
💡 Tip: string(65) produces the character "A" (ASCII code), not "65". To convert a number to a decimal string, use fmt.Sprintf or strconv.Itoa.


3. Example Code

Example 1: Basic Usage (Difficulty ⭐)

Scenario: Declare variables of different types, print their values and types.

GO
package main

import "fmt"

func main() {
    // ========== Variable Declaration ==========

    // 1. var declaration + explicit type
    var name string = "Alice"
    var age int = 28

    // 2. var declaration + type inference (compiler infers type from value)
    salary := 15000.5 // Inferred as float64

    // 3. Short variable declaration (most common)
    isEmployed := true
    city := "New York"

    // 4. Zero value demo — declare without assignment
    var defaultInt int        // Zero value: 0
    var defaultFloat float64  // Zero value: 0
    var defaultBool bool      // Zero value: false
    var defaultString string  // Zero value: ""

    // ========== Print Output ==========
    fmt.Println("=== Personal Info ===")
    fmt.Printf("Name: %s (Type: %T)\n", name, name)
    fmt.Printf("Age: %d (Type: %T)\n", age, age)
    fmt.Printf("Salary: %.1f (Type: %T)\n", salary, salary)
    fmt.Printf("Employed: %t (Type: %T)\n", isEmployed, isEmployed)
    fmt.Printf("City: %s (Type: %T)\n", city, city)

    fmt.Println("\n=== Zero Value Demo ===")
    fmt.Printf("int zero value:    %d\n", defaultInt)
    fmt.Printf("float64 zero value: %v\n", defaultFloat)
    fmt.Printf("bool zero value:   %t\n", defaultBool)
    fmt.Printf("string zero value: %q\n", defaultString) // %q shows quoted string
}
▶ Try it Yourself

Output:

TEXT
=== Personal Info ===
Name: Alice (Type: string)
Age: 28 (Type: int)
Salary: 15000.5 (Type: float64)
Employed: true (Type: bool)
City: New York (Type: string)

=== Zero Value Demo ===
int zero value:    0
float64 zero value: 0
bool zero value:   false
string zero value: ""

Key Points:


Example 2: Intermediate Usage (Difficulty ⭐⭐)

Scenario: Using constants, iota to define enums, and practical type conversion.

GO
package main

import "fmt"

// ========== iota Enum: Define Role Permissions ==========

type Role int // Custom type with int as underlying type

const (
    Guest    Role = iota // 0: Guest
    Member               // 1: Member
    Admin                // 2: Admin
    SuperAdmin           // 3: Super Admin
)

// Implement String() method for Role for easy printing
func (r Role) String() string {
    names := [...]string{"Guest", "Member", "Admin", "Super Admin"}
    if int(r) < len(names) {
        return names[r]
    }
    return "Unknown Role"
}

// ========== Advanced iota Usage: Bitwise Permission Flags ==========

type Permission int

const (
    Read    Permission = 1 << iota // 1 (001)
    Write                          // 2 (010)
    Execute                        // 4 (100)
)

// ========== Type Conversion in Practice ==========

func main() {
    // --- iota enum usage ---
    var userRole Role = Admin
    fmt.Printf("User role: %s (Value: %d)\n", userRole, userRole)

    // --- Bitwise permission combination ---
    userPerm := Read | Write // Combined permissions: Read + Write = 3 (011)
    fmt.Printf("\nUser permission value: %d (Binary: %03b)\n", userPerm, userPerm)
    fmt.Printf("Has read permission? %t\n", userPerm&Read != 0)
    fmt.Printf("Has execute permission? %t\n", userPerm&Execute != 0)

    // --- Type conversion ---
    var temperature float64 = 36.6
    var intTemp int = int(temperature) // float64 → int (truncates, doesn't round)
    fmt.Printf("\nBody temp: %.1f°C → Integer part: %d\n", temperature, intTemp)

    // Number → string (two ways)
    var code int = 65
    char := string(rune(code))      // Method 1: Convert to corresponding Unicode character → "A"
    numStr := fmt.Sprintf("%d", code) // Method 2: Convert to numeric string → "65"
    fmt.Printf("Number %d → Character: %s, String: %q\n", code, char, numStr)

    // --- Strings and bytes/characters ---
    s := "Hello,Mundo"
    fmt.Printf("\nString %q length: %d bytes\n", s, len(s))
    fmt.Println("Byte-by-byte traversal (all ASCII here, but CJK differs):")
    for i := 0; i < len(s); i++ {
        fmt.Printf("  [%d] %d %c\n", i, s[i], s[i])
    }
    fmt.Println("Rune-by-rune traversal (same for ASCII):")
    for i, r := range s {
        fmt.Printf("  [%d] %U '%c'\n", i, r, r)
    }
}
▶ Try it Yourself

Output:

TEXT
User role: Admin (Value: 2)

User permission value: 3 (Binary: 011)
Has read permission? true
Has execute permission? false

Body temp: 36.6°C → Integer part: 36
Number 65 → Character: A, String: "65"

String "Hello,Mundo" length: 11 bytes
Byte-by-byte traversal (all ASCII here, but CJK differs):
  [0] 72 H
  [1] 101 e
  [2] 108 l
  [3] 108 l
  [4] 111 o
  [5] 44 ,
  [6] 77 M
  [7] 117 u
  [8] 110 n
  [9] 100 d
  [10] 111 o
Rune-by-rune traversal (same for ASCII):
  [0] U+0048 'H'
  [1] U+0065 'e'
  [2] U+006C 'l'
  [3] U+006C 'l'
  [4] U+006F 'o'
  [5] U+002C ','
  [6] U+004D 'M'
  [7] U+0075 'u'
  [8] U+006E 'n'
  [9] U+0064 'd'
  [10] U+006F 'o'

Key Points:


Example 3: Comprehensive Application (Difficulty ⭐⭐⭐)

Scenario: Simulate a simple user registration information processing system, combining variables, constants, type conversion, and formatted output.

GO
package main

import (
	"fmt"
	"strings"
)

// ========== Constants ==========

// Gender enum
type Gender int

const (
	Unknown Gender = iota // 0: Unknown
	Male                  // 1: Male
	Female                // 2: Female
)

func (g Gender) String() string {
	return [...]string{"Unknown", "Male", "Female"}[g]
}

// Membership levels and corresponding discounts
const (
	LevelBronze   = 1
	LevelSilver   = 2
	LevelGold     = 3
	LevelPlatinum = 4
)

// Use iota to generate discount percentages
const (
	_                   = iota // Skip 0
	DiscountBronze   = 95      // 5% off
	DiscountSilver   = 90      // 10% off
	DiscountGold     = 85      // 15% off
	DiscountPlatinum = 80      // 20% off
)

// ========== User Struct (Preview, detailed in later lessons) ==========

type User struct {
	Name     string
	Age      int
	Gender   Gender
	Level    int
	Balance  float64
}

// ========== Core Logic ==========

func main() {
	// Simulated user data
	users := []User{
		{Name: "Li Ming", Age: 25, Gender: Male, Level: LevelGold, Balance: 1580.50},
		{Name: "Wang Fang", Age: 30, Gender: Female, Level: LevelPlatinum, Balance: 3200.00},
		{Name: "Zhang Wei", Age: 17, Gender: Male, Level: LevelBronze, Balance: 200.00},
		{Name: "Zhao Min", Age: 22, Gender: Female, Level: LevelSilver, Balance: 800.75},
	}

	fmt.Println("╔══════════════════════════════════════════════════════════╗")
	fmt.Println("║              User Registration System                    ║")
	fmt.Println("╚══════════════════════════════════════════════════════════╝")
	fmt.Println()

	// Statistics variables
	var totalAge int
	var totalBalance float64
	var maleCount, femaleCount int
	var adultCount int

	for _, u := range users {
		// Get discount
		discount := getDiscount(u.Level)
		discountAmount := u.Balance * float64(100-discount) / 100.0

		// Format output user info
		ageTag := ""
		if u.Age >= 18 {
			ageTag = "✅ Adult"
			adultCount++
		} else {
			ageTag = "❌ Minor"
		}

		fmt.Printf("👤 %-8s | Gender: %-6s | Age: %d (%s) | Level: Lv.%d | Balance: $%.2f\n",
			u.Name, u.Gender, u.Age, ageTag, u.Level, u.Balance)
		fmt.Printf("   💰 %d%% discount, save $%.2f\n", discount, discountAmount)

		// Statistics
		totalAge += u.Age
		totalBalance += u.Balance
		switch u.Gender {
		case Male:
			maleCount++
		case Female:
			femaleCount++
		}

		fmt.Println(strings.Repeat("-", 60))
	}

	// Print statistics
	avgAge := float64(totalAge) / float64(len(users))
	fmt.Println()
	fmt.Println("📊 Statistics:")
	fmt.Printf("   Total users: %d\n", len(users))
	fmt.Printf("   Male: %d | Female: %d\n", maleCount, femaleCount)
	fmt.Printf("   Adults: %d | Minors: %d\n", adultCount, len(users)-adultCount)
	fmt.Printf("   Average age: %.1f years\n", avgAge)
	fmt.Printf("   Total balance: $%.2f\n", totalBalance)
	fmt.Printf("   Average balance: $%.2f\n", totalBalance/float64(len(users)))

	// Demonstrate type conversion and formatting
	fmt.Println()
	fmt.Println("🔧 Type Conversion Demo:")
	demoTypeConversion()
}

// getDiscount returns the discount based on membership level
func getDiscount(level int) int {
	switch level {
	case LevelBronze:
		return DiscountBronze
	case LevelSilver:
		return DiscountSilver
	case LevelGold:
		return DiscountGold
	case LevelPlatinum:
		return DiscountPlatinum
	default:
		return 100 // No discount
	}
}

// demoTypeConversion demonstrates various type conversion scenarios
func demoTypeConversion() {
	// 1. Numeric type conversion
	var pi float64 = 3.14159
	var intPi int = int(pi) // Truncates, doesn't round
	fmt.Printf("   float64 → int: %.5f → %d\n", pi, intPi)

	// 2. Number → string (two methods compared)
	var num int = 2024
	way1 := string(rune(num))      // Unicode character → not what you want
	way2 := fmt.Sprintf("%d", num) // Decimal string → "2024"
	way3 := fmt.Sprintf("%x", num) // Hexadecimal string → "7e8"
	fmt.Printf("   int → string (rune):  %q\n", way1)
	fmt.Printf("   int → string (%%d):    %q\n", way2)
	fmt.Printf("   int → string (%%x):    %q\n", way3)

	// 3. String → number (using fmt.Sscanf)
	var parsed int
	_, err := fmt.Sscanf("12345", "%d", &parsed)
	if err == nil {
		fmt.Printf("   string → int (Sscanf): %d\n", parsed)
	}

	// 4. bool → string
	b := true
	boolStr := fmt.Sprintf("%t", b)
	fmt.Printf("   bool → string: %t → %q\n", b, boolStr)

	// 5. Difference between rune and byte
	var r rune = '€'
	var b2 byte = 'A'
	fmt.Printf("   rune '€': value=%d, hex=%U, %d bytes (UTF-8)\n", r, r, len(string(r)))
	fmt.Printf("   byte 'A': value=%d, hex=%U, 1 byte\n", b2, b2)
}
▶ Try it Yourself

Output:

TEXT
╔══════════════════════════════════════════════════════════╗
║              User Registration System                    ║
╚══════════════════════════════════════════════════════════╝

👤 Li Ming   | Gender: Male   | Age: 25 (✅ Adult) | Level: Lv.3 | Balance: $1580.50
   💰 15% discount, save $237.08
------------------------------------------------------------
👤 Wang Fang | Gender: Female | Age: 30 (✅ Adult) | Level: Lv.4 | Balance: $3200.00
   💰 20% discount, save $640.00
------------------------------------------------------------
👤 Zhang Wei | Gender: Male   | Age: 17 (❌ Minor) | Level: Lv.1 | Balance: $200.00
   💰 5% discount, save $10.00
------------------------------------------------------------
👤 Zhao Min  | Gender: Female | Age: 22 (✅ Adult) | Level: Lv.2 | Balance: $800.75
   💰 10% discount, save $80.08
------------------------------------------------------------

📊 Statistics:
   Total users: 4
   Male: 2 | Female: 2
   Adults: 3 | Minors: 1
   Average age: 23.5 years
   Total balance: $5781.25
   Average balance: $1445.31

🔧 Type Conversion Demo:
   float64 → int: 3.14159 → 3
   int → string (rune):  "\u07e8"
   int → string (%d):    "2024"
   int → string (%x):    "7e8"
   string → int (Sscanf): 12345
   bool → string: true → "true"
   rune '€': value=8364, hex=U+20AC, 3 bytes (UTF-8)
   byte 'A': value=65, hex=U+0041, 1 byte

Key Points:


3. Common Use Cases

Case 1: Configuration Management

GO
package main

import "fmt"

// Application configuration constants (determined at compile time, immutable)
const (
	AppName    = "GoWeb"
	Version    = "1.0.0"
	MaxRetries = 3
	DefaultTimeout = 30 // seconds
)

// Environment enum
type Env int

const (
	Dev  Env = iota // Development
	Staging         // Staging
	Prod            // Production
)

func (e Env) String() string {
	return [...]string{"Dev", "Staging", "Prod"}[e]
}

func main() {
	// Runtime variables
	currentEnv := Prod
	dbHost := "192.168.1.100"
	dbPort := 3306
	debug := currentEnv == Dev

	fmt.Printf("App: %s v%s\n", AppName, Version)
	fmt.Printf("Environment: %s\n", currentEnv)
	fmt.Printf("Database: %s:%d\n", dbHost, dbPort)
	fmt.Printf("Debug mode: %t\n", debug)
	fmt.Printf("Max retries: %d, Timeout: %d seconds\n", MaxRetries, DefaultTimeout)
}

Case 2: Data Formatting & Reports

GO
package main

import "fmt"

func main() {
	// Simulated student grade data
	type Student struct {
		Name  string
		Score float64
		Grade string
	}

	students := []Student{
		{"Alice", 92.5, ""},
		{"Bob", 87.0, ""},
		{"Charlie", 76.5, ""},
		{"Diana", 95.0, ""},
		{"Eve", 63.0, ""},
	}

	// Automatically assign grades based on scores
	for i := range students {
		switch {
		case students[i].Score >= 90:
			students[i].Grade = "A (Excellent)"
		case students[i].Score >= 80:
			students[i].Grade = "B (Good)"
		case students[i].Score >= 70:
			students[i].Grade = "C (Average)"
		case students[i].Score >= 60:
			students[i].Grade = "D (Pass)"
		default:
			students[i].Grade = "F (Fail)"
		}
	}

	// Print grade report
	fmt.Println("┌─────────┬────────┬────────────┐")
	fmt.Println("│  Name   │ Score  │   Grade    │")
	fmt.Println("├─────────┼────────┼────────────┤")
	var total float64
	for _, s := range students {
		fmt.Printf("│ %-7s │ %6.1f │ %-10s │\n", s.Name, s.Score, s.Grade)
		total += s.Score
	}
	fmt.Println("├─────────┼────────┼────────────┤")
	fmt.Printf("│ Average │ %6.1f │            │\n", total/float64(len(students)))
	fmt.Println("└─────────┴────────┴────────────┘")
}

❓ FAQ

Q1: Which should I use, var or :=? (Conceptual confusion)

A: Follow this simple principle:

Scenario Recommended Reason
Declare and assign inside function := More concise, Go community convention
Declare without assignment inside function var := requires assignment
Package-level variable var := cannot be used outside functions
Need explicit type specification var Avoid unexpected type inference
GO
func example() {
    // ✅ Recommended: use := inside functions
    name := "Go"
    count := 0

    // ✅ Must use var: declare without assignment
    var result string
    if someCondition {
        result = "yes"
    } else {
        result = "no"
    }

    // ✅ Must use var: need exact type
    var b byte = 255 // := would infer as int
}

Q2: Why isn't string(65) equal to "65"? (Common pitfall)

A: string(int) treats the integer as a Unicode code point, not as a text representation of the number:

GO
// ❌ Wrong assumption
s1 := string(65) // Expected "65", actually got "A" (Unicode U+0041)

// ✅ Correct approach
s2 := fmt.Sprintf("%d", 65)  // "65"
s3 := strconv.Itoa(65)       // "65" (requires import "strconv")

// Actual use of string(rune): Unicode code point → character
ch := string(rune(8364)) // "€" (U+20AC)

Q3: Why isn't len("Hello,Mundo") equal to 8? (Common pitfall)

A: len() returns the byte count, not the character count. Go strings use UTF-8 encoding by default, and CJK characters occupy 3 bytes each:

GO
s := "Hello,Mundo"
fmt.Println(len(s))          // 11 (5 + 1 + 5 = 11 bytes)
fmt.Println(utf8.RuneCountInString(s)) // 11 (5 + 1 + 5 = 11 characters)

// Correct way to count characters
count := 0
for range s {
    count++
}
fmt.Println(count) // 8

Q4: How do I quickly swap two variables? (Practical tip)

A: Go supports multiple assignment, one line of code does it:

GO
a, b := 10, 20
a, b = b, a // Swap: a=20, b=10

// You can also ignore a value this way
_, err := someFunction() // Use _ to ignore unwanted return value

📖 Summary


📝 Exercises

Exercise 1 (⭐): Variables and Zero Values

Declare the following variables and print their zero values:

Expected output:

TEXT
count: 0
price: 0
active: false
message: ""

Exercise 2 (⭐⭐): iota Enum and Type Conversion

Define a Color type (underlying int), use iota to define three colors: Red=0, Green=1, Blue=2. Implement a String() method for Color. Then:

  1. Declare a Color variable set to Green, print its name and value.
  2. Convert float64 value 3.14159 to int, print the result (should be 3).
  3. Convert number 2025 to string "2025", print the result.

Exercise 3 (⭐⭐⭐): Temperature Conversion Tool

Write a program that does the following:

  1. Define a constant AbsoluteZeroC = -273.15 (absolute zero in Celsius).
  2. Declare a set of Celsius temperatures: -40, 0, 37, 100.
  3. Iterate through the temperature array, converting each Celsius temperature to Fahrenheit (formula: F = C × 9/5 + 32).
  4. Format output as a table, with requirements:
    • Celsius and Fahrenheit temperatures rounded to 1 decimal place
    • Note whether the temperature is below absolute zero (physically impossible)
    • Align column widths

Expected output:

TEXT
┌─────────┬─────────┬────────────┐
│ Celsius │Fahrenheit│   Status   │
├─────────┼─────────┼────────────┤
│  -40.0  │  -40.0  │ Valid      │
│    0.0  │   32.0  │ Valid      │
│   37.0  │   98.6  │ Valid      │
│  100.0  │  212.0  │ Valid      │
└─────────┴─────────┴────────────┘

Hint: Use const, var (array/slice), for loop, fmt.Printf formatting, type conversion (intfloat64).


Next Lesson

Lesson 3: Control Flow — if/else, switch, for loops

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏