Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go: transfer var into anonymous function

Tags:

go

I am having trouble transferring a variable into an anonymous function. Is there a solution?

import  "github.com/lxn/walk"

***

var openAction [12]*walk.Action
for i := 0; i < 12; i++ {

    openBmp, err := walk.NewBitmapFromFile(_films[i][0])
    if err != nil {
        log.Printf("Open bitmap for buildBody() :%v\n", err)
    }
    openAction[i] = walk.NewAction()
    openAction[i].SetImage(openBmp)
    openAction[i].SetText(_films[i][2])
    openAction[i].Triggered().Attach( func(){
        exec(i)
    })
    mw.ToolBar().Actions().Add(openAction[i])
}

exec(i) where i always = 11

like image 509
Vladislav Avatar asked Apr 12 '12 02:04

Vladislav


People also ask

How do you make an anonymous function in Golang?

In Go language, you are allowed to assign an anonymous function to a variable. When you assign a function to a variable, then the type of the variable is of function type and you can call that variable like a function call as shown in the below example. You can also pass arguments in the anonymous function.

How do you pass an argument to anonymous function?

The syntax is simple: you can simply declare the anonymous function and make it execute by just calling it using the parenthesis at the end of the function. You can simply pass the parameters inside the immediate execution of the anonymous function as we have seen in the above example.

Can you assign anonymous function to a variable?

An anonymous function in javascript is not accessible after its initial creation. Therefore, we need to assign it to a variable, so that we can use its value later. They are always invoked (called) using the variable name. Also, we create anonymous functions in JavaScript, where we want to use functions as values.

Why use anonymous functions go?

Anonymous functions enable us to write function literals that denote a function value within any expression. The writing scheme and syntax is very similar to their named counterpart (regular functions) except that here, the function has no name succeeding the func keyword.


2 Answers

for i := 0; i < 12; i++ {
    i := i
    ...

Crazy as it looks, this is something you will see in Go code. It results from the way closures work and the way variables are scoped. Your anonymous function is a closure that captures i. Specifically, it is capturing a variable called i, not the current value of i, and it captures whatever i is in scope. In your original code this is the loop variable, which is the same variable for each iteration of the loop. All of your closures captured the same variable. The addition of i := i declares a new variable on each iteration. Now each closure will capture this new variable, and on each iteration it will be a different variable.

In a little more detail, the scope of the loop variable i is the for statement. This includes the loop block, but since the declaration of the loop variable i is outside of the block, declaring a new variable with the same name inside the block is legal and creates a new variable at that point in the block. The loop variable is then shadowed. Often a variable declared like this goes on the stack, but in this case compiler escape analysis sees that your closure is still referring to this block variable when it goes out of scope at the end of the block, and so the variable is placed on the heap. On each iteration, the block is reentered and a new variable i is placed on the heap.

like image 98
Sonia Avatar answered Nov 15 '22 05:11

Sonia


I think that this will get you what you want:

openAction[i].Triggered().Attach(func(x int) func() {
    return func() { exec(x) }
}(i))

The trick is to have your anonymous function return an anonymous function, and each created function will enclose each of the values of i.

like image 28
Adam Crossland Avatar answered Nov 15 '22 06:11

Adam Crossland