控制结构
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 函数:
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
语句结束,否则分支会自动终止。
它接受任意形式的表达式:
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 分支中进行测试不同的条件。
switch {case condition1:...case condition2:...default:...
}
switch 语句的第三种形式是包含一个初始化语句:
switch initialization {case val1:...case val2:...default:...
}
例如:
switch result := calculate(); {case result < 0:...case result > 0:...default:// 0
}
使用fallthrough可以继续指向下一个case,否则找到对应case就会退出:
package main
import "fmt"
func main() {k := 6switch k {case 4:fmt.Println("was <= 4")fallthroughcase 5:fmt.Println("was <= 5")fallthroughcase 6:fmt.Println("was <= 6")//fallthroughcase 7:fmt.Println("was <= 7")fallthroughcase 8:fmt.Println("was <= 8")fallthroughdefault:fmt.Println("default case")}
}
for
基于计数器的迭代
格式:
for 初始化语句; 条件语句; 修饰语句 {}
注意:和 C、Java、JavaScript 之类的语言不同,Go 的 for 语句后面的三个构成部分外没有小括号, 大括号 { }
则是必须的。
例如:
func main() {loopFor()
}
func loopFor() {for i := 0; i < 100; i++ {fmt.Println(i)}
}
基于条件判断的迭代
for 结构的第二种形式是没有头部的条件判断迭代(类似其它语言中的 while 循环),基本形式为:for 条件语句 {}。(相当于while循环)
您也可以认为这是没有初始化语句和修饰语句的 for 结构,因此 ;; 便是多余的了。
package main
import "fmt"
func main() {var i int = 5
for i >= 0 {i = i - 1fmt.Printf("The variable i is now: %d\n", i)}
}
for-range 结构
这是 Go 特有的一种的迭代结构,您会发现它在许多情况下都非常有用。它可以迭代任何一个集合。语法上很类似其它语言中 foreach 语句,但您依旧可以获得每次迭代所对应的索引。一般形式为:for ix, val := range coll { }
。val
始终为集合中对应索引的值拷贝,因此它一般只具有只读性质,对它所做的任何修改都不会影响到集合中原有的值(注:如果 val
为指针,则会产生指针的拷贝,依旧可以修改集合中的原值)。
例子:
for pos, char := range str {
...
}
break 和 continue
和java一样。
标签 与 goto
for、switch 或 select 语句都可以配合标签(label)形式的标识符使用,即某一行第一个以冒号(:
)结尾的单词。(标签的名称是大小写敏感的,为了提升可读性,一般建议使用全部大写字母)
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
package main
func main() {i:=0HERE:print(i)i++if i==5 {return}goto HERE
}
如果您必须使用 goto,应当只使用正序的标签(标签位于 goto 语句之后),但注意标签和 goto 语句之间不能出现定义新变量的语句,否则会导致编译失败。
错误示例:
// compile error goto2.go:8: goto TARGET jumps over declaration of b at goto2.go:8
package main
import "fmt"
func main() {a := 1goto TARGET // compile errorb := 9TARGET: b += afmt.Printf("a is %v *** b is %v", a, b)
}
学习参考资料:
《Go 入门指南》 | Go 技术论坛 (learnku.com)
Go 语言之旅