Golang Go语言中求助如何关闭 Pending 的 goroutine

最近在将 filebeat 源码嵌入项目

	go func(){
            if err := cmd.Filebeat(inputs.Init, cmd.FilebeatSettings()).Execute(); err != nil {
                os.Exit(1)
            }
        }

这个 cmd.Filebeat().Execute() 可以理解为 time.sleep(无限大)会一直 pending, 我怎么样才能关掉这个 goroutine 呢? time.sleep(无限大)的情况也没有办法去 select context

谢谢大家!


Golang Go语言中求助如何关闭 Pending 的 goroutine

更多关于Golang Go语言中求助如何关闭 Pending 的 goroutine的实战教程也可以访问 https://www.itying.com/category-94-b0.html

21 回复

go 没发通过其他 goroutine kill 掉 goroutine, 加个 cmd 脚本调用,改成非阻塞吧

更多关于Golang Go语言中求助如何关闭 Pending 的 goroutine的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


按照 go 的 api 设计风格,阻塞调用是通过 deadline 防止无限阻塞的。通过 SetDeadline 设置后(注意是记录绝对时间,需要反复设置)阻塞调用即使未成功也要在 deadline 返回,好让 goroutine 有机会检查是否需要终止流程。
你找找你用的库有没有这种 api 吧?

不管是 go 的 goroutine 还是 python 的 Thread ,你都不可能有办法从代码本身关闭或杀死,只能在程序里自己 return ,你 return 了它才会释放。

做不到,因为某个 goroutine 无法关闭其他 goroutine 。

我看不懂评论区了…

做不到,这种情况建议你用多进程……如果你改不了 Filebeat 的代码的话

谢谢各位, 是的语言层面就没有 goroutine id 这种东西,最开始设计就设计成不能关闭。 现在碰到到情况是我的源码需要调用一个 go 写的软件,并二次开发其中的代码(需要在主程序中调用源码中的函数),这个软件是 cmd 形式的(所以代码内部没有关闭的函数)。
感觉没路子走了 手动笑哭

cmd 脚本调用的话,就没办法通信, 和一次性交叉编译了

是的, 想避开多进程就是想通信和交叉编译更方便

你可以将 Execute 修改为 ExecuteContext ,通过 Context 的 CancelFunc 来从外部终止此 goroutine

改下内部实现加个 ctx ?

被调用方写的有问题,没有 ctx 或其他方式停止任务。

加个信号 收工

和我的想法完全一致, 我调了 cancel 但是他还在运行, 哭了

这个 cmd 库有 ctx , 我调了没有反应。 不知道是不是使用问题

<br> c := cmd.Filebeat(inputs.Init, cmd.FilebeatSettings())<br> ctx, cancel := context.WithCancel(context.Background)<br> go func(){<br> if err := c.ExecuteContextFunction(ctx); err != nil {<br> os.Exit(1)<br> }<br> }<br> time.sleep( 10 * time.Second )<br> cancel()<br> time.sleep( 10000 * time.Second )<br>
cmd.Filebeat() 的返回类型中有 ctx , 我改了一下源码由在里面新建变为传入一个 ctx , 调用 cancel 后控制台还是在输出 filebeat 的日志

你试试分两个程序?把阻塞这个操作包到一个 go 程序里,然后在主程序通过 cmd 包 执行,获取 pid ,停止 kill pid ?

来把阻塞操作变成非阻塞

仔细看了一下 filebeat ,里面会使用到 os.Exit 。 那还是建议拆成两个进程比较好

谢谢 确实没有注意到 里面有调用 os.Exit 。已经通过 exec.commandContext 拆成两个进程,拿 cancel 去关闭了。 只能做进程通信啦

在Go语言中,关闭处于Pending状态的goroutine是一个复杂且通常不建议直接操作的任务,因为Go的设计哲学倾向于让goroutine自己管理其生命周期。Pending状态的goroutine意味着它正在等待某个事件(如I/O操作、通道操作或同步原语等)完成。

直接“关闭”一个goroutine在Go中并不直接支持,也不安全。通常,你会通过以下几种方式间接地管理goroutine的生命周期:

  1. 通道(Channel):使用通道发送信号给goroutine,让它优雅地退出。例如,可以发送一个特定的信号值到通道,goroutine在接收到该值后执行清理操作并退出。

  2. 上下文(Context):使用context.Context来管理请求的取消和超时。goroutine可以监听ContextDone通道,一旦Done被关闭,goroutine就可以知道它应该停止工作并退出。

  3. 同步原语:使用互斥锁(sync.Mutex)、读写锁(sync.RWMutex)或原子操作(sync/atomic包)来协调goroutine之间的状态,从而间接控制它们的生命周期。

总之,管理goroutine的生命周期应该通过明确的信号传递和同步机制来实现,而不是尝试直接“关闭”它们。设计良好的程序应该让goroutine自己决定何时完成工作并退出,这样更符合Go语言的并发模型。

回到顶部