go的状态语句

Statement =
    Declaration | LabeledStmt | SimpleStmt |
    GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
    FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
    DeferStmt .

SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .

终止语句(Terminating statements)

终止语句是指下的情况:

return
goto
调用内置函数panic(interface{})
if语句以及else语句中语句的结束
for语句语句的结束
switch语句语句
select
labeled 

空白语句(Empty statements)

空白语句不做任何事情:

EmptyStmt = .

标记语句(Labeled statements)

标记语句可以是goto、break、continue的目标。

LabeledStmt = Label ":" Statement .
Label       = identifier .

表达式语句(Expression statements)

除了下面的内置函数,其它的函数、方法和接收操作符都可以用于表达式语句。

append cap complex imag len make new real
unsafe.Alignof unsafe.Offsetof unsafe.Sizeof

发送语句(Send statements)

发送语句是专用于向通道(channel)发送数据的。

SendStmt = Channel "<-" Expression .
Channel  = Expression .

递增递减语句(IncDec statements)

IncDecStmt = Expression ( "++" | "--" ) .

赋值语句(Assignments)

Assignment = ExpressionList assign_op ExpressionList .
assign_op = [ add_op | mul_op ] "=" .

if语句(If statements)

IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] .

switch语句(Switch statements)

switch语句分为以表达式为依据,和以类型为依据两种形式。

SwitchStmt = ExprSwitchStmt | TypeSwitchStmt .

使用表达式作为分支依据:

ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ExprCaseClause } "}" .
ExprCaseClause = ExprSwitchCase ":" StatementList .
ExprSwitchCase = "case" ExpressionList | "default" .

例如:

switch tag {
default: s3()
case 0, 1, 2, 3: s1()
case 4, 5, 6, 7: s2()
}

switch x := f(); {  // missing switch expression means "true"
case x < 0: return -x
default: return x
}

switch {
case x < y: f1()
case x < z: f2()
case x == 4: f3()
}

使用类型为依据:

TypeSwitchStmt  = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" .
TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
TypeCaseClause  = TypeSwitchCase ":" StatementList .
TypeSwitchCase  = "case" TypeList | "default" .
TypeList        = Type { "," Type } .

例如:

switch i := x.(type) {
case nil:
    printString("x is nil")                // type of i is type of x (interface{})
case int:
    printInt(i)                            // type of i is int
case float64:
    printFloat64(i)                        // type of i is float64
case func(int) float64:
    printFunction(i)                       // type of i is func(int) float64
case bool, string:
    printString("type is bool or string")  // type of i is type of x (interface{})
default:
    printString("don't know the type")     // type of i is type of x (interface{})
}

for语句(For statements)

for的语句循环条件有三种。

ForStmt = "for" [ Condition | ForClause | RangeClause ] Block .
Condition = Expression .

简略条件判断:

for a < b {
    a *= 2
}

完整条件判断:

ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] .
InitStmt = SimpleStmt .
PostStmt = SimpleStmt .

例如:

for i := 0; i < 10; i++ {
    f(i)
}

for cond { S() }    is the same as    for ; cond ; { S() }
for      { S() }    is the same as    for true     { S() }

range判断:

RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" Expression .

需要特别注意的是Expression不同时,range Expression的返回值不同。

Range expression                          1st value          2nd value

array or slice  a  [n]E, *[n]E, or []E    index    i  int    a[i]       E
string          s  string type            index    i  int    see below  rune
map             m  map[K]V                key      k  K      m[k]       V
channel         c  chan E, <-chan E       element  e  E

go语句(Go statements)

Stmt = "go" Expression .

select语句(Select statements)

select语句用于执行当前可以执行的语句。

SelectStmt = "select" "{" { CommClause } "}" .
CommClause = CommCase ":" StatementList .
CommCase   = "case" ( SendStmt | RecvStmt ) | "default" .
RecvStmt   = [ ExpressionList "=" | IdentifierList ":=" ] RecvExpr .
RecvExpr   = Expression .

如果有多个语句当前都可以执行,需要特别注意这些语句的执行顺序。

1. 通道(channel)相关的语句如果同时进入可执行状态,只执行在源码中位置靠前的语句
2. 如果多个语句可以执行,随机选择一个执行。
3. 如果所有语句都不能执行,那么执行default语句,如果没有default语句,进入等待状态

例如:

var a []int
var c, c1, c2, c3, c4 chan int
var i1, i2 int
select {
case i1 = <-c1:
    print("received ", i1, " from c1\n")
case c2 <- i2:
    print("sent ", i2, " to c2\n")
case i3, ok := (<-c3):  // same as: i3, ok := <-c3
    if ok {
        print("received ", i3, " from c3\n")
    } else {
        print("c3 is closed\n")
    }
case a[f()] = <-c4:
    // same as:
    // case t := <-c4
    //    a[f()] = t
default:
    print("no communication\n")
}

for {  // send random sequence of bits to c
    select {
    case c <- 0:  // note: no statement, no fallthrough, no folding of cases
    case c <- 1:
    }
}

select {}  // block forever

返回语句(Return statements)

ReturnStmt = "return" [ ExpressionList ] .

例如:

func simpleF() int {
    return 2
}

支持多值返回:

func complexF1() (re float64, im float64) {
    return -7.0, -4.0
}

可以直接将表达式的结果返回:

func complexF2() (re float64, im float64) {
    return complexF1()
}

还可以命名返回:

func complexF3() (re float64, im float64) {
    re = 7.0
    im = 4.0
    return
}

func (devnull) Write(p []byte) (n int, _ error) {
    n = len(p)
    return
}

命名的返回的时候,不同有同名的其它变量:

func f(n int) (res int, err error) {
    if _, err := f(n-1); err != nil {
        return  // invalid return statement: err is shadowed
    }
    return
}

break语句(Break statement)

BreakStmt = "break" [ Label ] .

例如:

OuterLoop:
    for i = 0; i < n; i++ {
        for j = 0; j < m; j++ {
            switch a[i][j] {
            case nil:
                state = Error
                break OuterLoop
            case item:
                state = Found
                break OuterLoop
            }
        }
    }

continue语句(Continue statements)

ContinueStmt = "continue" [ Label ] .

例如:

RowLoop:
	for y, row := range rows {
		for x, data := range row {
			if data == endOfRow {
				continue RowLoop
			}
			row[x] = data + bias(x, y)
		}
	}

goto语句(Goto statements)

GotoStmt = "goto" Label .

使用goto的时候要特别注意,不要在goto与Label直接存在变量的声明。

例如下面的做法符合语法要求,但是容易造成混乱,在L:之后的位置使用i,会报错:

	goto L  // BAD
	v := 3
L:

goto只能跳转到所在区块中的标记位置。

例如下面的做法是不符合语法的,L1是另一个区块中的标记。

if n%2 == 1 {
	goto L1
}
for n > 0 {
	f()
	n--
L1:
	f()
	n--
}

fallthrough语句(Fallthrough statements)

fallthrouch用于switch语句中,表示紧邻的下一个语句需要被执行。

FallthroughStmt = "fallthrough" .

defer语句(Defer statements)

defer表示跟随的语句需要在函数执行结束的时候执行。

DeferStmt = "defer" Expression .

例如:

lock(l)
defer unlock(l)  // unlocking happens before surrounding function returns

// prints 3 2 1 0 before surrounding function returns
for i := 0; i <= 3; i++ {
	defer fmt.Print(i)
}

// f returns 1
func f() (result int) {
	defer func() {
		result++
	}()
	return 0
}

参考

  1. go Lexical elements