V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
www6688w
V2EX  ›  程序员

Golang 学习中的疑问,请教一下

  •  
  •   www6688w · 2019-08-08 16:30:34 +08:00 · 2622 次点击
    这是一个创建于 1715 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Go 的分支语句 “ select ”

    我请想请教一下,我该如何通俗的理解这个语句的实际作用和运行原理,官方的说明如下:

    “ select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。 select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。

    1.每个 case 都必须是一个通信 2.所有 channel 表达式都会被求值 3.所有被发送的表达式都会被求值 4.如果任意某个通信可以进行,它就执行;其他被忽略。 5.如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。 ”

    我自己不能完全的理解的是 “每个 case 都必须是一个通信”

    我的疑问如下:

    1.以上文中“通信”的定义是什么?也就是在 case 中可以放什么?表达式?还是什么?

    2.selcet 分支中 case 是如何进行判断的?

    22 条回复    2019-08-15 16:24:01 +08:00
    sulinehk
        1
    sulinehk  
       2019-08-08 16:43:05 +08:00 via Android
    通信说的是 可以向一个通道取值或发送值

    case 就是选择一个执行
    poplar50
        2
    poplar50  
       2019-08-08 16:48:11 +08:00 via Android   ❤️ 2
    通俗讲 select 看字面意思就是选择,它会在它的 case 里选择一个来执行,那么问题来了,选择条件是什么? 其实就是哪个 case 准备好了(not blocked)就执行哪个,如果都准备好了就随机选择一个。
    SuperMild
        3
    SuperMild  
       2019-08-08 16:50:38 +08:00   ❤️ 1
    tour.golang.org 里面的例子你看看,那些例子很好。
    zdt3476
        4
    zdt3476  
       2019-08-08 16:51:53 +08:00   ❤️ 1
    1. 每个 Case 放的都是 channel; 只能放 channel; channel 发送或者是接受语句
    2. 就像 你上面第 5 点说的 随机选择一个 case 来执行,比如:
    select {
    case data := <- ch1: // 可能执行这个
    ...
    case ch2 <- data2: // 也可能执行这个
    }
    kidlj
        5
    kidlj  
       2019-08-08 17:08:00 +08:00
    读英文。
    sirgod
        6
    sirgod  
       2019-08-08 17:28:57 +08:00
    看几个实际的例子就明白了
    www6688w
        7
    www6688w  
    OP
       2019-08-08 17:36:01 +08:00
    @zdt3476 我现在就是没有完全明白 select 中的 case 要满足什么情况,才算是“可以运行的 case ”。
    CRVV
        8
    CRVV  
       2019-08-08 17:40:00 +08:00   ❤️ 1
    https://golang.org/ref/spec#Channel_types

    The capacity, in number of elements, sets the size of the buffer in the channel. If the capacity is zero or absent, the channel is unbuffered and communication succeeds only when both a sender and receiver are ready. Otherwise, the channel is buffered and communication succeeds without blocking if the buffer is not full (sends) or not empty (receives). A nil channel is never ready for communication.

    communication succeeds 就是 case 可以运行
    gamexg
        9
    gamexg  
       2019-08-08 17:44:51 +08:00 via Android   ❤️ 1
    通信是指的 chan,
    表达式最终的返回值必须是 chan。
    当然还有个 default。
    shingle
        10
    shingle  
       2019-08-08 17:45:20 +08:00   ❤️ 1
    一个最常见的例子: 执行一个任务,最多五秒超时, 满足哪个就会触发 select 进行后续的处理
    select {
    case result := <- ch: // 正常执行,并在 channel 里返回结果

    case <- timeout: // 执行超时
    }

    还有一种, 用于单独开一个协程处理返回结果.
    for{
    select result := <-ch:
    //do something
    }
    shingle
        11
    shingle  
       2019-08-08 17:49:20 +08:00   ❤️ 1
    你给出的是机翻译文吧, 通信一词不应该被翻译...指的是 golang 内置类型 channel
    www6688w
        12
    www6688w  
    OP
       2019-08-08 17:55:51 +08:00
    @shingle 这个是在一些文章中找到中文的解释,看起来的确不是很容易懂 (°ー°〃)
    yangkghjh
        13
    yangkghjh  
       2019-08-08 17:58:03 +08:00
    类似抢答
    SmartKeyerror
        14
    SmartKeyerror  
       2019-08-08 18:15:11 +08:00 via Android   ❤️ 1
    不知道是哪里的翻译,但是我觉得用"通道"这个词会更好一些。channel 是通道,目的在于 goroutine 之间的通信。go select 和 Linux select 在语义层面比较相似,都是用于选取已就绪的状态,如果想对 go select 有更深的理解的话,可以看看 Linux select。
    panda1001
        15
    panda1001  
       2019-08-08 18:21:22 +08:00 via Android
    同意楼上,建议参考 linux select 的原理和使用
    OakScript
        16
    OakScript  
       2019-08-08 18:50:27 +08:00   ❤️ 1
    实在不理解就想成是用于 channel 的 switch,虽然不准确
    Pythondr
        17
    Pythondr  
       2019-08-08 19:35:28 +08:00 via Android   ❤️ 1
    都放 chan, 哪个 chan 先取到值就执行哪个 case
    Y4ssss
        18
    Y4ssss  
       2019-08-08 20:02:01 +08:00   ❤️ 1
    哪个通道是没有阻塞的就选择哪个,都没阻塞随机选一个,都阻塞 select 自身阻塞
    justfly
        19
    justfly  
       2019-08-08 21:35:51 +08:00   ❤️ 1
    你如果了解 linux 内核网络部提供的 select epoll 之类的,理解这个就不难了。
    laodao1990
        20
    laodao1990  
       2019-08-09 10:01:40 +08:00   ❤️ 1
    为什么不静下心来了找本书系统的学习下?
    推荐 《 Go 语言程序设计》
    www6688w
        21
    www6688w  
    OP
       2019-08-09 10:56:56 +08:00
    @laodao1990 多谢指点,不过我个人学习习惯先看一些视频教程,简单入门之后再啃书。你说的是这一本吗? https://book.douban.com/subject/27044219/
    laodao1990
        22
    laodao1990  
       2019-08-15 16:24:01 +08:00
    @www6688w 是的。这个是官方翻译的,github 上还有一个是网友自己翻译的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3522 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 04:54 · PVG 12:54 · LAX 21:54 · JFK 00:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.