doujingxi3356 2017-08-13 13:17
浏览 41
已采纳

Goroutine,回调和sync.WaitGroup

With the following code:

package main

import (
    "github.com/davecgh/go-spew/spew"
    "sync"
    "time"
)
func callbackWithTimeout(cbFunc func() ([]byte, error), timeout time.Duration) {
    defer wg.Done() //I don't want this function to know about sync.WaitGroup
    time.Sleep(timeout)
    d, e := cbFunc()
    spew.Dump(d)
    spew.Dump(e)
}
var wg sync.WaitGroup
func main() {
    wg.Add(1)
    go func() {
        cbFunc := func() ([]byte, error) {
            //I feel like I should be able to defer here instead
            return nil, nil
        }
        callbackWithTimeout(cbFunc, time.Duration(4*time.Second))
    }()
    println("some line")
    wg.Wait()
}

In function callbackWithTimeout, I don't want to use defer wg.Done() because it's not callbackWithTimeout()'s concern to wg.Done(). How do I go about implementing such a thing? i.e., remove any sync.WaitGroup in callbackWithTimeout? I have a bit of problem understanding the separation of concerns here as a callback'er function should not have to know about waitgroups but in this case it seems, I have no other choice?

I feel like it should be a caller's responsibility to wg.Done() (which in this case is the cbFunc) but lack any concise reference to documentation or ideas on how to implement it in Go because by definition, all a callback function does is call the function back. So, where I am doing it wrong?


Silly assumptions were made by yours truly during refactoring. Working code below. Many thanks.

package main

import (
    "errors"
    "github.com/davecgh/go-spew/spew"
    "sync"
    "time"
)

func callbackWithTimeout(cbFunc func() ([]byte, error), timeout time.Duration) {
    time.Sleep(timeout)
    d, e := cbFunc()
    spew.Dump(d)
    spew.Dump(e)
}

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        callbackWithTimeout(func() ([]byte, error) {
            b := []byte{1, 2, 3, 4}
            e := errors.New("error123")
            return b, e
        }, time.Duration(2*time.Second))
    }()
    println("some line")
    wg.Wait()
}
  • 写回答

1条回答 默认 最新

  • dqotv26286 2017-08-13 13:43
    关注

    May be like this?

    package main
    
    import (
        "sync"
        "time"
    
        "github.com/davecgh/go-spew/spew"
    )
    
    func callbackWithTimeout(cbFunc func() ([]byte, error), timeout time.Duration) {
        time.Sleep(timeout)
        d, e := cbFunc()
        spew.Dump(d)
        spew.Dump(e)
    }
    
    func main() {
        var wg sync.WaitGroup
    
        wg.Add(1)
    
        go func() {
            defer wg.Done() // move it here
            cbFunc := func() ([]byte, error) {
                //I feel like I should be able to defer here instead
                return nil, nil
            }
            callbackWithTimeout(cbFunc, time.Duration(4*time.Second))
        }()
    
        println("some line")
    
        wg.Wait()
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化