Go語言實現(xiàn)權(quán)重抽獎系統(tǒng)的項目實踐
更新時間:2025年04月17日 11:06:49 作者:程序智享家
本文主要介紹了Go語言實現(xiàn)權(quán)重抽獎系統(tǒng)的項目實踐,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
需求描述
- 支持配置多個獎品及對應(yīng)權(quán)重
- 保證抽獎結(jié)果符合權(quán)重概率分布
- 防止重復(fù)中獎
- 提供抽獎結(jié)果驗證接口
完整實現(xiàn)代碼
package main
import (
"crypto/rand"
"encoding/json"
"fmt"
"math/big"
"net/http"
"sync"
)
// 獎品配置
type Prize struct {
ID int `json:"id"`
Name string `json:"name"`
Weight int `json:"weight"` // 權(quán)重值(非百分比)
}
// 抽獎系統(tǒng)
type LotterySystem struct {
prizes []Prize
totalWeight int
issuedPrizes map[int]bool
mu sync.Mutex
}
// 初始化抽獎系統(tǒng)
func NewLotterySystem(prizes []Prize) *LotterySystem {
total := 0
for _, p := range prizes {
total += p.Weight
}
return &LotterySystem{
prizes: prizes,
totalWeight: total,
issuedPrizes: make(map[int]bool),
}
}
// 安全隨機數(shù)生成
func secureRandom(max int) (int, error) {
n, err := rand.Int(rand.Reader, big.NewInt(int64(max)))
if err != nil {
return 0, err
}
return int(n.Int64()), nil
}
// 執(zhí)行抽獎
func (ls *LotterySystem) Draw() (*Prize, error) {
ls.mu.Lock()
defer ls.mu.Unlock()
if ls.totalWeight == 0 {
return nil, fmt.Errorf("no available prizes")
}
// 生成隨機數(shù)
randomNum, err := secureRandom(ls.totalWeight)
if err != nil {
return nil, err
}
// 權(quán)重選擇
current := 0
for _, p := range ls.prizes {
current += p.Weight
if randomNum < current {
if ls.issuedPrizes[p.ID] {
continue // 已發(fā)放的獎品跳過
}
ls.issuedPrizes[p.ID] = true
return &p, nil
}
}
return nil, fmt.Errorf("draw failed")
}
// HTTP服務(wù)
func main() {
// 初始化獎品池
prizes := []Prize{
{ID: 1, Name: "一等獎", Weight: 1},
{ID: 2, Name: "二等獎", Weight: 5},
{ID: 3, Name: "三等獎", Weight: 20},
{ID: 4, Name: "參與獎", Weight: 74},
}
lottery := NewLotterySystem(prizes)
http.HandleFunc("/draw", func(w http.ResponseWriter, r *http.Request) {
prize, err := lottery.Draw()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(prize)
})
fmt.Println("抽獎服務(wù)已啟動,監(jiān)聽端口 8080")
http.ListenAndServe(":8080", nil)
}核心功能說明
權(quán)重算法:
// 權(quán)重選擇邏輯
current := 0
for _, p := range ls.prizes {
current += p.Weight
if randomNum < current {
return &p
}
}- 使用累計權(quán)重區(qū)間算法
- 保證概率分布準確性
安全隨機數(shù):
// 使用crypto/rand生成安全隨機數(shù)
func secureRandom(max int) (int, error) {
n, err := rand.Int(rand.Reader, big.NewInt(int64(max)))
// ...
}- 避免使用math/rand的可預(yù)測性
- 滿足安全抽獎需求
并發(fā)控制:
var mu sync.Mutex
func (ls *LotterySystem) Draw() {
ls.mu.Lock()
defer ls.mu.Unlock()
// ...
}- 使用互斥鎖保證線程安全
- 防止并發(fā)抽獎導(dǎo)致的數(shù)據(jù)競爭
防重復(fù)機制:
issuedPrizes map[int]bool
- 使用內(nèi)存映射記錄已發(fā)放獎品
- 生產(chǎn)環(huán)境可替換為Redis等持久化存儲
擴展功能建議
概率可視化驗證:
// 添加測試端點驗證概率分布
http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
results := make(map[int]int)
for i := 0; i < 10000; i++ {
tempLottery := NewLotterySystem(prizes)
prize, _ := tempLottery.Draw()
results[prize.ID]++
}
json.NewEncoder(w).Encode(results)
})分布式鎖擴展:
// 使用Redis分布式鎖
func (ls *LotterySystem) DistributedDraw() {
lock := redis.NewLock("lottery_lock")
err := lock.Lock()
// ...抽獎邏輯...
lock.Unlock()
}獎品庫存管理:
type Prize struct {
// ...
Stock int // 新增庫存字段
}
func (ls *LotterySystem) Draw() {
// 檢查庫存
if p.Stock <= 0 {
continue
}
// 扣減庫存
p.Stock--
}運行測試
啟動服務(wù):
go run main.go
測試抽獎:
curl http://localhost:8080/draw
# 示例返回:{"id":3,"name":"三等獎","weight":20}概率驗證測試:
curl http://localhost:8080/test # 返回萬次抽獎結(jié)果分布
關(guān)鍵優(yōu)化點
性能優(yōu)化:
- 使用預(yù)計算總權(quán)重值
- 內(nèi)存級鎖粒度控制
- 對象池復(fù)用
安全增強:
- JWT用戶身份驗證
- 抽獎頻率限制
- 敏感操作日志
業(yè)務(wù)擴展:
- 支持不同抽獎活動
- 獎品有效期管理
- 中獎名單公示
到此這篇關(guān)于Go語言實現(xiàn)權(quán)重抽獎系統(tǒng)的項目實踐的文章就介紹到這了,更多相關(guān)Go語言 權(quán)重抽獎系統(tǒng)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go1.20最新資訊go?arena手動管理內(nèi)存鴿了
由于過于繁雜,Go?核心團隊成員@Ian?Lance?Taylor,也表態(tài):目前尚未做出任何決定,也不可能在短期內(nèi)做出任何決定,可以認為這個提案基本鴿了,今天這篇文章就是給大家同步目前的情況2023-11-11
Golang使用gin模板渲染base64圖片出現(xiàn)#ZgotmplZ的解決辦法
這篇文章主要介紹了Golang使用gin模板渲染base64圖片出現(xiàn)#ZgotmplZ的的場景復(fù)現(xiàn)和解決辦法,文中通過代碼示例講解的非常詳細,對大家解決問題有一定的幫助,需要的朋友可以參考下2024-05-05

