登录 立即注册

首页 > 绿虎论坛 > 软件开发 > 编程语言 > golang (发帖)

标题: golang的子协程内部阻塞处理时,怎么及时的判断超时,从而不导致 继续写入一个 应为超时而早已被关闭的channel引发的panic

作者: @Ta

时间: 04-30 09:52发布,04-30 10:26修改

点击: 6784

代码如下

package main

import (
	"context"
	"os"
	"time"
)

func main() {
	g()
	//模拟全局线程继续运行
	time.Sleep(time.Second * 5)
}

func g() {
	// 创建一个子节点的context,3秒后自动超时
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
	defer func() {
		cancel()
		println("g()函数已完结")
	}()

	channel := make(chan string)
	defer close(channel)

	// 创建一个子协程 用于某些阻塞的操作
	go func() {
		defer println("(block)子携程退出", os.Getppid())
		select {
			case <-ctx.Done():
				return
			default:
				time.Sleep(time.Millisecond * 100)
				//1获取到一些数据后,结果发送到channel
				channel <- "hello"
				time.Sleep(time.Second * 4)
				//2获取到一些数据后,结果发送到channel
				channel <- "hello"
			}
	}()
	select {
	case <-ctx.Done():
		return
	case h := <-channel:
		println("收到消息", h)
	}
}

错误:

收到消息 hello
g()函数已完结 
(block)子携程退出 1616                                     
panic: send on closed channel                              
                                                           
goroutine 6 [running]:                                     
main.g.func2()                                             
        C:/Users/admin/IdeaProjects/testg/main.go:39 +0xa5 
created by main.g in goroutine 1                           
        C:/Users/admin/IdeaProjects/testg/main.go:27 +0x125

有些思路

每次 channel <- "hello"的时候用,但是有临界问题,如果刚判断完毕channel可用(临界值),然后就被close(channel),还是会出现panic: send on closed channel,难道需要还要额外加入一个写锁判断吗

_,ok:=<-channel;
ok  &&  channel <- "hello"

[隐藏样式|查看源码]


『回复列表(2|隐藏机器人聊天)』

1. 关于channel关闭操作
https://go101.org/article/channel-closing.html
(/@Ta/2024-04-30 10:54//)

2. 既然子协程是消息的生产者,当然就要子协程负责关闭channel了,把关闭channel放到子协程的defer里面就行了。
(/@Ta/2024-05-02 11:57//)

回复需要登录

12月13日 11:29 星期五

本站由hu60wap6华为CPU驱动

备案号: 京ICP备18041936号-1