Golang 帮看一下,运行的时候 panic,原因是写入了关闭的 channel,请问该如何解决?

netboy · · 947 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

```` golang package main import ( "context" "errors" "fmt" "sync" "time" ) type Detail struct { ID string } func Get(ctx context.Context, id string) (*Detail, error) { //you can call this function directly time.Sleep(time.Second * 3) if id == "3" { return nil, errors.New("error id is 3") } return &Detail{ID: id}, nil } func GetAll(ctx context.Context, ids []string) (map[string]*Detail, error) { var swg sync.WaitGroup result := make(map[string]*Detail, len(ids)) detailChan := make(chan *Detail, 3) doneChan := make(chan struct{}, 1) errChan := make(chan error, 1) defer close(detailChan) defer close(doneChan) defer close(errChan) ctx, cancel := context.WithCancel(ctx) for _, value := range ids { swg.Add(1) go func(ctx context.Context, v string) { defer swg.Done() res, err := Get(ctx, v) if err != nil { fmt.Println("get error ", err, v) errChan <- err return } detailChan <- res /* select { case <-ctx.Done(): return default: detailChan <- res } */ }(ctx, value) } go func() { for value := range detailChan { fmt.Println("range ", value) result[value.ID] = value } }() go func() { swg.Wait() doneChan <- struct{}{} }() select { case err := <-errChan: fmt.Println("select error:", err) cancel() return nil, err case <-doneChan: fmt.Println("select done") } return result, nil } func main() { str := []string{"1", "2", "3", "4", "5", "6"} GetAll(context.Background(), str) fmt.Println("end") } ```` 当执行 cancel() 的时候,会关闭 detailChan,但是 goroutine 仍然会执行,并向 detailChan 中写数据,导致 panic。

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

947 次点击  ∙  2 赞  
加入收藏 微博
5 回复  |  直到 2019-09-21 15:46:49
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传