简介
这里介绍下Go中的break、continue、goto的使用,以及与Label的结合使用。同时会介绍下for-select,如何跟break、continue、goto以及Label结合使用。
break
break在循环中的作用是跳出循环。
func testBreak() {
list := []int{1, 2, 3, 4}
for _, i := range list {
if i == 2 {
break
}
fmt.Println(i)
}
}
// 运行输出结果:
1
break单独使用只能跳出当前循环,无法跳出多层循环。
func testBreak2() {
list1 := []int{1, 2, 3}
list2 := []int{4, 5, 6, 7}
for _, i := range list1 {
for _, i2 := range list2 {
if i2 == 5 {
break // 只会跳出当前for循环,还会执行当前循环下面的语句
}
}
fmt.Println(i)
}
}
// 运行输出结果:
1
2
3
想一次跳出到指定的地方,可以结合Label实现。
func testBreak3() {
list1 := []int{1, 2, 3}
list2 := []int{4, 5, 6, 7}
Label:
for _, i := range list1 {
for _, i2 := range list2 {
if i2 == 5 {
break Label
}
}
fmt.Println(i)
}
fmt.Println("end")
}
// Label在最外层for循环,此时break Label会直接跳出外层for循环
// 运行输出结果:
end
continue
continue在循环中后续语句不会再执行,但不会跳出当前的循环。
func testContinue1() {
list := []int{1, 2, 3, 4}
for _, i := range list {
if i == 2 {
continue // i == 2时,不再执行后续的语句
}
fmt.Println(i)
}
}
// 运行输出结果:
1
3
4
如果continue到Label,则表示对Label指定的for循环,continue之后的语句都不再执行。
func testContinue2() {
list := []int{1, 2, 3, 4}
Label:
for _, i := range list {
if i == 2 {
continue Label
}
fmt.Println(i)
}
}
// 运行输出结果:
1
3
4
如果多层循环,也是一样,对Lable指定的for循环,continue之后的语句都不再执行。
func testContinue3() {
list1 := []int{1, 2}
list2 := []int{3, 4, 5}
Label:
for _, i := range list1 {
for _, i2 := range list2 {
if i2 == 4 {
continue Label // Label指定的最外层循环
}
fmt.Println(i, i2) // i==1时输出 1 3, i==2时输出 2 3
}
fmt.Println(i) // continue Label的逻辑会影响到最外层的逻辑,这里在continue之后,导致这里永远不会执行。
}
}
// 运行输出结果:
1 3
2 3
goto
goto需要结合Label使用,可以直接跳到对应的代码逻辑。
func testGoto() {
a := 1
b := 2
if a == 1 {
goto Label
}
fmt.Println(a)
Label:
fmt.Println(b)
}
// 运行输出结果:
2
for-select
golang里的select,用来监听channel的读写事件,当事件发生时,触发相应的动作。
//select基本用法
select {
case <- chan1:
// 如果chan1成功读到数据,则进行该case处理语句
case chan2 <- 1:
// 如果成功向chan2写入数据,则进行该case处理语句
default:
// 如果上面都没有成功,则进入default处理流程
}
select执行后会直接结束,所以一般会跟for循环结合使用。
func testSelect() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
fmt.Println(1)
}
}
}
// 会一直循环下去
// 运行输出结果:
1
1
...
break
在select中break,并不会跳出for循环。
func testSelectBreak() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
fmt.Println(1)
break // 无法跳出for循环
}
}
}
// 会一直循环下去
// 运行输出结果:
1
1
...
break结合标签可以跳到for循环之外
func testSelectBreakLabel() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
Label:
for {
select {
case <-ticker.C:
fmt.Println(1)
break Label // 跳出for循环
}
}
fmt.Println("end")
}
// 运行输出结果:
1
end
goto
在for-select,使用goto结合标签可以跳到for循环之外。与break的区别在于Label标签要在for语句之后。
func testSelectGotoLabel() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
fmt.Println(1)
goto Label // 跳出for循环
}
}
Label:
fmt.Println("end")
}
// 运行输出结果:
1
end
continue
continue无法在select里单独使用,编译报错,使用的话必须在for里面,使用for-select模式。
func testSelectContinue() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
Label:
for {
select {
case <-ticker.C:
fmt.Println(1)
continue Label // 并不会跳出for循环
fmt.Println(2) // continue之后的语句不会执行
}
}
}
// 会一直循环下去
// 运行输出结果:
1
1
...