简体   繁体   中英

WaitGroup with Channels

I've been playing around with this and came up with:

type Function struct{
    Function func(*TaskGroup, []interface{})
    Args []interface{}
}

type TaskGroup struct{
    Group sync.WaitGroup
    Functions []Function
}

func (x *TaskGroup) Start() {
    for _, Function := range x.Functions{
        x.Group.Add(1)
        go Function.Function(x, Function.Args)
    }
    x.Group.Wait()
}

In order to work easier with mutliple functions I have to wait for.

The following tests will work and I do not understand why:

func auxC(x *TaskGroup, args []interface{}){
    defer x.Group.Done()
    messageOut := args[0].(chan string)
    messageOut <- "TestC"
}
func auxD(x *TaskGroup, args []interface{}){
    defer x.Group.Done()
    messageOut := args[0].(chan string)
    messageOut <- "TestD"
}

func TestTaskGroupBaseB(t *testing.T) {
    messageC := make(chan string, 1)
    messageD := make(chan string, 1)

    tg := TaskGroup{
        Functions: []Function{
            {auxC, []interface{}{messageC}},
            {auxD, []interface{}{messageD}},
        },
    }
    tg.Start()

    fmt.Println(<- messageC)
    fmt.Println(<- messageD)

    time.Sleep(100 * time.Millisecond)
}

I first tried with unbuffered channels like this:

messageC := make(chan string)
messageD := make(chan string)

But it doesn't work it just gets stuck forever without doing anything, so i have a few questions:

  1. Why do buffered channels with size 1 work while unbuffered doesn't?
  2. Isn't unbuffered by default size 1?

Refactored code, see comments:

Main/Tests:

func auxC(args []interface{}){
    messageOut := args[0].(chan string)
    messageOut <- "TestC"
}
func auxD(args []interface{}){
    messageOut := args[0].(chan string)
    messageOut <- "TestD"
}

func TestTaskGroupBaseB(t *testing.T) {
    messageC := make(chan string,1)
    messageD := make(chan string,1)

    tg := TaskGroup{
        Functions: []Function{
            {auxC, []interface{}{messageC}},
            {auxD, []interface{}{messageD}},
        },
    }
    tg.Wait()

    fmt.Println(<- messageC)
    fmt.Println(<- messageD)

    time.Sleep(100 * time.Millisecond)
}

Task Group:

type Function struct{
    Function func([]interface{})
    Args []interface{}
}

type TaskGroup struct{
    Group sync.WaitGroup
    Functions []Function
}

func (x *TaskGroup) Wait() {
    for _, function := range x.Functions{
        x.Group.Add(1)
        go func(x *TaskGroup, f Function){
            defer x.Group.Done()
            f.Function(f.Args)
        }(x, function)
    }
    x.Group.Wait()
}

Using a channel with buffer size 1, first write buffers data, then goroutines end and you can read the buffered data in the main goroutine.

When channel size is zero a write to the channel blocks until another goroutine reads from it. So both of your goroutines are waiting to write the channels. If you move the Wait() call after the channel reads in main it should work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM