workerpool icon indicating copy to clipboard operation
workerpool copied to clipboard

Bug - strange behavior

Open surjit opened this issue 3 years ago • 1 comments

Ubuntu 20.04 LTS go version go1.19.3 linux/amd64 github.com/gammazero/workerpool v1.1.3

package main

import (
	"fmt"
	"github.com/gammazero/workerpool"
)

type JobAccount struct {
	Id       int
	Username string
}

func main() {
	list := []string{
		"demo1", "demo2", "demo3",
	}

	var accounts []*JobAccount

	for k, v := range list {
		accounts = append(accounts, &JobAccount{
			Id:       k,
			Username: v,
		})
	}

	wp := workerpool.New(2)

	for _, account := range accounts {
		fmt.Printf("loop %+v\n", account.Username)

		wp.Submit(func() {
			fmt.Printf("go rountine %+v\n", account.Username)
		})
	}

	wp.StopWait()
}

Here actual output

loop demo1
go rountine demo1
loop demo2
loop demo3
go rountine demo3
go rountine demo3

I was expecting

loop demo1
go rountine demo1
loop demo2
loop demo3
go rountine demo2
go rountine demo3

surjit avatar Jan 28 '23 00:01 surjit

This isn't a bug in workerpool, it's how go works.

	for _, account := range accounts { // <- here you are assigning a pointer to a variable named account
		fmt.Printf("loop %+v\n", account.Username) // <- you'll always get the expected answer here

		wp.Submit(func() {
                        // here, you are capturing the outer pointer to "account"
                        // by the time this function is actually run, it may have a different value. That's your problem.
			fmt.Printf("go rountine %+v\n", account.Username)
		})
	}

This is actually clearly documented right in the sample:

	for _, r := range requests {
		r := r // <-- 🙂
		wp.Submit(func() {
			fmt.Println("Handling request:", r)
		})
	}

See also http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/index.html#closure_for_it_vars

See also https://github.com/gammazero/workerpool/issues/67

hut8 avatar Feb 26 '23 01:02 hut8