Go语言学习 二十九 其他语句
一 终止语句
终止语句可以阻止当前块中其后出现的所有语句的执行,规则如下:
return
或goto
语句。- 调用内置函数
panic
- 语句列表以终止语句结束的块。
if
语句,其中:else
分支存在,并且- 两个分支都是终止语句。
for
语句,其中:- 没有
break
语句引用for
语句,并且 - 循环条件不存在
- 没有
switch
语句,其中:- 没有
break
语句引用switch
语句 - 存在
default
子句,并且 - 在每种case下,包括
default
的语句,以终止语句结束,或者可能标记为fallthrough
语句。
- 没有
select
语句,其中:- 没有
break
语句引用select
语句,并且 - 在每种case下,包括
default
语句(如果存在),以终止语句结束。
- 没有
- 标签语句标记终止的语句
除此之外,所有其他语句都不会终止。
如果语句列表不为空,并且最后一个非空语句终止,则该列表终止。
二 标签语句
标签语句可能是goto
,break
或continue
语句的目标。
Label:
Statement
三 表达式语句
除特定的内建函数外,函数和方法调用,还有接收操作可以出现在语句上下文中。这些语句可以用括号括起来。
语句上下文中不允许使用以下内置函数:
append cap complex imag len make new real
unsafe.Alignof unsafe.Offsetof unsafe.Sizeof
四 赋值
赋值使用=
符号。每个左侧操作数必须是可寻址的、映射索引表达式或空白标识符(仅限=
赋值)。
x = 1
*p = f()
a[i] = 23
(k) = <-ch // 同: k = <-ch
对于赋值操作x op= y
,其中op
是一个二元算数运算符,则其等价于x = x op y
,但是对于x
只进行一次求值。op=
是单个标记。在赋值操作中,左右两边的表达式列表必须只包含一个单值表达式,且左侧表达式不能是空白标识符。
a[i] <<= 2
i &^= 1<<n
元组赋值将多值运算的各个元素分配给变量列表。有两种形式:
第一种,右侧操作数是单个多值表达式,例如函数调用,信道或映射操作,或类型断言。左侧操作数的数量必须与值的数量匹配。例如,如果f
是一个返回两个值的函数。
x, y = f()
将第一个值赋值给x
,第二个赋值给y
。
第二种,左侧操作数个数必须与右侧表达式个数相等,其中右侧表达式必须是单值的,且右侧第n
个表达式将赋值给左侧第n
个变量:
one, two, three = '一', '二', '三'
空白标识符提供了一种方式来忽略赋值过程中右侧的值:
_ = x // 对x求值,但忽略结果
x, _ = f() // 对f()求值,但忽略第二个值
赋值分两个阶段进行。首先,左侧的索引表达式和指针重定向操作(包括选择器中的隐式指针重定向)的操作数和右侧的表达式都按正常的顺序进行求值。其次,赋值按从左到右的顺序进行。
a, b = b, a // 交换a和b
x := []int{1, 2, 3}
i := 0
i, x[i] = 1, 2 // 设置 i = 1, x[0] = 2
i = 0
x[i], i = 2, 1 // 设置 x[0] = 2, i = 1
x[0], x[0] = 1, 2 // 设置 x[0] = 1, 然后 x[0] = 2 (所以最后 x[0] == 2)
x[1], x[3] = 4, 5 // 设置 x[1] = 4, 然后紧接着设置 x[3] = 5.
type Point struct { x, y int }
var p *Point
x[2], p.x = 6, 7 // 设置 x[2] = 6, 然后紧接着设置 p.x = 7
i = 2
x = []int{3, 5, 7}
for i, x[i] = range x { // 设置 i, x[2] = 0, x[0]
break
}
// 该循环之后, i == 0 且 x == []int{3, 5, 3}
在赋值中,每个值必须可分配给它所分配的操作数的类型,另外以下是特例:
- 可以将任何有类型的值分配给空白标识符。
- 如果将无类型常量分配给接口类型的变量或空白标识符,则首先将常量隐式转换为其默认类型。
- 如果将无类型布尔值分配给接口类型的变量或空白标识符,则首先将其隐式转换为
bool
类型。
五 Return语句
函数F
中的return
语句将终止F
的执行,并可选地提供一个或多个结果值。 任何由F
推迟的函数都将在F
返回其调用者之前执行。
在没有结果类型的函数中,return
语句不能指定任何结果值:
func noResult() {
return
}
有三种方式从有结果值的函数中返回值:
返回值可以在
return
中明确指出。每个表达式必须是单值的,且可赋值给函数的结果类型:func simpleF() int { return 2 } func complexF1() (re float64, im float64) { return -7.0, -4.0 }
return
语句中的表达式列表可以是对多值函数的单个调用。就好像从该函数返回的每个值都分配给具有相应值类型的临时变量,然后是列出这些变量的return
语句,此时应用前一个案例的规则。func complexF2() (re float64, im float64) { return complexF1() }
如果函数的结果类型指定其结果参数的名称,则表达式列表可以为空。结果参数充当普通局部变量,并且函数可以根据需要为它们分配值。
return
语句返回这些变量的值: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 }
无论如何声明它们,所有的结果值在进入函数时都将初始化为其类型的零值。指定结果的return
语句在执行任何推迟函数之前设置结果参数。
实现限制:如果与结果参数同名的其他实体(常量,类型或变量)在返回位置的范围内,则编译器可能会在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
语句终止在同一函数内执行最里面的for
,switch
或select
语句。
如果有标签,则必须是包含for
,switch
或select
语句的标签,并且该标签的执行将终止:
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
语句表示开始下一次最内层for
循环的迭代,该for
循环必须在同一个函数中。
如果有标签,那么它必须包含一个for
语句,并且该for
循环即执行进程的标签。
RowLoop:
for y, row := range rows {
for x, data := range row {
if data == endOfRow {
continue RowLoop
}
row[x] = data + bias(x, y)
}
}
八 Goto语句
goto
语句将控制转移到同一个函数内相应的标签语句。
goto Error
执行goto
语句不得导致任何尚未在goto
范围内的变量进入。例如,这个例子是错误的:
goto L // BAD
v := 3
L:
跳转到标签L
会导致跳过v
的创建。
goto
语句只能跳转到同一个函数中的同一个块中,不能跳到其他块,例如,这个例子也是错误的:
if n%2 == 1 {
goto L1 // error
}
for n > 0 {
f()
n--
L1:
f()
n--
}
因为标签L1
在for
语句的块内,但goto
不在。
九 Fallthrough语句
fallthrough
语句将控制转移到表达式switch
语句中的下一个case子句的第一个语句。它可能仅用作此类子句中的最终非空语句。
switch n {
case 1 :
fmt.Println("case 1")
fmt.Println("case 1")
case 2 :
fmt.Println("case 2")
fmt.Println("case 2")
fallthrough
case 3 :
fmt.Println("case 3")
fmt.Println("case 3")
}
版权声明:知识共享署名-非商用-非衍生 (CC BY-NC-ND 3.0) 转载请注明出处