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

基于Go协程与通道的斐波那契代码运行原理问询

Go协程+通道实现斐波那契序列的疑问解答

先贴出Rosetta Code上常见的对应实现代码:

package main

import "fmt"

func fib(c, quit chan int) {
	x, y := 0, 1
	for {
		select {
		case c <- x:
			x, y = y, x+y
		case <-quit:
			fmt.Println("fib协程退出")
			return
		}
	}
}

func main() {
	c := make(chan int)
	quit := make(chan int)

	// 启动匿名协程负责接收数值并触发停止
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println(<-c)
		}
		quit <- 0 // 发送停止信号
	}()

	fib(c, quit)
}

1. fib函数里的无限for循环怎么停止?

fib里的for确实是无限循环,但它被select语句包裹着。当quit通道收到值时,case <-quit:分支会被触发,执行return直接退出fib函数,循环自然就终止了。

2. 通道c是如何传递停止信号的?

先澄清:在上面的代码里,传递停止信号的是quit通道,c的作用是传递斐波那契数值。如果你的代码里是用c来传停止信号,大概率是另一种单通道实现:

func fib(c chan int) {
	a, b := 0, 1
	for {
		select {
		case c <- a:
			a, b = b, a+b
		case <-c:
			return
		}
	}
}

func main() {
	c := make(chan int)
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println(<-c)
		}
		c <- 0 // 往c发停止信号
	}()
	fib(c)
}

这种情况下,c兼具两个作用:fib协程往里面塞斐波那契值,接收协程取完指定数量后,往c里塞一个值,fib里的case <-c:分支触发,执行return退出循环。

3. 函数调用的逻辑顺序是怎样的?

以双通道版本为例:

  • 主协程先创建c(传数值)和quit(传停止信号)两个通道。
  • 启动匿名协程:这个协程会循环10次,每次从c里取斐波那契值打印,取完10次后往quit通道发一个值。
  • 主协程调用fib(c, quit),进入fib的无限循环。
  • fib里的select会优先尝试往c发值(此时匿名协程在等c的值,通道不阻塞),每次发完更新斐波那契数值。
  • 匿名协程取完10个值后,往quit发0,fib的select检测到quit有值,触发退出分支,fib函数返回。
  • 主协程执行完毕,程序退出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:26:05