Golang中如何从for-range循环退出ticker?

Golang中如何从for-range循环退出ticker? https://play.golang.org/p/7FI8e7EVJBd

当for-range循环退出时,是否通过goroutine中的return退出? 在上面的示例中,第15行代码从未执行,这是为什么?

4 回复

嗯,这种行为相当令人困惑。看起来像是内存泄漏。

更多关于Golang中如何从for-range循环退出ticker?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我发现对于我的情况,这个方法可以解决问题。

cinematik:

当 for-range 循环退出时,是否通过 goroutine 的 return 退出?

循环永远不会退出,因为 ticker 的通道永远不会关闭。

cinematik:

在上面的示例中,为什么从未打印第 15 行?

因为 for 循环是无限循环,这是由于 ticker 的通道永远不会被关闭。

在 Go 语言中,从 for range 循环退出 ticker 时,确实可以通过在 goroutine 中使用 return 来退出。但根据你提供的代码示例(虽然我无法直接访问链接,但基于常见模式),问题通常出现在 goroutine 和主程序之间的同步上。当主程序退出时,所有 goroutine 会被强制终止,这可能导致某些代码(如你提到的第15行)未执行。

以下是一个典型示例,展示如何正确从 for range 循环退出 ticker,并确保 goroutine 正常结束:

package main

import (
	"fmt"
	"time"
)

func main() {
	ticker := time.NewTicker(1 * time.Second)
	done := make(chan bool)

	go func() {
		for {
			select {
			case <-done:
				fmt.Println("Goroutine exiting via return")
				return // 退出 goroutine
			case t := <-ticker.C:
				fmt.Println("Tick at", t)
			}
		}
	}()

	time.Sleep(5 * time.Second) // 模拟运行一段时间
	ticker.Stop()               // 停止 ticker
	done <- true                // 发送退出信号
	fmt.Println("Ticker stopped")
}

在这个示例中:

  • 我们使用 ticker := time.NewTicker(1 * time.Second) 创建一个每秒触发的 ticker。
  • goroutine 中的 for 循环通过 select 语句监听两个通道:done 通道(用于退出信号)和 ticker.C 通道(用于 ticker 事件)。
  • 当主程序调用 ticker.Stop() 并发送 done <- true 时,goroutine 会执行 case <-done: 分支,通过 return 退出循环,并打印 “Goroutine exiting via return”。
  • 这确保了第15行(或类似代码)能够执行。

如果你原始代码中的第15行未执行,可能是因为:

  1. 主程序在 goroutine 有机会处理退出信号前就退出了(例如,缺少 time.Sleep 或同步机制)。
  2. 未正确停止 ticker 或发送退出信号,导致 goroutine 阻塞在 ticker.C 上。

通过使用 done 通道和 select,可以可靠地控制 goroutine 的退出。

回到顶部