golang 随机概率的权重抽奖实现
package main import ( "encoding/json" "fmt" "math" "math/rand" "sort" "time" ) type Prize struct { PlayerId int64 Weight int } func main() { //设置奖项名称、权重等数组 var prizes = make([]*Prize, 0) for i := 0; i < 4; i++ { prize := &Prize{ PlayerId: int64(i) + 10000, Weight: (5 - i) * 10, } prizes = append(prizes, prize) } for _, v := range prizes { fmt.Println(v.PlayerId, v.Weight) } RandomDraw(prizes) } // 权重随机抽奖 func RandomDraw(prizes []*Prize) int64 { //权重累加求和 var weightSum int for _, v := range prizes { weightSum += v.Weight } //生成一个权重随机数,介于0-weightSum之间 rand.Seed(time.Now().UnixNano()) randomNum := rand.Intn(weightSum) //权重数组重组并排序 randomNumTmp := &Prize{PlayerId: -1, Weight: randomNum} concatWeightArr := make([]*Prize, 0) aa, _ := json.Marshal(prizes) _ = json.Unmarshal(aa, &concatWeightArr) fmt.Println("concatWeightArr:", concatWeightArr) concatWeightArr = append(concatWeightArr, randomNumTmp) //将随机数加入权重数组 //将包含随机数的新权重数组按从小到大(升序)排序 sort.Slice(concatWeightArr, func(i, j int) bool { return concatWeightArr[i].Weight < concatWeightArr[j].Weight }) sort.Slice(prizes, func(i, j int) bool { return prizes[i].Weight < prizes[j].Weight }) for _, v := range prizes { fmt.Println(*v) } //索引权重随机数的数组下标 var randomNumIndex = -1 //索引随机数在新权重数组中的位置 for p, v := range concatWeightArr { if v.Weight == randomNum { randomNumIndex = p } } randomNumIndexTmp := math.Min(float64(randomNumIndex), float64(len(prizes)-1)) //权重随机数的下标不得超过奖项数组的长度-1,重新计算随机数在奖项数组中的索引位置 randomNumIndex = int(randomNumIndexTmp) //取出对应奖项 res := prizes[randomNumIndex] //从奖项数组中取出本次抽奖结果 fmt.Println("本次抽奖结果:", res.PlayerId) return res.PlayerId }