You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言select关键字运作机制及代码终止原因问询

Go语言select关键字的运作逻辑

select是Go专门用来处理多通道操作的控制结构,核心规则如下:

  • 它会同时监听所有case里的通道操作;
  • 当至少一个case的通道操作处于就绪状态时,select会随机挑选一个就绪的case执行;
  • 如果所有case都未就绪,select会阻塞,直到某个case的操作就绪;
  • 若存在default分支,所有case未就绪时会立刻执行default,不会阻塞。
你的代码停止原因详解

先修正并格式化你的代码:

package main

import "fmt"

func fibonacci(c, quit chan int) {
    x, y := 0, 1
    for {
        select {
        case c <- x:
            fmt.Printf("x = %d, y = %d\n", x, y)
            x, y = y, x+y
        case <-quit:
            fmt.Println("quit")
            return
        }
    }
}

func main() {
    c := make(chan int)
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(<-c)
        }
        quit <- 0
    }()
    fibonacci(c, quit)
}

程序在第10次迭代后停止,核心原因是无缓冲通道的同步特性:

  • 你创建的c是无缓冲通道,无缓冲通道的发送(c <- x)和接收(<-c)必须成对完成——发送方要等接收方准备好接收,操作才算完成,反之亦然。
  • 匿名goroutine循环10次接收c的数据:每接收一次,fibonacci里的c <- x就完成一次,随后更新x、y,进入下一轮select。
  • 当匿名goroutine完成10次接收后,会执行quit <- 0:此时fibonacci的select会检测到<-quit通道有数据可读(处于就绪状态),就会执行这个分支,打印"quit"并返回,直接终止fibonacci函数的无限循环,程序也就停止了。

你误以为c <- x始终可执行,是因为忽略了无缓冲通道的阻塞特性:当匿名goroutine停止接收c的数据后,c <- x会一直阻塞,但此时quit通道的操作已经就绪,select会优先执行就绪的<-quit分支,而不是一直等c <- x。

内容的提问来源于stack exchange,提问作者Lol Lol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 15:35:09