欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語言實現權重抽獎系統的項目實踐

 更新時間:2025年04月17日 11:06:49   作者:程序智享家  
本文主要介紹了Go語言實現權重抽獎系統的項目實踐,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

需求描述

  • 支持配置多個獎品及對應權重
  • 保證抽獎結果符合權重概率分布
  • 防止重復中獎
  • 提供抽獎結果驗證接口

完整實現代碼

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"` // 權重值(非百分比)
}

// 抽獎系統
type LotterySystem struct {
    prizes       []Prize
    totalWeight  int
    issuedPrizes map[int]bool
    mu           sync.Mutex
}

// 初始化抽獎系統
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),
    }
}

// 安全隨機數生成
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")
    }

    // 生成隨機數
    randomNum, err := secureRandom(ls.totalWeight)
    if err != nil {
        return nil, err
    }

    // 權重選擇
    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服務
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("抽獎服務已啟動,監(jiān)聽端口 8080")
    http.ListenAndServe(":8080", nil)
}

核心功能說明

權重算法:

// 權重選擇邏輯
current := 0
for _, p := range ls.prizes {
    current += p.Weight
    if randomNum < current {
        return &p
    }
}
  • 使用累計權重區(qū)間算法
  • 保證概率分布準確性

安全隨機數:

// 使用crypto/rand生成安全隨機數
func secureRandom(max int) (int, error) {
    n, err := rand.Int(rand.Reader, big.NewInt(int64(max)))
    // ...
}
  • 避免使用math/rand的可預測性
  • 滿足安全抽獎需求

并發(fā)控制:

var mu sync.Mutex

func (ls *LotterySystem) Draw() {
    ls.mu.Lock()
    defer ls.mu.Unlock()
    // ...
}
  • 使用互斥鎖保證線程安全
  • 防止并發(fā)抽獎導致的數據競爭

防重復機制:

issuedPrizes map[int]bool
  • 使用內存映射記錄已發(fā)放獎品
  • 生產環(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--
}

運行測試

啟動服務:

go run main.go

測試抽獎:

curl http://localhost:8080/draw
# 示例返回:{"id":3,"name":"三等獎","weight":20}

概率驗證測試:

curl http://localhost:8080/test
# 返回萬次抽獎結果分布

關鍵優(yōu)化點

性能優(yōu)化:

  • 使用預計算總權重值
  • 內存級鎖粒度控制
  • 對象池復用

安全增強:

  • JWT用戶身份驗證
  • 抽獎頻率限制
  • 敏感操作日志

業(yè)務擴展:

  • 支持不同抽獎活動
  • 獎品有效期管理
  • 中獎名單公示

到此這篇關于Go語言實現權重抽獎系統的項目實踐的文章就介紹到這了,更多相關Go語言 權重抽獎系統內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Go并發(fā)之RWMutex的源碼解析詳解

    Go并發(fā)之RWMutex的源碼解析詳解

    RWMutex是一個支持并行讀串行寫的讀寫鎖。RWMutex具有寫操作優(yōu)先的特點,寫操作發(fā)生時,僅允許正在執(zhí)行的讀操作執(zhí)行,后續(xù)的讀操作都會被阻塞。本文就來從源碼解析一下RWMutex的使用
    2023-03-03
  • Go1.20最新資訊go?arena手動管理內存鴿了

    Go1.20最新資訊go?arena手動管理內存鴿了

    由于過于繁雜,Go?核心團隊成員@Ian?Lance?Taylor,也表態(tài):目前尚未做出任何決定,也不可能在短期內做出任何決定,可以認為這個提案基本鴿了,今天這篇文章就是給大家同步目前的情況
    2023-11-11
  • go語言實現聊天服務器的示例代碼

    go語言實現聊天服務器的示例代碼

    這篇文章主要介紹了go語言實現聊天服務器的示例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • 詳解Golang中文件系統事件監(jiān)聽

    詳解Golang中文件系統事件監(jiān)聽

    文件系統事件是指文件系統相關的各種操作和狀態(tài)變化,當一個應用層的進程操作文件或目錄時,會觸發(fā)system call,內核的notification子系統可以守在那里,把該進程對文件的操作上報給應用層的監(jiān)聽進程,這篇文章主要介紹了Golang之文件系統事件監(jiān)聽,需要的朋友可以參考下
    2024-01-01
  • Golang使用gin模板渲染base64圖片出現#ZgotmplZ的解決辦法

    Golang使用gin模板渲染base64圖片出現#ZgotmplZ的解決辦法

    這篇文章主要介紹了Golang使用gin模板渲染base64圖片出現#ZgotmplZ的的場景復現和解決辦法,文中通過代碼示例講解的非常詳細,對大家解決問題有一定的幫助,需要的朋友可以參考下
    2024-05-05
  • Golang中的Unicode與字符串示例詳解

    Golang中的Unicode與字符串示例詳解

    這篇文章主要給大家介紹了關于Golang中Unicode與字符串的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Golang具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2020-05-05
  • go語言go?func(){select{}}()的用法

    go語言go?func(){select{}}()的用法

    本文主要介紹了go語言go?func(){select{}}()的用法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-02-02
  • Go1.18新特性工作區(qū)模糊測試及泛型的使用詳解

    Go1.18新特性工作區(qū)模糊測試及泛型的使用詳解

    這篇文章主要為大家介紹了Go?1.18新特性中的工作區(qū)?模糊測試?泛型使用進行詳細講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • Go語言什么時候該使用指針

    Go語言什么時候該使用指針

    本文主要介紹了Go語言什么情況下應該使用指針,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Go 中 slice 的 In 功能實現探索

    Go 中 slice 的 In 功能實現探索

    這篇文章主要介紹了Go 中 slice 的 In 功能實現探索,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09

最新評論