Go语言学习 七 流程控制之if-else
Go中关于流程控制方面主要有if-else
,for
循环,switch
。另外,Go中还多了一种新的控制结构select
,这种结构包含一个类型开关和一个多路通信复用器;if
和switch
接受类似for
的可选初始化语句;break
,continue
和goto
语句采用可选标签来标识要中断或继续以及要跳转的内容;与C相比,Go的控制结构语法也有些区别:没有小括号,并且控制体必须包含在一对大括号中。
关于select的用法,将在后续关于并发的文章中讲。
一 if语句
if表达式外无需小括号 ( )
,而大括号 { }
则是必须的。强制使用大括号是为了鼓励将简单的if
语句拆分成多行。这是一个好习惯,特别是当控制体中包含return
或break
语句时。
在Go中,一个简单的if
语句如下:
if x > 0 {
return y;
}
示例:
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(sqrt(16))
fmt.Println(sqrt(-9))
}
func sqrt(x float64) string {
if x < 0 {
return sqrt(-x) + "i"
}
return fmt.Sprint(math.Sqrt(x))
}
二 简短语句
if 语句可以在条件表达式前执行一个简单的语句。该语句声明的变量作用域仅在 if 之内。
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 3, 20),
)
}
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
}
// return v // 错误:undefined: v
return lim
}
上述示例中的第16行中,语句v := math.Pow(x, n)
会优先求值。然后再拿结果进行比较。
类比一下:Java中类似语法可以这样写:
int r; if ((r = Math.round(x) > 0) { return r; }
在 if 的简短语句中声明的变量同样可以在任何对应的 else 块中使用。
例如,将上述示例中的pow
函数改为:
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
} else {
fmt.Printf("pow(%v, %v, %v)超出lim参数范围,结果将被截取为%v\n", x, n, lim, lim)
}
// return v // 错误:undefined: v
return lim
}
在Go中,如果if
语句之后没有进入下一个语句,则意味着该if
控制体中最后一行是 break
、continue
、goto
或者return
(这里省略了非必须的else
语句):
f, err := os.Open(name)
if err != nil {
return err
}
codeUsing(f)
联想:在Java中,break
、continue
只能出现在循环体中,而goto
是保留关键字。
下面是一种常见的情况,其中代码必须处理防止一系列错误。由于错误情况将以return语句结束,因此之后的代码不需要else语句。
f, err := os.Open(name)
if err != nil {
return err
}
d, err := f.Stat()
if err != nil {
f.Close()
return err
}
codeUsing(f, d)
类比一下:这种做法在Java和其他语言中也很常见,避免过多的if-else
嵌套。
三 重新声明和重新赋值
上一节中的最后一个示例演示了:=
简短声明的工作原理。调用os.Open
的声明:
f, err := os.Open(name)
该语句声明了两个变量f
和err
。几行之后,调用f.Stat
:
d, err := f.Stat()
看起来好像是声明了d
和err
。但请注意,err
出现在两个语句中。这种重复是合法的:err
是由第一个语句声明的,但在第二个语句中仅是重新赋值而已。这意味着对f.Stat
的调用使用上面声明的现有err
变量,并只是给它一个新值。
在:=
声明中,即使已经声明变量v
,也可能再次出现变量v
,前提是:
- 此声明与
v
的现有声明在同一范围内(如果v
已在外部作用域中声明,当前声明将创建一个新变量) - 初始化中的相应的值可分配给
v
,并且 - 声明中至少有一个其他变量是新声明的。
这种特殊的特性纯粹是为了实用,能够简单的复用同一个变量,而且这种用法很常见。
值得注意的是,在Go中,函数参数和返回值的作用域范围与函数体相同,即使它们在大括号之外的词法上出现。
参考:
https://golang.org/doc/effective_go.html#if
https://golang.org/ref/spec#If_statements
版权声明:知识共享署名-非商用-非衍生 (CC BY-NC-ND 3.0) 转载请注明出处