How do I capture variables at time of an anonymous function’s execution?

Written by
reddit
Link to Post

https://www.reddit.com/r/golang/comments/bnvn5m/how_do_i_capture_variables_at_time_of_an/ by 

I’ve been learning Golang and as an exercise, I decided to try and implement a thread pool (or in this case a goroutine pool) because there seems to be a lot of implementations out there. I know my implementation is probably not that flexible or performant, but it was still helpful.

Like most languages these days, Go has support for higher-order functions, which comes in handy for this exercise. My pool’s execution function takes a function with the signature func(...interface{}) error and takes ...interface{} as arguments to the function provided. (all in all, func (pool *Pool) Exec(f func(...interface{}) error, args ...interface{}))

However, Go’s anonymous functions capture their environment at the time of their instantiation. I realized this is a problem for me when I was trying to benchmark my pool against the spin-up-a-goroutine-for-every-operation method using a concurrent Fibonacci function.

This is my control (no concurrency)

var a, b int64 = 0, 1 for i := 0; i < 100; i++ { a = a + b a, b = b, a } 

which produces the result 3736710778780434371

When I went to write the concurrent version, I realized that Go would capture the variables at instantiation time if I did something like this

var numAActual, numBActual int64 = 0, 1 pool := splash.NewPool(25, 50) // 25 goroutines, buffer size of 50 for j := 0; j < 100; j++ { pool.Exec(func(args ...interface{}) error { args[0].(int64) = args[0].(int64) + args[1].(int64) args[0].(int64), args[1].(int64) = args[1].(int64), args[0].(int64) return nil }, numAActual, numBActual) } 

or even this

var numAActual, numBActual int64 = 0, 1 pool := splash.NewPool(25, 50) // 25 goroutines, buffer size of 50 for j := 0; j < 100; j++ { pool.Exec(func(args ...interface{}) error { *args[0].(*int64) = *args[0].(*int64) + *args[1].(*int64) *args[0].(*int64), *args[1].(*int64) = *args[1].(*int64), *args[0].(*int64) return nil }, &numAActual, &numBActual) } 

Using the second version, I’ve gotten varying results, from 1 to -4953053512429003327 to 86267571272

It is obvious, both that this is wrong, and what is happening (at least I think it is), but I don’t know how to work around it.

Is there any way I can capture variables at the time an anonymous function is executed rather than when it is instantiated?

Any help is appreciated! Thanks!

submitted by /u/Spaceface16518
[link] [comments]

Article Tags:
· ·
Article Categories:
reddit

Leave a Reply