Go语言中,花括号一定要跟着if、for、func等行的最后,否则语法出错。
if condition {
代码块
}
if 8 > 3 {
fmt.Println("5 greater than 2")
}
if condition1 {
代码块1
} else if condition2 {
代码块2
} else if condition3 {
代码块3
} ... {
...
} else if conditionN {
代码块N
} else {
代码块
}
package main
import "fmt"
func main() {
a := 6
if a < 0 {
fmt.Println("negative")
} else if a > 0 { // 走到这里一定 a 不小于 0
fmt.Println("positive")
} else { // 走到这里一定 a 不大于、也不小于 0
fmt.Println("zero")
}
positive
package main
import "fmt"
func main() {
// 嵌套
a := 6
if a == 0 {
fmt.Println("zero")
} else {
if a > 0 {
fmt.Println("negative")
} else if a >= 0 { // 走到这里一定 a 不小于 0
fmt.Println("positive")
}
}
}
negative
循环也可以互相嵌套,形成多层循环。循环嵌套不易过深
Go语言的switch有别于C语言的switch,case是独立代码块,不能穿透。
package main
import "fmt"
func main() {
// 嵌套
switch a := 20; a { // 待比较的是a
case 10:
fmt.Println("ten")
case 20:
fmt.Println("twenty")
case 30, 40, 50: // 或关系
fmt.Println(">=30 and <=50")
default:
fmt.Println("other")
}
}
package main
import "fmt"
func main() {
// 嵌套
a := 20
switch { // 没有待比较变量,意味着表达式是true,是布尔型
case a > 0:
fmt.Println("positive")
case a < 0:
fmt.Println("negative")
default:
fmt.Println("zero")
}
}
package main
import "fmt"
func main() {
switch a := 20; { // 没有待比较变量,意味着表达式是true,是布尔型
case a > 0: // 如果待比较值是true,a > 0如果返回true,就进入
fmt.Println("positive")
case a < 0: // 如果待比较值是true,a < 0如果返回true,就进入
fmt.Println("negative")
default:
fmt.Println("zero")
}
}
package main
import "fmt"
func main() {
switch a := 20; { // 没有待比较变量,意味着表达式是true,是布尔型
case a > 0: // 如果待比较值是true,a > 0如果返回true,就进入
fmt.Println("positive")
fallthrough // 穿透
case a < 0: // 如果待比较值是true,a < 0如果返回true,就进入
fmt.Println("negative")
default:
fmt.Println("zero")
}
}
positive
negative
在Go语言中实现穿透效果,使用fallthrough穿透当前case语句块。但是,大家使用C语言的时候,一般都不想要使用这种穿透效果,所以,如非必要,不要使用fallthrough。
switch可以写成 switch a:=20;a 这种形式,也就是可以在表达式a之前写一个语句后接一个分号。if也可以这样。
这种写法中定义的变量作用域只能是当前if或switch。
if score, line := 99, 90; score > line {
fmt.Println("perfect")
} else {
fmt.Println("good")
} // score, line作用域只能是当前if语句
Go语言没有提供while关键字,可以用for方便的替代
for [初始操作];[循环条件];[循环后操作] {
循环体
}
for i := 0; i < 10; i++ {
fmt.Println(i)
} // 初始操作中的短格式定义的i的作用域只能在for中
0
1
2
3
4
5
6
7
8
9
// 特殊写法
for i := 5; i < 10; {}
for i := 5; ; {} // 没条件就相当于true
for i < 10 {} // for condition {},condition就是循环条件
for ;; {} // 死循环
// 死循环简写如下
for {} // 死循环 相对于 for true {}
中止当前这一趟循环体的执行,直接执行“循环后操作”后,进入下一趟循环的条件判断
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue
}
fmt.Println(i)
} 把当前符合条件的跳出去在执行
1
3
5
7
9
终止当前循环的执行,结束了
package main
import "fmt"
func main() {
for i := 0; ; i++ {
if i%2 == 0 {
continue
}
fmt.Println(i)
if i >= 10 {
break
}
}
}
除了break,函数的return结束函数执行,当然也能把函数中的循环打断。
这是一个被很多语言尘封或者废弃的关键字,它会破坏结构化编程,但是确实能做到便利的无条件跳转。
跳出多重循环使用,但是问题是为什么要用多重循环?
到同一处标签处统一处理,例如统一错误处理。问题是,写个函数也可以实现。
有时候也能简化一些代码,但是它是双刃剑,不要轻易使用。
goto需要配合标签label使用,label就像代码中的锚点,goto将无条件跳到那里开始向后执行代码。
package main
import "fmt"
func main() {
for i := 0; ; i++ {
if i%2 == 0 {
continue
}
fmt.Println(i)
if i > 10 {
goto condition
}
}
condition:
fmt.Println("done")
}
1
3
5
7
9
11
done
continue、break也可以指定label,方便某些循环使用。但是,建议不要这么写,弄不好就成了毛线团。
for range 结构是Go语言特有的一种的迭代结构,在许多情况下都非常有用,for range 可以遍历数组、切片、字符串、map 及通道(channel),for range 语法上类似于其它语言中的 foreach 语句,一般形式为:
for key, val := range coll {
...
}
package main
import "fmt"
func main() {
for i, v := range "abcd测试" {
fmt.Printf("%d, %[2]d, %[2]c, %#[2]x\n", i, v)
}
}
0, 97, a, 0x61
1, 98, b, 0x62
2, 99, c, 0x63
3, 100, d, 0x64
4, 27979, 测, 0x6d4b
7, 35797, 试, 0x8bd5
//"abcd测试" '测'在字符串中的是属于字符 在字符串中占三个字节
func main() {
// for i, v := range "abcd测试" {
// fmt.Printf("%d, %[2]d, %[2]c, %#[2]x\n", i, v)
// }
fmt.Println("\xe6\xb5\x8b\xe8\xaf\x95") // 6个字节
}
测试
索引就是字节偏移量,从索引可以看出,中文在字符串中是utf-8编码,占3个字节。
但是for range读取字符串返回的是一个个字符(整数),而字符是ASCII或UNICODE对应的编码值。
%d 打印的是unicode值
%c 打印的是字符
package main
import "fmt"
func main() {
arr := [5]int{1, 3, 5, 7, 9}
for i, v := range arr {
fmt.Println(i, v, arr[i])
}
for i := range arr {
fmt.Println(i, arr[i])
}
for _, v := range arr {
fmt.Println(v)
}
}
0 1 1
1 3 3
2 5 5
3 7 7
4 9 9
0 1
1 3
2 5
3 7
4 9
1
3
5
7
9
标准库"math/rand"
在1.20.X版本后 直接可以得到随机数,不用指定公式和随机数源
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println(rand.Intn(20)) //20 代表20以内的数
}
//多次执行出现结果
4
19
package main
import (
"fmt"
"math/rand"
)
func main() {
for i := 0; i < 10; i++ {
fmt.Println(rand.Intn(20))
}
}
//获得10个20以内的随机数
3
15
7
9
19
4
14
16
10
13 //并且执行多次 随机数一直在变化
在1.20.X版本前
我们使用的是伪随机数,是内部写好的公式计算出来的。这个公式运行提供一个种子,有这个种子作为起始值开始计算。
func main() {
src := rand.NewSource(10) 使用种子10创建一个随机数源
gen10 := rand.New(src) 使用源创建随机数生成器
for i := 0; i < 10; i++ {
fmt.Println(gen10.Intn(20)) 返回[0, 20)的随机整数
}
}
14
8
7
19
8
4
19
15
15
18
我们重复执行 随机数是一模一样的 因为随机数源是固定的
因此我们只需要将随机数源的值变成随机的就可以改变
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
src := rand.NewSource(time.Now().UnixNano()) //
gen10 := rand.New(src)
for i := 0; i < 5; i++ {
fmt.Println(gen10.Intn(20))
}
}
9
12
17
14
9
多次执行 发现随机数也是改变的