Variables
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.
var intNum int
var str string
var char byteWhen declaring multiple variables of the same type, you can write the type only once:
var numA, numB, numC intWhen declaring multiple variables of different types, you can use parentheses to wrap them, and there can be multiple ().
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:
var name string
name = "jack"You can also assign directly when declaring:
var name string = "jack"Or like this:
var name string
var age int
name, age = "jack", 1The 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.
name := "jack" // variable of type stringAlthough 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.
name := nil // cannot compileShort variable declarations can be batch initialized:
name, age := "jack", 1The short variable declaration method cannot be used on an already existing variable:
// Wrong example
var a int
a := 1
// Wrong example
a := 1
a := 2However, there is one exception: when assigning to an old variable while declaring a new variable at the same time:
a := 1
a, b := 2, 2This 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:
func main() {
a := 1
}It will report a compile-time error, indicating that the variable was declared but not used:
a declared and not usedThis rule only applies to variables inside functions. For package-level variables outside functions, there is no such restriction. The following code can compile:
var a = 1
func main() {
}Anonymous
You can use an underscore to indicate that a certain variable is not needed:
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:
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:
num1, num2 := 25, 36
num1, num2 = num2, num1The same applies to three variables:
num1, num2, num3 := 25, 36, 49
num1, num2, num3 = num3, num2, num1Consider the following code snippet, which is part of calculating the Fibonacci sequence. What are the values of the three variables after calculation?
a, b, c := 0, 1, 1
a, b, c = b, c, a+bThe answer is:
1 1 1You might wonder why it's not:
1 1 2Why 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.
a, b, c = b, c, a+bYou might think it would be expanded to:
a = b
b = c
c = a + bBut actually, it calculates the values of a, b, and c first and then assigns them, which is equivalent to:
a, b, c = 1, 1, 0+1When function calls are involved, this effect is more obvious. We have a function sum that returns the sum of two numbers:
func sum(a, b int) int {
return a + b
}Performing two-number addition through the function:
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 1So the code should be written separately:
a, b = b, c
c = a + bComparison
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:
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:
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:
minVal := min(1, 2, -1, 1.2)Use the max function to compare maximum values:
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.
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:
func main() {
a := 1
{
a := 2
fmt.Println(a)
}
{
a := 3
fmt.Println(a)
}
fmt.Println(a)
}Output:
2
3
1Variables between blocks are independent of each other, not interfered with, cannot be accessed, but can be affected by the parent block.
func main() {
a := 1
{
a := 2
fmt.Println(a)
}
{
fmt.Println(a)
}
fmt.Println(a)
}Output:
2
1
1