使用fx.Parallel方法并发执行函数时遇到的惰性计算的坑
错误的写法
package scripts_stroage import ( "encoding/hex" "fmt" "github.com/zeromicro/go-zero/core/fx" "math/rand" "sync" "testing" "time" ) var fns []func() var lock sync.Mutex var allFriends []string type student struct { Name string Age int Friends []string } func init() { rand.Seed(time.Now().UnixNano()) } func RandStr2(n int) string { result := make([]byte, n/2) rand.Read(result) return hex.EncodeToString(result) } func genStudents() []student { ret := make([]student, 0) for i := 1; i < 5; i++ { currStu := student{ Name: fmt.Sprintf("whw_%v", i), Age: i + 10, Friends: []string{RandStr2(3), RandStr2(4)}, } ret = append(ret, currStu) } return ret } func TestT11T(t *testing.T) { stus := genStudents() fmt.Println(stus) // 注意:这里有 "惰性计算" 的坑 for _, stu := range stus { if stu.Age > 13 { fns = append(fns, func() { lock.Lock() defer lock.Unlock() allFriends = append(allFriends, stu.Friends[0]) }) } else { fns = append(fns, func() { lock.Lock() defer lock.Unlock() allFriends = append(allFriends, stu.Friends...) }) } } // 并发去执行 fns 中的函数 fx.Parallel(fns...) fmt.Println("allFriends: ", allFriends) // 惰性计算的结果 // [{whw_1 11 [a5 f487]} {whw_2 12 [66 1c7f]} {whw_3 13 [56 88b3]} {whw_4 14 [04 d505]}] // allFriends: [04 04 d505 04 d505 04 d505] }
避免惰性计算的写法
package scripts_stroage import ( "encoding/hex" "fmt" "github.com/zeromicro/go-zero/core/fx" "math/rand" "sync" "testing" "time" ) var fns []func() var lock sync.Mutex var allFriends []string type student struct { Name string Age int Friends []string } func init() { rand.Seed(time.Now().UnixNano()) } func RandStr2(n int) string { result := make([]byte, n/2) rand.Read(result) return hex.EncodeToString(result) } func genStudents() []student { ret := make([]student, 0) for i := 1; i < 5; i++ { currStu := student{ Name: fmt.Sprintf("whw_%v", i), Age: i + 10, Friends: []string{RandStr2(3), RandStr2(4)}, } ret = append(ret, currStu) } return ret } func TestT11T(t *testing.T) { stus := genStudents() fmt.Println(stus) for _, stu := range stus { // 避免惰性计算:这里用临时变量去接收~ currStu := stu if currStu.Age > 13 { fns = append(fns, func() { lock.Lock() defer lock.Unlock() allFriends = append(allFriends, currStu.Friends[0]) }) } else { fns = append(fns, func() { lock.Lock() defer lock.Unlock() allFriends = append(allFriends, currStu.Friends...) }) } } // 并发去执行 fns 中的函数 fx.Parallel(fns...) fmt.Println("allFriends: ", allFriends) // 正确的结果 // [{whw_1 11 [37 41f0]} {whw_2 12 [cf 4895]} {whw_3 13 [d2 773b]} {whw_4 14 [e0 9ebd]}] // allFriends: [e0 37 41f0 cf 4895 d2 773b] }
~~~