go基础篇(6)
1. if else
在Go语言中,关键字if
是用于测试某个条件(布尔型或逻辑型)的语句,如果该条件成立,则会执行 if 后由大括号{}
括起来的代码块,否则就忽略该代码块继续执行后续的代码。
if condition {
// 条件为真执行
}
condition 称之为条件表达式或者布尔表达式,执行结果需返回true或false。{ 必须在条件表达式的尾部
x := 0
if x <= 0 {
fmt.Println("为真进入这里")
}
如果存在第二个分支,则可以在上面代码的基础上添加 else
关键字以及另一代码块,这个代码块中的代码只有在条件不满足时才会执行,if 和 else 后的两个代码块是相互独立的分支,只能执行其中一个。
if condition {
// 条件为真 执行
} else {
// 条件不满足 执行
}
x := 5
if x <= 0 {
fmt.Println("为真进入这里")
//go语言格式要求很严,else必须写在}后面
}else{
fmt.Println("为假进入这里")
}
如果存在第三个分支,则可以使用下面这种三个独立分支的形式:
if condition1 {
// condition1 满足 执行
} else if condition2 {
// condition1 不满足 condition2满足 执行
}else {
// condition1和condition2都不满足 执行
}
else if 分支的数量是没有限制的,但是为了代码的可读性,还是不要在 if 后面加入太多的 else if 结构
if语句可以嵌套:
/* 定义局部变量 */
var a int = 100
var b int = 200
/* 判断条件 */
if a == 100 {
/* if 条件语句为 true 执行 */
if b == 200 {
/* if 条件语句为 true 执行 */
fmt.Printf("a 的值为 100 , b 的值为 200\n" )
}
}
1.1 特殊写法
if 还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断,代码如下:
if a := 10; a >5 {
fmt.Println(a)
return
}
这种写法可以将返回值与判断放在一行进行处理,而且返回值的作用范围被限制在 if、else 语句组合中。
在编程中,变量的作用范围越小,所造成的问题可能性越小,每一个变量代表一个状态,有状态的地方,状态就会被修改,函数的局部变量只会影响一个函数的执行,但全局变量可能会影响所有代码的执行状态,因此限制变量的作用范围对代码的稳定性有很大的帮助。
2. for
go语言中的循环语句只支持 for 关键字,这个其他语言是不同的。
sum := 0
//i := 0; 赋初值,i<10 循环条件 如果为真就继续执行 ;i++ 后置执行 执行后继续循环
for i := 0; i < 10; i++ {
sum += i
}
第二种写法:
sum := 0
for {
sum++
if sum > 100 {
//break是跳出循环
break
}
}
上述的代码,如果没有break跳出循环,那么其将无限循环
第三种写法:
n := 10
for n>0 {
n--
fmt.Println(n)
}
我们来看下面一种写法:
step := 2
//初值可以省略,但是;必须有,但是这样写step的作用域就比较大了,脱离了for循环
for ; step > 0; step-- {
fmt.Println(step)
}
进一步简化代码,将 if 判断整合到 for 中,变为下面的代码:
step := 2
for step > 0 {
step--
fmt.Println(step)
}
结束循环的方式:
return
step := 2 for step > 0 { step-- fmt.Println(step) //执行一次就结束了 return } //不会执行 fmt.Println("结束之后的语句....")
break
step := 2 for step > 0 { step-- fmt.Println(step) //跳出循环,还会继续执行循环外的语句 break } //会执行 fmt.Println("结束之后的语句....")
painc
step := 2 for step > 0 { step-- fmt.Println(step) //报错了,直接结束 panic("出错了") } //不会执行 fmt.Println("结束之后的语句....")
goto
package main import "fmt" func main() { for x := 0; x < 10; x++ { for y := 0; y < 10; y++ { if y == 2 { // 跳转到标签 goto breakHere } } } // 手动返回, 避免执行进入标签 return // 标签 breakHere: fmt.Println("done") }
2.1 代码优化
package main
func length(s string) int {
println("call length.")
return len(s)
}
func main() {
s := "abcd"
// 这样写会多次调佣length函数
for i:= 0; i < length(s); i++ {
println(i, s[i])
}
}
优化:
package main
func length(s string) int {
println("call length.")
return len(s)
}
func main() {
s := "abcd"
// 这样写会多次调佣length函数
for i,n:= 0,length(s); i <n; i++ {
println(i, s[i])
}
}
2.2 案例
输出九九乘法表
package main
import "fmt"
func main() {
// 遍历, 决定处理第几行
for y := 1; y <= 9; y++ {
// 遍历, 决定这一行有多少列
for x := 1; x <= y; x++ {
fmt.Printf("%d*%d=%d ", x, y, x*y)
}
// 手动生成回车
fmt.Println()
}
}
3. for range
for range 结构是Go语言特有的一种的迭代结构,for range 可以遍历数组、切片、字符串、map 及管道(channel)
for key, val := range coll {
...
}
val
始终为集合中对应索引的值拷贝
,因此它一般只具有只读性质,对它所做的任何修改都不会影响到集合中原有的值
遍历map:
m := map[string]int{
"hello": 100,
"world": 200,
}
for key, value := range m {
fmt.Println(key, value)
}
字符串也可以使用for range:
str := "pony的go教程"
//因为一个字符串是 Unicode 编码的字符(或称之为 rune )集合
//char 实际类型是 rune 类型
for pos, char := range str {
fmt.Println(pos,char)
}
每个 rune 字符和索引在 for range 循环中是一一对应的,它能够自动根据 UTF-8 规则识别 Unicode 编码的字符。
通过 for range 遍历的返回值有一定的规律:
数组、切片、字符串返回索引和值。
map 返回键和值。
channel只返回管道内的值。
4. switch
switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。
switch 分支表达式可以是任意类型,不限于常量。可省略 break,默认自动终止。
switch 语句的语法如下:
switch var1 {
case val1:
...
case val2:
...
default:
...
}
变量 var1
可以是任何类型,而 val1 和 val2 则可以是同类型的任意值
。
类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。
您可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3。
/* 定义局部变量 */
var grade string = "B"
var score int = 90
switch score {
case 90: grade = "A"
case 80: grade = "B"
case 50,60,70 : grade = "C"
default: grade = "D"
}
//swtich后面如果没有条件表达式,则会对true进行匹配
//swtich后面如果没有条件表达式,则会对true进行匹配
switch {
case grade == "A" :
fmt.Printf("优秀!\n" )
case grade == "B", grade == "C" :
fmt.Printf("良好\n" )
case grade == "D" :
fmt.Printf("及格\n" )
case grade == "F":
fmt.Printf("不及格\n" )
default:
fmt.Printf("差\n" )
}
fmt.Printf("你的等级是 %s\n", grade )
Go里面switch默认相当于每个case最后带有break,匹配成功后不会自动向下执行其他case,而是跳出整个switch, 那么如何做到执行完一个case之后,进入下一个case而不是跳出swtich呢?
答案是:fallthrough
var s = "hello"
switch {
case s == "hello":
fmt.Println("hello")
fallthrough
case s != "world":
fmt.Println("world")
}
注意事项:
加了fallthrough后,会直接运行【紧跟的后一个】case或default语句,不论条件是否满足都会执行
var s = "hello" switch { case s == "hello": fmt.Println("hello") fallthrough case s == "world": fmt.Println("world") }
5. goto
goto 语句通过标签进行代码间的无条件跳转,同时 goto 语句在快速跳出循环、避免重复退出上也有一定的帮助,使用 goto 语句能简化一些代码的实现过程。
使用 goto 退出多层循环
传统写法:
package main
import "fmt"
func main() {
var breakAgain bool
// 外循环
for x := 0; x < 10; x++ {
// 内循环
for y := 0; y < 10; y++ {
// 满足某个条件时, 退出循环
if y == 2 {
// 设置退出标记
breakAgain = true
// 退出本次循环
break
}
}
// 根据标记, 还需要退出一次循环
if breakAgain {
break
}
}
fmt.Println("done")
}
使用goto的写法:
package main
import "fmt"
func main() {
for x := 0; x < 10; x++ {
for y := 0; y < 10; y++ {
if y == 2 {
// 跳转到标签
goto breakHere
}
}
}
// 手动返回, 避免执行进入标签
return
// 标签
breakHere:
fmt.Println("done")
}
使用 goto 语句后,无须额外的变量就可以快速退出所有的循环
使用 goto 集中处理错误
多处错误处理 存在代码重复
例如:
package main
import (
"errors"
"fmt"
"os"
)
func main() {
err := firstCheckError()
if err != nil {
fmt.Println(err)
exitProcess()
}
err = secondCheckError()
if err != nil {
fmt.Println(err)
exitProcess()
}
fmt.Println("done")
}
func secondCheckError() interface{} {
return errors.New("错误2")
}
func exitProcess() {
//退出
os.Exit(1)
}
func firstCheckError() interface{} {
return errors.New("错误1")
}
使用goto:
package main
import (
"errors"
"fmt"
"os"
)
func main() {
err := firstCheckError()
if err != nil {
fmt.Println(err)
goto onExit
}
err = secondCheckError()
if err != nil {
fmt.Println(err)
goto onExit
}
fmt.Println("done")
return
onExit:
exitProcess()
}
func secondCheckError() interface{} {
return errors.New("错误2")
}
func exitProcess() {
fmt.Println("exit")
//退出
os.Exit(1)
}
func firstCheckError() interface{} {
return errors.New("错误1")
}
6. break
break 语句可以结束 for、switch 和 select 的代码块,另外 break 语句还可以在语句后面添加
标签
,表示退出某个标签对应的代码块,标签
要求必须定义在对应的for
、switch
和select
的代码块上。
package main
import "fmt"
func main() {
OuterLoop:
for i := 0; i < 2; i++ {
for j := 0; j < 5; j++ {
switch j {
case 2:
fmt.Println(i, j)
break OuterLoop
case 3:
fmt.Println(i, j)
break OuterLoop
}
}
}
}
7. continue
continue 语句可以结束当前循环,开始下一次的循环迭代过程,仅限在 for 循环内使用,在 continue 语句后添加
标签
时,表示开始标签对应的循环
package main
import "fmt"
func main() {
OuterLoop:
for i := 0; i < 2; i++ {
for j := 0; j < 5; j++ {
switch j {
case 2:
fmt.Println(i, j)
continue OuterLoop
}
}
}
}