Skip to content

Variables ​

Before You Start

  • Applies to: Go 1.21+ (examples verified with Go 1.22) · Prerequisites: Data Types · Read time: about 6 min

Variables are storage locations that hold values, allowing the stored values to change dynamically at runtime. Each variable declared allocates a piece of memory to store a value of the corresponding type. Visit the Reference Manual - Variables for more details.

Declaration ​

In Go, type declarations come after the variable name. The var keyword is used for variable declaration, with the format var variableName typeName. Variable names must follow the naming rules for identifiers.

go
var intNum int
var str string
var char byte

When declaring multiple variables of the same type, you can write the type only once:

go
var numA, numB, numC int

When declaring multiple variables of different types, you can use parentheses to wrap them, and there can be multiple ().

go
var (
  name    string
  age     int
  address string
)

var (
  school string
  class int
)

If a variable is declared without assignment, the value stored in the variable is the zero value of the corresponding type.

Assignment ​

The assignment operator = is used. For example:

go
var name string
name = "jack"

You can also assign directly when declaring:

go
var name string = "jack"

Or like this:

go
var name string
var age int
name, age = "jack", 1

The second method requires specifying the type each time. You can use the official syntactic sugar: short variable initialization, which omits the var keyword and the trailing type. The specific type is inferred by the compiler.

go
name := "jack" // variable of type string

Although you don't need to specify the type, subsequent assignments must keep the type consistent. The following code cannot compile:

a := 1
a = "1"

It should also be noted that short variable initialization cannot use nil because nil does not belong to any type, and the compiler cannot infer its type.

go
name := nil // cannot compile

Short variable declarations can be batch initialized:

go
name, age := "jack", 1

The short variable declaration method cannot be used on an already existing variable:

go
// Wrong example
var a int
a := 1

// Wrong example
a := 1
a := 2

However, there is one exception: when assigning to an old variable while declaring a new variable at the same time:

go
a := 1
a, b := 2, 2

This code can compile. Variable a is reassigned, while b is newly declared.

In Go, there is a rule that all variables declared inside a function must be used. For example, the code below only declares a variable but does not use it:

go
func main() {
  a := 1
}

It will report a compile-time error, indicating that the variable was declared but not used:

a declared and not used

This rule only applies to variables inside functions. For package-level variables outside functions, there is no such restriction. The following code can compile:

go
var a = 1

func main() {

}

Anonymous ​

You can use an underscore to indicate that a certain variable is not needed:

go
Open(name string) (*File, error)

For example, the os.Open function has two return values. If we only want the first one and not the second, you can write it as follows:

go
file, _ := os.Open("readme.txt")

Unused variables cannot compile. When you don't need a certain variable, you can use underscore _ instead.

Swap ​

In Go, if you want to swap the values of two variables, you don't need to use pointers. You can swap directly using the assignment operator. The syntax looks very intuitive:

go
num1, num2 := 25, 36
num1, num2 = num2, num1

The same applies to three variables:

go
num1, num2, num3 := 25, 36, 49
num1, num2, num3  = num3, num2, num1

Consider the following code snippet, which is part of calculating the Fibonacci sequence. What are the values of the three variables after calculation?

go
a, b, c := 0, 1, 1
a, b, c = b, c, a+b

The answer is:

1 1 1

You might wonder why it's not:

1 1 2

Why was a assigned the value of b, but the result of a+b is still 1? When Go performs multiple variable assignment operations, it calculates the values first and then assigns them, not from left to right.

go
a, b, c = b, c, a+b

You might think it would be expanded to:

go
a = b
b = c
c = a + b

But actually, it calculates the values of a, b, and c first and then assigns them, which is equivalent to:

go
a, b, c = 1, 1, 0+1

When function calls are involved, this effect is more obvious. We have a function sum that returns the sum of two numbers:

go
func sum(a, b int) int {
  return a + b
}

Performing two-number addition through the function:

go
a, b, c := 0, 1, 1
a, b, c = b, c, sum(a, b)

The result does not change. When calculating the return value of the sum function, its input parameters are still 0 and 1:

1 1 1

So the code should be written separately:

go
a, b = b, c
c = a + b

Comparison ​

There is a major prerequisite for comparing variables: their types must be the same. Go does not have implicit type conversion. The following code cannot compile:

go
func main() {
  var a uint64
  var b int64
  fmt.Println(a == b)
}

The compiler will tell you that the types do not match:

invalid operation: a == b (mismatched types uint64 and int64)

Therefore, you must use explicit type conversion:

go
func main() {
  var a uint64
  var b int64
  fmt.Println(int64(a) == b)
}

Before generics were available, the early Go built-in min and max functions only supported floating-point numbers. In version 1.21, Go finally rewrote these built-in functions using generics. Now you can use the min function to compare minimum values:

go
minVal := min(1, 2, -1, 1.2)

Use the max function to compare maximum values:

go
maxVal := max(100, 22, -1, 1.12)

Their parameters support all comparable types. The comparable types in Go are:

  • Booleans
  • Numbers
  • Strings
  • Pointers
  • Channels (only supports checking equality)
  • Arrays of comparable types (slices are not comparable) (only supports checking equality) (only supports comparison between arrays of the same length, because array length is also part of the type, and different types cannot be compared)
  • Structs where all field types are comparable (only supports checking equality)

In addition, you can also import the standard library cmp for comparison, but it only supports ordered type parameters. In Go, the built-in ordered types are only numbers and strings.

go
import "cmp"

func main() {
  cmp.Compare(1, 2)
  cmp.Less(1, 2)
}

Code Blocks ​

Inside a function, you can create a code block using curly braces. The variable scopes between code blocks are independent of each other. For example:

go
func main() {
  a := 1

  {
    a := 2
    fmt.Println(a)
  }

  {
    a := 3
    fmt.Println(a)
  }
  fmt.Println(a)
}

Output:

2
3
1

Variables between blocks are independent of each other, not interfered with, cannot be accessed, but can be affected by the parent block.

go
func main() {
  a := 1

  {
    a := 2
    fmt.Println(a)
  }

  {
    fmt.Println(a)
  }
  fmt.Println(a)
}

Output:

2
1
1

Complete Example ​

The program below runs as-is: copy it into a file and execute go run main.go, or paste it into the Go Playground.

go
package main

import "fmt"

func main() {
	var a int = 1
	var b = 2         // type inferred as int
	c := 3            // short declaration (functions only)
	var d, e = 4, "5" // multiple variables in one statement

	fmt.Println(a, b, c, d, e)

	// Swapping two variables without a temporary variable
	x, y := 1, 2
	x, y = y, x
	fmt.Println(x, y)

	// Zero values: variables are always initialized
	var zeroInt int
	var zeroStr string
	var zeroBool bool
	fmt.Printf("zero values: %d %q %v\n", zeroInt, zeroStr, zeroBool)
}

Expected output:

text
1 2 3 4 5
2 1
zero values: 0 "" false

Common Pitfalls ​

  • Short declarations cannot be used at package level. := is only allowed inside functions; at package scope use var.
  • Unused local variables are compile errors. declared and not used — remove the variable or use _.
  • Swapping already-declared variables uses =, not :=. With :=, the compiler reports no new variables on left side of := when both variables already exist in the same scope.
  • Shadowing is silent. An inner x := ... creates a new variable; a common bug is assigning to a shadowed err inside an if block and then checking the outer one.
  • Type mismatches need an explicit conversion. var n int = "3" does not compile; use strconv.Atoi or an explicit conversion such as int64(n).

Change Log ​

  • 2026-10-14: Added "Before You Start" notes, a complete runnable example with expected output, common pitfalls, and this change log.

Golang by www.golangdev.cn · Adapted in part from Golang 中文学习文档 (MIT, © 寒江蓑笠翁)