您现在的位置是:首页 >技术杂谈 >Golang分支和循环网站首页技术杂谈

Golang分支和循环

Twx_ 2023-05-27 20:00:02
简介Golang分支和循环

程序控制

· 顺序
	- 按照先后顺序一条条执行
		- 例如,先洗手,再吃饭,再洗碗
· 分支
	- 根据不同的情况判断,条件满足执行某条件下的语句
		- 例如,先洗手,如果饭没有做好,玩游戏;如果饭做好了,就吃饭;如果饭都没有做,叫外卖
· 循环
	- 条件满足就反复执行,不满足就不执行或不再执行
		- 例如,先洗手,看饭好了没有,没有好,一会来看一次是否好了,一会儿来看一次,直到饭好了,才可是吃饭。这里循环的条件是饭没有好,饭没有好,就循环的来看饭好了没有

单分支

if condition {
    代码块
}
if 5 > 2 {
    fmt.Println("5 greater than 2")
}

注意:Go语言中,花括号一定要跟着if、for、func等行的最后,否则语法出错。这其实就是为了解决C 风格、Java风格之争。
- condition必须是一个bool类型,在Go中,不能使用其他类型等效为布尔值。 if 1 {} 是错误的
- 语句块中可以写其他代码
- 如果condition为true,才能执行其后代码块

多分支

if condition1 {
    代码块1
} else if condition2 {
    代码块2
} else if condition3 {
    代码块3
} ... {
    ...
} else if conditionN {
    代码块N
} else {
    代码块
}
----------------------------------------------------------------------------------------------
a := 6
if a < 0 {
 fmt.Println("false")
} else if a > 0 { 							// 走到这里一定 a 不小于 0
 fmt.Println("positive")
} else { 									// 走到这里一定 a 不大于、也不小于 0
 fmt.Println("zero")
}
  • 多分支结构,从上向下依次判断分支条件,只要一个分支条件成立,其后语句块将被执行,那么其他条件都不会被执行
  • 前一个分支条件被测试过,下一个条件相当于隐含着这个条件
  • 一定要考虑一下else分支是有必要写,以防逻辑漏洞
// 嵌套
a := 6
if a == 0 {
 	fmt.Println("zero")
} else {
 	if a > 0 {
 		fmt.Println("negative")
 	} else if a >= 0 { // 走到这里一定 a 不小于 0
 		fmt.Println("positive")
 }
}

** 循环也可以互相嵌套,形成多层循环。循环嵌套不易过深。**

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")
}

C语言的switch有穿透效果,如果想在Go语言中实现穿透效果,使用fallthrough穿透当前case语句块。
但是,大家使用C语言的时候,一般都不想要使用这种穿透效果,所以,如非必要,不要使用fallthrough

特殊if

switch可以写成 switch a:=20;a 这种形式,也就是可以在表达式a之前写一个语句后接一个分号。if也
可以这样

if score, line := 99, 90; score > line {
 	fmt.Println("perfect")
} else {
	fmt.Println("good")
} // score, line作用域只能是当前if语句

这种写法中定义的变量作用域只能是当前if或switch。

for循环

Go语言没有提供while关键字,可以用for方便的替代

for [初始操作];[循环条件];[循环后操作] {  //循环顺序 初始操作->循环条件->循环体->循环后操作
    循环体
}

循环顺序: 初始操作 -> 循环条件(进行条件判断) -> 循环体(执行代码) -> 循环后操作

for i := 0; i < 10; i++ {
 fmt.Println(i)
} // 初始操作中的短格式定义的i的作用域只能在for中
// 特殊写法
for i := 5; i < 10; {}
for i := 5; ; {} // 没条件就相当于true
for i < 10 {} // for condition {},condition就是循环条件
for ;; {} // 死循环
// 死循环简写如下
for {} // 死循环 相对于 for true {}

continue

中止当前这一趟循环体的执行,直接执行“循环后操作”后,进入下一趟循环的条件判断。

for i := 0; i < 10; i++ {
 if i%2 == 0 {    //当条件满足  执行continue fmt.Println(i)将不再执行 进入下一次循环
 continue
 }     
 fmt.Println(i)
}

break

终止当前循环的执行,结束了。

for i := 0; ; i++ {
 	if i%2 == 0 {
 	continue
 }
 fmt.Println(i)
 if i >= 10 {
 	break
 }
} // 请问执行结果是什么?

除了break,函数的return结束函数执行,当然也能把函数中的循环打断。

goto和label

不建议使用 它会破坏结构化编程,但是确实能做到便利的无条件跳转

for range

类型变量range expression第一个值第二个值
array or slicea[n]E, *[n]E []E-ndex i inta[i] E
strings“abcd”index i int utf-8字节偏移unicode值 rune
mapmmap[K]Vkey k Km[k] V
channelcchan E <-chan Eelement e E

随机数

标准库"math/rand"

我们使用的是伪随机数,是内部写好的公式计算出来的。这个公式运行提供一个种子,有这个种子作为起始值开始计算。

  • src := rand.NewSource(100),使用种子100创建一个随机数源
  • rand.New(rand.NewSource(time.Now().UnixNano())) ,利用当前时间的纳秒值做种子
  • r10 := rand.New(src),使用源创建随机数生成器
  • r10.Intn(5),返回[0, 5)的随机整数
package main
import (
 	"fmt"
 	"math/rand"
)
func main() {
 	src := rand.NewSource(10)
 	r10 := rand.New(src)
 	r1 := rand.New(rand.NewSource(1))
 	for i := 0; i < 10; i++ {
 		fmt.Printf("%d, %d, %d
", rand.Intn(5), r1.Intn(5), r10.Intn(5))
 	}
}

全局随机数生成器globalRand

  • 它的种子默认为1
  • 如果要改变globalRand的种子,就需要使用rand.Seed(2)修改种子
  • rand.Intn(5)就是使用它生成随机数
golang语言 rand.New(rand.NewSource(time.Now().UnixNano()))和rand.Seed(time.Now().UnixNano()))的区别
这两个函数的作用是相同的,都是用于提供一个基于当前时间的伪随机数生成器的种子。区别在于使用的函数不同,一个是rand.NewSource(),一个是rand.Seed()。rand.NewSource()返回一个以给定值为种子的新的随机数生成器,而rand.Seed()则将给定值作为当前进程的随机数种子。一般来说,建议使用rand.NewSource(time.Now().UnixNano())生成随机数生成器的种子,因为它提供的随机性更强。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。