使用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]
}

~~~

posted on 2023-05-27 12:27  江湖乄夜雨  阅读(54)  评论(0编辑  收藏  举报