select中的break和return

yaxiaomu · 2020-05-09 13:28:03 · 1722 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2020-05-09 13:28:03 的主题,其中的信息可能已经有所发展或是发生改变。

break是break的select还是for呢?那return呢?除了做实验有什么方法可以看到这两个关键字的区别与用法

...
go func(wg *sync.WaitGroup) {
        defer wg.Done()
        for {
            select {
            case resGt := <-ch2:
                if resGt > 28 {
                    fmt.Println("bug:lwq")
                    return
                }
                fmt.Println(resGt)
            }

        }
    }(&wg)

...

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1722 次点击  
加入收藏 微博
4 回复  |  直到 2020-05-11 14:40:27
ysh_77
ysh_77 · #1 · 5年之前

break是针对for的,直接跳出循环。 return是针对函数,直接终止运行当前函数。 select没有此类对应的关键字。 做实验已经是一个比较好直观观察到现象的方法了。

ysh_77
ysh_77 · #2 · 5年之前

不好意思,上面说break一定是针对for跳出循环是不对的。 应该是break包在select里面就是针对select的,不是的话则是针对for的,应该是一个作用域问题
return的话不管在哪里都是直接终止函数,demo如下:

package main

import (
    "fmt"
    "time"
)

var ch = make(chan int, 100)

func main() {
    ch <- 98
    ch <- 98
    hh()
    fmt.Println("函数执行结束")
    time.Sleep(10 * time.Second)
}

func hh() {
    ticker := time.NewTicker(2 * time.Second)
    for {
        fmt.Println("is for")
        select {
        case <-ch:
            fmt.Println("is select")
            break //这里是针对select
        case <-ticker.C:
            fmt.Println("ticker")
            return
        }
        fmt.Println("select 之后")
        break //这里是针对for
    }
}
yaxiaomu
yaxiaomu · #3 · 5年之前

2楼 @ysh_77 谢谢回复,很详细。我再补充点注释。

package main

import (
    "fmt"
    "time"
)

var ch = make(chan int, 100)

func main() {
    ch <- 98
    ch <- 99
    testBreakScope()
    fmt.Println("main 函数执行结束")
    time.Sleep(3 * time.Second)
}

func testBreakScope() {
    var counter int
    defer func() {
        fmt.Println("func testBreakScope 结束")
    }()
    ticker := time.NewTicker(10 * time.Nanosecond)
    for {
        counter++
        fmt.Println("for 中执行第", counter, " 次")
        select {
        case i := <-ch:
            fmt.Println("1===命中第一个case,值为:", i, " 触发select里的break")
            break //这里是针对select,还会执行到select之外的内容
        case <-ticker.C:
            fmt.Println("3===计时器到期执行case,触发select里的return")
            return //这里是针对整个函数,只会执行defer中的内容
        }
        fmt.Println("select已经退出,触发select外的break ")
        break //这里是针对for,还会执行到for之外的内容
    }
    fmt.Println(" 跳出for第", counter, "次")
}
ysh_77
ysh_77 · #4 · 5年之前
yaxiaomuyaxiaomu #3 回复

2楼 @ysh_77 谢谢回复,很详细。我再补充点注释。 ``` package main import ( "fmt" "time" ) var ch = make(chan int, 100) func main() { ch <- 98 ch <- 99 testBreakScope() fmt.Println("main 函数执行结束") time.Sleep(3 * time.Second) } func testBreakScope() { var counter int defer func() { fmt.Println("func testBreakScope 结束") }() ticker := time.NewTicker(10 * time.Nanosecond) for { counter++ fmt.Println("for 中执行第", counter, " 次") select { case i := <-ch: fmt.Println("1===命中第一个case,值为:", i, " 触发select里的break") break //这里是针对select,还会执行到select之外的内容 case <-ticker.C: fmt.Println("3===计时器到期执行case,触发select里的return") return //这里是针对整个函数,只会执行defer中的内容 } fmt.Println("select已经退出,触发select外的break ") break //这里是针对for,还会执行到for之外的内容 } fmt.Println(" 跳出for第", counter, "次") } ```

后来又看了一下: select中的break写不写没有关系,因为golang在select中的case执行完毕之后会自动执行break。单独使用select中的break可用于判断条件后的提前break

select一般和for一起使用,想要在select中的case中直接跳出break,需要搭配label使用,这样比较方便简洁,demo如下:

func kk() {

SELECT:
    for {
        select {
        case <-time.After(time.Second):
            fmt.Println("一秒后退出")
            //break 跳出select
            break SELECT //带标签的break,实际上跳出到select外层的for语句块
        case <-time.After(time.Second * 10):
            fmt.Println("十秒后退出")
            break
        }
    }

    fmt.Println("select 语句结束")
}
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传