单分支
if condition { 代码块 } if 5 > 2 { fmt.Println("5 greater than 2") }
Go语言中,花括号一定要跟着if、for、func等行的最后,否则语法出错。
condition必须是一个bool类型,在Go中,不能使用其他类型等效为布尔值。 if 1 {} 是错误的
语句块中可以写其他代码
如果condition为true,才能执行其后代码块
多分支
if condition1 { 代码块1 } else if condition2 { 代码块2 } else if condition3 { 代码块3 } ... { ... } else if conditionN { 代码块N } else { 代码块 }
多分支结构,从上向下依次判断分支条件,只要一个分支条件成立,其后语句块将被执行,那么其他条件都不会被执行
前一个分支条件被测试过,下一个条件相当于隐含着这个条件 一定要考虑一下else分支是有必要写,以防逻辑漏洞
循环也可以互相嵌套,形成多层循环。循环嵌套不易过深。
if score, line := 99, 90; score > line { fmt.Println("perfect") } else { fmt.Println("good") } // score, line作用域只能是当前if语句 // 这种写法中定义的变量作用域只能是当前if或switch。
switch分支// Go语言的switch有别于C语言的switch,case是独立代码块,不能穿透。
a := 20 switch 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") }
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") }
a := 20 switch { // 没有待比较变量,意味着表达式是true,是布尔型 case a > 0: fmt.Println("positive") case a < 0: fmt.Println("negative") default: fmt.Println("zero") }
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") }
for循环
for [初始操作];[循环条件];[循环后操作] { 循环体 }
初始操作:第一次进入循环前执行,语句只能执行一次,之后不再执行
循环条件:要求返回布尔值,每次进入循环体前进行判断。如果每次条件满足返回true,就进入循 环执行一次循环体;否则,循环结束
循环后操作:每次循环体执行完,在执行下一趟循环条件判断之前,执行该操作一次
for i := 5; i < 10; {} for i := 5; ; {} // 没条件就相当于true for i < 10 {} // for condition {},condition就是循环条件 for ;; {} // 死循环 // 死循环简写如下 for {} // 死循环 相对于 for true {}
continue
中止当前这一趟循环体的执行,直接执行“循环后操作”后,进入下一趟循环的条件判断。
break
终止当前循环的执行,结束了。
for range
类型 | 变量 | range表达式 | 第一个值 | 第二个值 |
数组或切片 | a | [n]E, *[n]E []E | int类型的index | a[i] E |
字符串 | s | "abcd" | index i int utf-8字节偏 移 | unicode值 rune |
map | m | map[K]V | key | value |
随机数
标准库"math/rand" 使用的是伪随机数,是内部写好的公式计算出来的。这个公式运行提供一个种子,有这个种子作为 起始值开始计算。
src := rand.NewSource(100),使用种子100创建一个随机数源
rand.New(rand.NewSource(time.Now().UnixNano())) ,利用当前时间的纳秒值做种子
r10 := rand.New(src),使用源创建随机数生成器
r10.Intn(5),返回[0, 5)的随机整数
// 对于go1.20*之前的版本,采用这种方法会导致每次生成的随机数都是一样的 // 这是因为之前的版本所使用的全局随机数生成器globalRand的种子默认是1 for i := 0; i < 10; i++ { fmt.Println(rand.Intn(10) - 8) // 伪随机数,每次都一样,go1.20版本开始就不一样了,就是真随机数了 }
它的种子默认为1, var globalRand = New(&lockedSource{src: NewSource(1). (*rngSource)})
如果要改变globalRand的种子,就需要使用rand.Seed(2)修改种子
rand.Intn(5)就是使用它生成随机数
下面是go1.20之前版本的原码:
从Go v1.20开始,globalRand已经改变为使用随机种子。参看Release notes https://go.dev/doc/go1.2 0
下面是go1.20.4版本的原码:
如果想使用旧版globalRand的行为,可以手动设定种子源 rand.Seed(1) 或使用环境变量os.Setenv("GODEBUG", "randautoseed=0") 。