并发如何与匿名函数一起工作? 走

I'm trying to loop through a list (e.g. sql rows) and fire go routines for each row. The issue is that the values passed to the function are not evaluated at the runtime so depending by how much time the function takes to execute it may use whatever value is on one of the next(s) rows instead the current one.

I'm aware that I could extract the function in a normal one and pass the arguments but I still want to share some global variables(to avoid many function arguments) thus the need to use an anonymous function. Still it's also confusing to me that the anonymous function takes variables from the environment while it's being executed because as far as I understand it is supposed to be executed in a separate routines just like & in unix programs, the communication being done only through channels.

The question is how do I make the anonymous function to receive a copy of vc and use it during runtime ?

package main

import "fmt"
import "time"


type mystruct struct {
    i int
    s string
}

func main() {

    vc := mystruct{}
    vc.i = 1
    vc.s = "hi"
    gl := "this is global"
    for i := 1; i < 4; i++ {

    go func() {
        vc.i++
        time.Sleep(1 * time.Second)

        fmt.Printf("row specific is %v, global is %v", vc, gl)
    }()

    }
    time.Sleep(2 * time.Second)

}

Play here

I honestly don't understand what you're trying to achieve, however, if your only goal is to make a copy of the variable, you can just pass it to the go func like this:

for i := 1; i < 4; i++ {
    go func(vc mystruct) {
        vc.i++
        //time.Sleep(1 * time.Second)

        fmt.Printf("row specific is %v, global is %v
", vc, gl)
    }(vc)
}

The code is accessing the same struct from multiple goroutines . You need to protect the struct with a mutex to govern the access to its value. Also you need to wait for all the goroutines to finish. Time.Sleep alone will not guarantee that. Use a Wait group. Here is a working example:

package main

import "fmt"
import "time"
import "strconv"
import "sync"

type mystruct struct {
    i int
    s string
    m sync.Mutex
}

func main() {

    vc := mystruct{}
    vc.i = 1
    vc.s = "hi"

    var wg sync.WaitGroup

    for i := 0; i < 4; i++ {
        wg.Add(1)
        go func() {
            vc.m.Lock()
            defer vc.m.Unlock()
            defer wg.Done()
            vc.i++
            time.Sleep(1 * time.Millisecond)
            vc.s = "good bye" + strconv.Itoa(vc.i)
            fmt.Printf("%v 
", vc)
        }()

    }

    wg.Wait()

}

Playground: http://play.golang.org/p/K6rnQQSA1c

It seems the only way is to create the struct within the anonymous function and copy the closure value . See the code below. As @fabrizioM advised you should use wg if you need synchronisation. However the question was not about that thus I don't include the wg.

Still I'm not sure if it's safe as the the copy of vc may take some time so edits/ improvements are still welcome

package main

import "fmt"
import "time"

type mystruct struct {
    i int
    s string
}

func main() {

    vc := mystruct{}
    vc.i = 1
    vc.s = "hi"

    for i := 1; i < 4; i++ {

        go func() {
            vc2 := vc
            vc.i++
            time.Sleep(1 * time.Second)

            fmt.Printf("%v
", vc2)
        }()

    }
    time.Sleep(2 * time.Second)

}

Click to play