Go Learning Note Variable declaration

Source: Internet
Author: User

Golang has a number of improvements over the C language in variable declaration, initialization, and assignment statements:

a) support for declaring multiple variables on the same line

var A, b, C int

b) Support for initializing multiple variables on the same line (different types can also)

var A, b, C = 5, "Hello", 3.45
A, B, c: = 5, "Hello", 3.45 (short variable Declaration)

c) Support for assigning multiple variables on the same line (after declaration and different types are possible)

A, B, C = 5, "Hello", 3.45

This syntax sugar we are consultation fee, after all, life is short, less write a line is a line ah ^_^.

But this kind of grammatical sugar has brought us some puzzling problems! For example, here's a question for Rob Pike in a talk slide (Go Course Day2):

N0, n1 = N0 + n1, N0

or:

N0, n1 = OP (n0,n1), N0

N0, how much is the value of N1 after the above statement is executed?

Obviously this problem involves the sentence evaluation order (evaluation order) of the Go language. The Order of evaluation is difficult in any programming language, and in many cases, the answer given by the language specification is "undefined (undefined)" or "not specified" or "dependent implementation", especially with regard to which ambiguous wording, as Rob Pike gives.

To figure out the order of evaluation in go, we need to turn to go language Specification,go spec with Go release, you can start a Godoc Web server (godoc-http= : 6060, then visit localhost:6060/ref/spec) to view Go language specification. Go Language Specification has a special section/ref/spec#order_of_evaluation a description of the order of evaluation.

In Go specs, there are three points in this statement:

1. The evaluation Order (evaluation order) of the initialization expression (initialization expressions) in the variable declaration (variable declaration) is dependent by the initialization (initialization dependencies), but the evaluation of the operands inside the initialization expression needs to be in the order of 2: from left to right;
2. In a non-variable initialization statement, when the operands in an expression, an assignment statement, or a return statement are evaluated, the functions (function) calls, method calls, and communication operations contained in the operands (primarily for channel) are evaluated from left to right in the syntax.
3, the assignment statement evaluation is divided into two stages, the first stage is the index expressions on the left side of the equal sign, the pointer indirections and the expression to the right of the equals sign in the order of evaluation of the operands in 2 from left to right, and the second stage in left-to-right order of the variable assignment.

Let's take a look at these three points separately.

First, the evaluation order of initialization expressions in a variable declaration

The declaration of a variable with an initialization expression is in the following form:

var A, b, C = expr1, expr2, EXPR3//package level or Function/method interior

or

A, B, c: = Expr1, EXPR2, EXPR3//Only inside function/method

According to Lang specs, the order of evaluation is determined by the initialization dependency (initialization dependencies) rule. What is the initialization dependency rule? Golang Specs also has a special section description: Ref/spec#package_initialization.

Summary of initialization dependency rules, roughly the following:

1. In the package, the initialization order of the package-level variables is in order of declaration, but if the initialization expression of a variable (such as a) relies on other variables (such as B), then the initialization order of variable A is followed by the variable B.
2, for uninitialized, and does not contain the corresponding initialization expression or its initialization expression does not depend on any uninitialized variables, we call it "ready for initialization" variable. Initialization is the process of repeating the initialization of the next variable in the order in which it is declared, until there is no "ready for initialization" variable.
3, if the initialization process is still a variable in the uninitialized State, the program has a syntax error.
4. The order in which multiple variables in different files are declared depends on the order in which the compiler processes the files, first processing the variables in the file in the order prior to all the variables in the post-processing file.
5. Dependency analysis is performed in a package, and only dependent variables, functions, and methods in the same package are considered.

Rules are abstract, examples are more intuitive, we look at an example in Golang spec and use the above rules for analysis. Lab environment:go 1.5, Amd64,darwin Kernel Version 13.1.0.

//golang-statements-evaluating-order/example1.go
Package Main

import "FMT"

var (
A = C + b
b = f ()
c = f ()
D = 3
)

func f () int {
d++
Return D
}

Func Main () {
Fmt. Println (A, B, C, D)
}

Let's analyze the result values of a, B, C, and D four variables after the execution of the program, but the initialization order of the four variables is critical because different initialization sequences result in different result values.

The initialization process for variables A, B, C, and D is as follows:

1, according to the rules, initialization according to the variable declaration sequence, so first to analyze the variable a,a initialization expression depends on B and C; So the initialization order of variable A is followed by B and C;
2, according to the initialization of a right-value expression, C, B in the right-hand expression in the order of occurrence is C before B;
3. Is c a ready for initialization variable? We see that C relies on the F function, and the F function relies on the initialization of the variable d, so D is before C;
4, we look at the variable d, "D = 3", D is uninitialized and does not contain an initialization expression, so D is a ready for initialization variable, we can initialize from D. At this point, the initialization sequence of the four variables is scheduled to be a, B, C, A; (This is different from the analysis in spec, but it should be the order from the running result; issue on this spec see #12369)
5, D is initialized to 3, at this time the set of variables initialized [d=3];
6. Then initialize C:C = f (), so C = 4 (at this time d=4), at which time the set of variables is initialized [c=4,d=4];
7, next Turn b:b = f (), so B = 5 (at this time D = 5), at this time the set of variables initialized [b=5,c=4,d=5];
8, the last initialization a:a = C + B, in the set of initialized variables we can find B and C, so a= 9, so that four variables are initialized;
9, after analysis: The result of the program execution should be 9,5,4,5.

Let's execute this procedure to verify that our analysis is correct:

$go Run Example1.go
9 5 4 5

Let's look at an example, and also the example in Golang specs, and we'll change it a bit and set it to example2:

//golang-statements-evaluating-order/example2.go
Package Main

import "FMT"

var A, b, C = f () + V (), G (), Sqr (U ()) + V ()

func f () int {
Fmt. PRINTLN ("Calling F")
Return C
}

func g () int {
Fmt. Println ("Calling G")
Return a
}

func sqr (x int) int {
Fmt. Println ("Calling Sqr")
return x * x
}

func V () int {
Fmt. Println ("Calling V")
Return 1
}

func u () int {
Fmt. Println ("Calling U")
Return 2
}

Func Main () {
Fmt. Println (A, B, c)
}

This example is also analyzed based on the variable initialization dependency rule:

1, according to the variable declaration order, first initialize a:a= f () + V (), f () dependent variable c;v does not depend on any variables, so the initialization order of variable C should be before a variable: C-A.
2, Analysis c:c = SQR (U ()) + V (), u, SQR, v three functions do not depend on any variables, so C is in ready for initialization, so C is initialized, function execution order (left to right) is: U (), Sqr () V (); The set of variables is initialized: [c = 5];
3, back to a:a = f () + V (), after C is initialized, a also processes the ready for initialization, so for a initialization, the function execution order is: f (), V (), at this time the set of variables initialized: [C=5, a= 6];
4, according to the variable declaration order, the next turn to the variable b:b= g (), and g () dependent a,a has been initialized, so B is ready for initialization, so the B initialization, function execution order is: g (), so that the set of variables initialized: [C=5, A= 6, b=6].
5, after analysis: The result of the program execution should be 6,6,5.

Let's execute this procedure to verify that our analysis is correct:

$go Run Example2.go
Calling U
Calling Sqr
Calling V
Calling F
Calling V
Calling G
6 6 5

second, the Order of evaluation in non-variable initialization statements

As mentioned earlier: in non-variable initialization statements, when the operands in an expression, an assignment statement, or a return statement are evaluated, the functions (function) calls, method calls, and communication operations contained in the operand (primarily for channel) are The order is evaluated from left to right .

We also look at an example:example3.go.

//golang-statements-evaluating-order/example3.go
Package Main

import "FMT"

func f () int {
Fmt. PRINTLN ("Calling F")
Return 1
}

func g (A, B, c int) int {
Fmt. Println ("Calling G")
Return 2
}

func h () int {
Fmt. PRINTLN ("Calling H")
Return 3
}

func i () int {
Fmt. PRINTLN ("Calling i")
Return 1
}

func J () int {
Fmt. Println ("Calling J")
Return 1
}

func K () bool {
Fmt. Println ("Calling K")
return True
}

Func Main () {
var y = []int{11, 12, 13}
var x = []int{21, +, +}

var c chan int = make (chan int)
Go func () {
C <-1
}()

y[f ()], _ = G (h (), I () +x[j ()], <-c), K ()

FMT. Println (y)
}

y[f ()], _ = G (h (), I () +x[j ()], <-c), K () This line of statements is an assignment statement, but the operands of an assignment statement include function calls, channel operations, and, by rule, these function calls, Channel operations are valued in order from left to right.

1, according to the order from left to right, the first one is Y[f ()] in the f ();
2, followed by G (), the parameter list of G () is still an assignment operation, so it involves the sequence of functions called H (), I (), J (), <-c, so the actual order is H () –> I () –> J () –> C operation, G ();
3, the last is K (), so the complete invocation order is: f (), h () –> I () –> J () –> C operations, G () –> K ().

The actual operating conditions are as follows:

$go Run Example3.go
calling F
Calling H
Calling I
Calling J
Calling G
Calling K
[2]

Three, the evaluation order of assignment statements

Let's go back to the front. Rob Pike that question:

N0, n1 = N0 + n1, N0

or:

N0, n1 = OP (n0, N1), N0

This is an assignment statement, according to Rule 3, our operands to the expression at both ends of the equals sign take the order of evaluation from left to right.

we assume the initial value:
N0, N1 = 1, 2

1, the first stage: the expression evaluation of the two ends, the above problem, only the right side has n0+n1 and n0 two expressions, but the expression of the operand (n0,n1) is initialized, so directly bring the value into, get the evaluation result. After evaluation, the statement can be considered as: n0, n1 = 3, 1;
2, the second stage: assignment value. N0 =3, n1 = 1

// Golang-statements-evaluating-order/example4.go
Package Main

import "FMT"

func example1 () {
N0, N1: = 1, 2
N0, N1 = n0+n1, N0
Fmt. Println (N0, N1)
}

func op (A, b int) int {
Return a + b
}

func example2 () {
N0, N1: = 1, 2
N0, N1 = OP (n0, N1), N0
Fmt. Println (N0, N1)
}

Func Main () {
Example1 ()
Example2 ()
}

$go Run Example4.go
3 1
3 1

Iv. Summary

Although we understand the rules, we try not to write things like:"var A, B, C = f () + V (), G (), Sqr (U ()) + V ()" complex, difficult to understand statements. If necessary, split into multiple lines is good, you can also add some code (if your company is in code to evaluate the performance of one of the indicators), get forgive and forgive Ah, burn the sentence or try to avoid as good.

Go Learning Note Variable declaration

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.