Go Language Variables
Variables originate from mathematics and are abstract concepts in computer languages that can store calculation results or represent values.
Variables can be accessed through variable names.
Go language variable names consist of letters, numbers, and underscores, with the first character not being a number.
The general form of declaring a variable is using the var
keyword:
var identifier type
Multiple variables can be declared at once:
var identifier1, identifier2 type
Example
package main
import "fmt"
func main() {
var a string = "tutorialpro"
fmt.Println(a)
var b, c int = 1, 2
fmt.Println(b, c)
}
The output of the above example is:
tutorialpro
1 2
Variable Declaration
First, specify the variable type. If not initialized, the variable defaults to zero value.
var v_name v_type
v_name = value
The zero value is the value set by the system when the variable is not initialized.
Example
package main
import "fmt"
func main() {
// Declare a variable and initialize
var a = "tutorialpro"
fmt.Println(a)
// Not initialized, defaults to zero value
var b int
fmt.Println(b)
// Bool zero value is false
var c bool
fmt.Println(c)
}
The execution result of the above example is:
tutorialpro
0
false
-
Numeric types (including complex64/128) are 0
-
Boolean type is false
-
String is "" (empty string)
-
The following types are nil:
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error is an interface
Example
package main
import "fmt"
func main() {
var i int
var f float64
var b bool
var s string
fmt.Printf("%v %v %v %q\n", i, f, b, s)
}
The output is:
0 0 false ""
Second, determine the variable type based on the value.
var v_name = value
Example
package main
import "fmt"
func main() {
var d = true
fmt.Println(d)
}
The output is:
true
Third, if the variable has already been declared using var
, using :=
to declare the variable will result in a compilation error. The format is:
v_name := value
For example:
var intVal int
intVal :=1 // This will cause a compilation error because intVal has already been declared
Simply use the following statement:
intVal := 1 // This will not cause a compilation error because a new variable is declared, as `:=` is a declaration statement
intVal := 1
is equivalent to:
var intVal int
intVal =1
The statement var f string = "tutorialpro"
can be simplified to f := "tutorialpro"
:
Example
package main
import "fmt"
func main() {
f := "tutorialpro" // var f string = "tutorialpro"
fmt.Println(f)
}
The output is:
tutorialpro
Multiple Variable Declaration
// Multiple variables of the same type, not global
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3 // Similar to Python, no need to explicitly declare the type, automatically inferred
vname1, vname2, vname3 := v1, v2, v3 // Variables on the left of `:=` should not have been declared before, otherwise it will cause a compilation error
// This keyword factorization style is generally used for declaring global variables
var (
vname1 v_type1
vname2 v_type2
)
Example
package main
var x, y int
var ( // This notation for factoring keywords is typically used to declare global variables
a int
b bool
)
var c, d int = 1, 2
var e, f = 123, "hello"
// This format without declaration can only appear within function bodies
// g, h := 123, "hello"
func main() {
g, h := 123, "hello"
println(x, y, a, b, c, d, e, f, g, h)
}
The output of the above example is:
0 0 0 false 1 2 123 hello 123 hello
Value Types and Reference Types
Basic types such as int, float, bool, and string are all value types, where variables of these types directly point to values stored in memory:
When a variable is assigned to another using the equals sign =
, such as j = i
, a copy of the value of i
is made in memory:
You can obtain the memory address of variable i
using &i
, for example: 0xf840000040
(the address may vary each time).
The values of value type variables are stored in the heap.
Memory addresses can differ between machines, and even the same program executed on different machines may result in different memory addresses. This is because each machine may have a different memory layout and allocation scheme.
More complex data often requires multiple words and is generally stored using reference types.
A reference type variable like r1
stores the memory address (a number) where the value of r1
is located, or the location of the first word in the memory address.
This memory address is called a pointer, which is also stored in another value.
The multiple words pointed to by the same reference type pointer can be in contiguous memory addresses (a contiguous memory layout), which is the most efficient storage form; or they can be scattered in memory, with each word indicating the next word's memory address.
When the assignment statement r2 = r1
is used, only the reference (address) is copied.
If the value of r1
is changed, all references to that value will point to the modified content, and in this example, r2
will also be affected.
Short Form, Using the := Assignment Operator
We know that variable types can be omitted during initialization and inferred by the system. Writing the var
keyword in the declaration statement is somewhat redundant, so we can abbreviate it to a := 50
or b := false
.
The types of a
and b
(int and bool) will be inferred automatically by the compiler.
This is the preferred form for using variables, but it can only be used within function bodies and not for declaring and assigning global variables. Using the :=
operator efficiently creates a new variable, called an initialization declaration.
Notes
Within the same code block, we cannot use the initialization declaration for a variable with the same name more than once, for example, a := 20
is not allowed, and the compiler will prompt an error no new variables on left side of :=
. However, a = 20
is permissible, as it assigns a new value to the same variable.
If you use a variable a
before defining it, you will get a compilation error undefined: a
.
If you declare a local variable but do not use it within the same code block, you will also get a compilation error, such as the variable a
in the following example:
Example
package main
import "fmt"
func main() {
var a string = "abc"
fmt.Println("hello, world")
}
Trying to compile this code will result in the error a declared but not used.
Additionally, simply assigning a value to a
is not enough; the value must be used, so using
fmt.Println("hello, world", a)
will remove the error.
However, global variables are allowed to be declared without being used.
Multiple variables of the same type can be declared on the same line, such as:
var a, b, c int
Multiple variables can be assigned on the same line, such as:
var a, b int
var c string
a, b, c = 5, 7, "abc"
The above line assumes that variables a
, b
, and c
have already been declared; otherwise, it should be used like this:
a, b, c := 5, 7, "abc"
The values on the right are assigned to the variables on the left in the same order, so a
gets the value 5, b
gets 7, and c
gets "abc".
This is called parallel or simultaneous assignment.
If you want to swap the values of two variables, you can simply use a, b = b, a
, and the types of the two variables must be the same.
The blank identifier _
is also used to discard values, such as the value 5 in _, b = 5, 7
.
The _
is essentially a write-only variable, and you cannot get its value. This is done because Go requires all declared variables to be used, but sometimes you don't need to use all the return values from a function.
Parallel assignment is also used when a function returns multiple return values, such as val
and err
obtained simultaneously by calling Func1
: val, err = Func1(var1)
.