Dev/Go

go 에서 time 없는 난수 발생

newtype 2022. 9. 19. 15:55

목적

  • 랜덤 대진표를 만드려고 한다. local 환경에서 만드는 경우는 난수 생성시 seed 값을 time을 사용하는데, go playground 에서 실행해보니 항상 같은 값이 나왔다. 아마도 go-playground가 일종의 vm 이라서 최초 생성시 동일한 시간으로 생성되는것으로 추정된다. go-playground 에서도 랜덤하게 생성되도록 구현해보자.

방법

  • 아래 예제에서는 crypto로 값을 seed를 초기화 하고 있다(init 함수).
  • go-playground 에서도 Run 버튼 옆에 "Go dev branch"를 선택해야 정상 동작한다.
package main

import (
    cryptoRand "crypto/rand"
    "encoding/binary"
    "fmt"
    mathRand "math/rand"
)

func init() {
    var b [8]byte
    _, err := cryptoRand.Read(b[:])
    if err != nil {
        panic("cannot seed math/rand package with cryptographically secure random number generator")
    }
    mathRand.Seed(int64(binary.LittleEndian.Uint64(b[:])))
}

func shuffle(list []string) []string {
    result := make([]string, len(list))
    copy(result, list)

    //math_rand.Seed(time.Now().UnixNano())  // vm 이라 seed가 시간이 같은듯.
    mathRand.Shuffle(len(result), func(i, j int) { result[i], result[j] = result[j], result[i] })
    return result
}

func main() {

    // 랜덤 대진표 생성
    list := []string{"Lee", "Woo", "Ju", "Chul", "Kim"}

    result := map[string]int{}

    for _, p1 := range shuffle(list) {
        for _, p2 := range shuffle(list) {
            play := ""
            if p1 > p2 {
                play = fmt.Sprintf("%s:%s", p1, p2)
            } else if p1 < p2 {
                play = fmt.Sprintf("%s:%s", p2, p1)
            }

            if len(play) > 0 {
                result[play] = 0
            }
        }
    }

    // 결과 출력
    for k, _ := range result {
        fmt.Println(k)
    }
}

참고

반응형