控制结构
if-else:
关键字 if 和 else 之后的左大括号 { 必须和关键字在同一行,如果你使用了 else-if 结构,则前段代码块的右大括号 } 必须和 else-if 关键字在同一行。这两条规则都是被编译器强制规定的。
格式如下:
if condition1 {
// do something
} else if condition2 {
// do something else
} else {
// catch-all or default
}
if 可以包含一个初始化语句(如:给一个变量赋值)。这种写法具有固定的格式(在初始化语句后方必须加上分号),例如:
val := 10
if val > max {
// do something
}
你也可以这样写:
if val := 10; val > max {
// do something
}
使用简短方式 := 声明的变量的作用域只存在于 if 结构中(在 if 结构的大括号之间,如果使用 if-else 结构则在 else 代码块中变量也会存在)。如果变量在 if 结构之前就已经存在,那么在 if 结构中,该变量原来的值会被隐藏。(我的理解是相当于声明了一个作用域为条件判断结构的局部变量)
测试多返回值函数的错误
Go 语言的函数经常使用两个返回值来表示执行是否成功:返回某个值以及 true 表示成功;返回零值(或 nil)和 false 表示失败
当不使用 true 或 false 的时候,也可以使用一个 error 类型的变量来代替作为第二个返回值:成功执行的话,error 的值为 nil,否则就会包含相应的错误信息(Go 语言中的错误类型为 error: var err error)
如果我们想要在错误发生的同时终止程序的运行,我们可以使用 os 包的 Exit 函数:
Go
if err != nil {
fmt.Printf("Program stopping with error %v", err)
os.Exit(1)
}
os包的Exit()会直接终止程序。如果在main包中,则使用return就可以终止程序。
switch
相比较 C 和 Java 等其它语言而言,Go 语言中的 switch 结构使用上更加灵活。Go 的 switch 语句类似于 C、C++、Java、JavaScript 和 PHP 中的,不过 Go 只运行选定的 case,而非之后所有的 case。 实际上,Go 自动提供了在这些语言中每个 case 后面所需的 break
语句。 除非以 fallthrough
语句结束,否则分支会自动终止。
它接受任意形式的表达式:
Go
switch var1 {
case val1:
...
case val2:
...
default:
...
}
-
当代码块只有一行时,可以直接放置在 case 语句之后。
-
您同样可以使用 return 语句来提前结束代码块的执行。当您在 switch 语句块中使用 return 语句,并且您的函数是有返回值的,您还需要在 switch 之后添加相应的 return 语句以确保函数始终会返回。
-
可选的 default 分支可以出现在任何顺序,但最好将它放在最后。它的作用类似与 if-else 语句中的 else,表示不符合任何已给出条件时,执行相关语句。
-
您可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3。
-
每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。( Go 语言使用快速的查找算法来测试 switch 条件与 case 分支的匹配情况,直到算法匹配到某个 case 或者进入 default 条件为止。)
-
一旦成功地匹配到某个分支,在执行完相应代码后就会退出整个 switch 代码块,也就是说您不需要特别使用 break 语句来表示结束。
switch 语句的第二种形式是不提供任何被判断的值(实际上默认为判断是否为 true),然后在每个 case 分支中进行测试不同的条件。
Go
switch {
case condition1:
...
case condition2:
...
default:
...
}
switch 语句的第三种形式是包含一个初始化语句:
Go
switch initialization {
case val1:
...
case val2:
...
default:
...
}
例如:
Go
switch result := calculate(); {
case result < 0:
...
case result > 0:
...
default:
// 0
}
使用fallthrough可以继续指向下一个case,否则找到对应case就会退出:
Go
package main
import "fmt"
func main() {
k := 6
switch k {
case 4:
fmt.Println("was <= 4")
fallthrough
case 5:
fmt.Println("was <= 5")
fallthrough
case 6:
fmt.Println("was <= 6")
//fallthrough
case 7:
fmt.Println("was <= 7")
fallthrough
case 8:
fmt.Println("was <= 8")
fallthrough
default:
fmt.Println("default case")
}
}
for
基于计数器的迭代
格式:
Go
for 初始化语句; 条件语句; 修饰语句 {}
注意 :和 C、Java、JavaScript 之类的语言不同,Go 的 for 语句后面的三个构成部分外没有小括号, 大括号 { }
则是必须的。
例如:
Go
func main() {
loopFor()
}
func loopFor() {
for i := 0; i < 100; i++ {
fmt.Println(i)
}
}
基于条件判断的迭代
for 结构的第二种形式是没有头部的条件判断迭代(类似其它语言中的 while 循环),基本形式为:for 条件语句 {}。(相当于while循环)
您也可以认为这是没有初始化语句和修饰语句的 for 结构,因此 ;; 便是多余的了。
Go
package main
import "fmt"
func main() {
var i int = 5
for i >= 0 {
i = i - 1
fmt.Printf("The variable i is now: %d\n", i)
}
}
for-range 结构
这是 Go 特有的一种的迭代结构,您会发现它在许多情况下都非常有用。它可以迭代任何一个集合。语法上很类似其它语言中 foreach 语句,但您依旧可以获得每次迭代所对应的索引。一般形式为:for ix, val := range coll { }
。val
始终为集合中对应索引的值拷贝,因此它一般只具有只读性质,对它所做的任何修改都不会影响到集合中原有的值(注:如果 val
为指针,则会产生指针的拷贝,依旧可以修改集合中的原值)。
例子:
Go
for pos, char := range str {
...
}
break 和 continue
和java一样。
标签 与 goto
for、switch 或 select 语句都可以配合标签(label)形式的标识符使用,即某一行第一个以冒号(:
)结尾的单词。(标签的名称是大小写敏感的,为了提升可读性,一般建议使用全部大写字母)
Go
package main
import "fmt"
func main() {
LABEL1:
for i := 0; i <= 5; i++ {
for j := 0; j <= 5; j++ {
if j == 4 {
continue LABEL1
}
fmt.Printf("i is: %d, and j is: %d\n", i, j)
}
}
}
使用goto结合lable
Go
package main
func main() {
i:=0
HERE:
print(i)
i++
if i==5 {
return
}
goto HERE
}
如果您必须使用 goto,应当只使用正序的标签(标签位于 goto 语句之后),但注意标签和 goto 语句之间不能出现定义新变量的语句,否则会导致编译失败。
错误示例:
Go
// compile error goto2.go:8: goto TARGET jumps over declaration of b at goto2.go:8
package main
import "fmt"
func main() {
a := 1
goto TARGET // compile error
b := 9
TARGET:
b += a
fmt.Printf("a is %v *** b is %v", a, b)
}
学习参考资料: