SoFunction
Updated on 2025-03-05

Go language variable definition details

1. Variables

Declare variables

The way go to define variables is different from c, c++, and java syntax.as follows:

var variable name type, for example:var a int

var is first, variable name is middle, type is after

Let's use the code as follows:

var i int = 0
var i = 0
var i int

All the above three expressions are legal. The third expression will initialize i to a zero value of type int, 0; if i is bool type, it is false; if i is float64 type, it is 0.0; i isstringType, it is ""; i is interface type, it is nil; i is reference type, it is nil; if i is struct, it is initialized to all fields in struct as zero values ​​of the corresponding type.

This initialization mechanism can ensure that any variable has an initial value, so you don’t need to worry about the uninitialized value when checking boundary conditions. It can avoid some potential errors. I believe that C and C++ programmers have a deeper understanding.

(s) // ""

The s here can be printed normally, rather than causing some unpredictable error.

Multiple variables can be declared in the same statement:

var b, f, s = true, 2.3, "four"// bool, float64, string

The variables visible in the package aremainThe function is initialized before execution, and the local variable is initialized when the function is executed to the corresponding declaration statement.

Variables can also be initialized by the return value of the function:

var f, err = (name) //  returns a file and an error

2. Short statement

Inside the function, there is a way to declare it in the formname := expression, Here, the type of the variable is automatically determined by the compiler.

anim := {LoopCount: nframes}
freq := rand.Float64() * 3.0
t := 0.0

Because this form is very concise, it is used extensively inside functions (local variables). If you need to explicitly specify the type for the local variable, or declare a variable before assigning a value,Then you should use var:

i := 100// an int
var boiling float64 = 100// a float64
var names []string
var err error
var p Point

Just like var declarations, short declarations can also be initialized in parallel.

i, j := 0, 1

It should be kept in mind that := is a declaration and = is an assignment, so it cannot be used in places where assignment is required.

var i int
i := 10//panic : no new variables on left side of :=

Value exchange can be performed using the characteristics of parallel assignment:

i, j = j, i // swap values of i and j

One thing to note: the variables on the left side of the short statement may not be all new statements! :

//...
out, err := (path2) 

/Because err has been declared, only one new variable out is declared here.

Although := is used here, err is declared in the previous statement, here is just assignment/

Moreover, there must be one of the variables on the left of the short declaration that are new,If all of them have been declared before, a compilation error will be reported:

f, err := (infile)
// ...
f, err := (outfile) // compile error: no new variables

The correct way to write it is like this:

f, err := (infile)
// ...
f, err = (outfile) // compile ok

pointer

The value variable stores a value. For example, x = 1 means that the value 1 is stored at the storage address of x; x[i] = 1 means that the value 1 is stored at the i + 1th position of the array; = 1 means that the value 1 is stored at the storage location where the f field in struct x is located.

The pointer value is the storage address of a variable. Note: Not all values ​​have addresses, but variables must have addresses! This concept must be clarified! Through pointers, we can access a variable indirectly, without even knowing the variable name.

var x int = 10
p := &x 
/*&x is the address of the x variable, so p is a pointer pointing to the x variable.
 Here the type of p is *int, which means a pointer to int*/
("addr:%p, value:%d\n", p, *p)
//output: addr:0xc820074d98, value:10
*p = 20// renewxarrive20

In the above code, we say that p points to x or p contains the address of x. p means to take out the corresponding variable value from the p address, so p is the value of x: 10. Because p is a variable, it can be used as an lvalue, p = 20, which means that the value in the p address is updated to 20, so x will become 20 here. The following example also fully explains the role of pointers:

x := 1
p := &x         // p type: *int, pointing to x(*p) // "1"
*p = 2// Equivalent to x = 2(x)  // "2"

Aggregation typestructorarrayThe elements in it are also variables, so pointers can be obtained by addressing (&).

If a value is a variable, then it is addressable. Therefore, if an expression can be used as a variable, it means that the expression can be addressable or used by the & operator.

The zero value of the 'pointer is nil (remember what happened before? All types of go will be initialized to the zero value of that type by default if there is no initial value). If p points to a variable, then p != nil is true, because p will be assigned the address of the variable. Pointers are comparable, and two pointers equal means that both pointers point to the same variable or both pointers are nil.

var x, y int
(&x == &x, &x == &y, &x == nil) // "true false false"    

It is safe to return the address of a local variable in a function. For example, the following code, the local variable v is created in f, and it will still exist after returning from f, and the pointer p will still refer to v:

var p = f()
(*p) //output:1
func f() *int{
    v := 1
return &v
}

Each time f is called, a different pointer is returned, because f creates a new local variable and returns a pointer:

(f() == f()) // "false"
Pass the pointer of the variable to the function,That is, the variable can be modified inside the function(goThe default function is value passing,All value types will be copied in memory)。

func incr(p *int)int{
        *p++ // increments what p points to; does not change p
return *p
}
v := 1
incr(&v)              // v is now 2(incr(&v)) // "3" (and v is 3)

Pointers are important in flag packages. flag will read the parameters of the program command line and then set variables inside the program. In the following example, we have two command line parameters: -n, which does not print newlines;-s sep, print using a custom string separator.

package main
import(
"flag"
"fmt"
"strings"
)
var n = ("n", false, "Ignore newlines")
var sep = ("s", " ", "Separator")
func main(){
    ()
    (((), *sep))
if !*n {
          ()
    }
}

A bool-type flag variable will be created, with three parameters: the name of the flag, the default flag value (false) when the command line does not pass the value, and the description information of the flag (when the user passes an illegal parameter or -h or -help, the description information will be printed). The variables sep and n are pointers to flag variables, so the original flag value must be accessed through sep and n.

When the program is running, it is called first before using the flag value. Non-flag parameters can be accessed through args := (), the type of args is []string (see subsequent chapters). ifIf an error is reported, the program will print out a instructions for use and call (2) to end.

Let's test the above program:

$ go build /ch2/echo4
$ ./echo4 a bc def
a bc def
$ ./echo4 -s / a bc def
a/bc/def
$ ./echo4 -n a bc def
a bc def$
$ ./echo4 -help
Usage of ./echo4:
     -n    Ignore line breaks
     -s string
     Delimiter (default" ")

3. new function

It can also be built-in(built-in)Function new to create variables. new(T) will initialize a variable of type T, the value is the zero value corresponding to type T, and then return a pointer: *T.

p := new(int)   // p, type *int, point to an unnamed int variable(*p) // "0"
*p = 2
(*p) // "2"

This declaration method is no different from the ordinary var declaration and then the address is retrieved.If you don't want to rack your brain to think about a variable name, then you can use new:

func newInt() *int{            func newInt() *int{
returnnew(int)                 var dummy int
}                                   return &dummy
                                }

Each time new is called returns a unique address:

p := new(int)
q := new(int)
(p == q) // "false"

But there is an exception: for example, struct{} or [0]int, variables of this type do not contain any information and have zero values, and may have the same address.

New functions are relatively rarely used because the most commonly used unnamed variables arestructTypes, for this type, the corresponding struct syntax is more flexible and more suitable.

Because new is a predefined function name (see the reserved word in the previous section) and is not a language keyword, you can use new as the variable name in the function:

func delta(old, new int)int{ returnnew - old }

Of course, inside the delta function, the new function can no longer be used!

4. The life period of variables

The life period of a variable is the survival period of a variable during program execution. The lifespan of variables visible in the package is fixed: the entire execution period of the program. For comparison, the lifespan of a local variable is dynamic: each time a declaration statement is executed, a new variable instance is created, and the lifespan of a variable is the time period from creation to the unreachable state (see below). After the lifespan ends, the variable may be recycled.

Function parameters and local variables are dynamic lifespans, and these variables are created every time the function is called and executed.For example, the following code:

for t := 0.0; t < cycles*2*; t += res {
    x := (t)
    y := (t*freq + phase)
    (size+int(x*size+0.5), size+int(y*size+0.5),
          blackIndex)
    }

Each time the for loop is executed, t, x, y will be recreated.

So how does GC determine that a variable should be recycled? A complete mechanism is very complex, but the basic idea is to find the process path of each variable. If such a path cannot be found, then the variable is inaccessible and therefore can be recycled.

The life span of a variable only depends on whether the variable is reachable, so a local variable can survive outside the loop, or even after the function returns. The compiler will choose to allocate variables on the heap or stack, but remember: the choice of the compiler is not determined by declaration methods such as var or new.

var global *int
func f() {                      func g(){
    var x int                       y := new(int)
    x = 1                           *y = 1
    global = &x                 }
}

In the above code, x is a variable allocated on the heap, because after f returns, x is also arrivable (global pointer). Here x is the local variable of f, so here we say that x escapes from f. On the contrary, when g returns, the variable y becomes unreachable and then it is garbage collected. Because y does not escape from g, the compiler allocates *y on the stack (even if it is allocated with new). In most cases, we don’t have to worry about variable escape, just realize when doing performance optimization: every escaped variable needs to be allocated extra memory.

Although automatic GC is a huge help for writing modern programs, we also need to understand the memory mechanism of the Go language. Programs do not require explicit memory allocation or recycling, but in order to write efficient programs, we still need to clearly know the life period of variables. For example, holding a pointer to a short-term object in a long-term object (especially global variables) will prevent GC from reclaiming these short-term objects because in this case, short-term objects are reachable! !

V. Scope of variables

If you have experience in c, c++, and java, then the domain name of the go language variables is the same as these languages.

In a word: The principle of proximity, variables defined in scope can only be used in functions.

If there is a variable with the same name defined outside, the proximity principle is.

This is the end of this article about the detailed definition of variable definition in Go. For more relevant Go variable definition content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!