如果要產生假資料的話,亂數產生器是必要的。
今天先建立一個中文字的資料結構,然後再由 Go 產生亂數來選擇中文字,最後再經由 Command 輸出。
分析
首先要了解亂數是怎麼產生的,查了一下資料,看來 math/rand
就夠用了。
因為要給種子,所以查了一下時間 time
微秒的取法,結果找到奈秒的:
t := time.Now().UnixNano()
fmt.Println(t)
|
另外官方範例有展示 math/rand
的兩種用法,一種是全域的:
rand.Seed(time.Now().UnixNano())
fmt.Println(rand.Int())
|
另一種是用種子取得結構後,再開始產生亂數:
t := time.Now().UnixNano() r1 := rand.New(rand.NewSource(t)) r2 := rand.New(rand.NewSource(t))
fmt.Println(r1.Int()) fmt.Println(r1.Int()) fmt.Println(r1.Int()) fmt.Println(r2.Int()) fmt.Println(r2.Int()) fmt.Println(r2.Int())
|
輸出如下:
6097576665619044690 3051760752526126731 1042372804046134795 6097576665619044690 3051760752526126731 1042372804046134795
|
亂數看來沒問題了,再來可以建一個模組存放這些中文的靜態資料。
開工
首先建目錄 provider
,在下面先建資源檔 resource.go
:
package provider
var names = []string{ "金太郎", "金城武", "金智賢", }
|
這個檔比較沒什麼問題,下一個建主要產生器 generator
:
package provider
import ( "math/rand" "time" )
type Generator struct { rand *rand.Rand }
func (generator *Generator) Name() string { length := len(names)
return names[generator.rand.Intn(length)] }
func Create() Generator { r := rand.New(rand.NewSource(time.Now().UnixNano()))
return Generator{ rand: r, } }
|
這裡說明一下,Create()
是建立 Generator
結構,類似工廠方法。
Generator
則有著亂數產生器,可以自行建立亂數,也可以依亂數取得資源內的內容。
其中 rand.Intn(length)
會回傳 0 ~ length 中的一個數字。剛好可以拿來當 key。
原始碼的 Action 函式如下:
func(c *cli.Context) error { num, err := strconv.Atoi(c.String("num"))
if err != nil { return err }
fmt.Println("Generate " + strconv.Itoa(num))
generator := provider.Create()
for i := 0; i < num; i++ { fmt.Println(generator.Name()) }
return nil },
|
展示
使用 go run 執行:
$ go run main.go generate Generate 10 金城武 金太郎 金智賢 金智賢 金智賢 金太郎 金智賢 金智賢 金智賢 金太郎
|
詳細程式可以參考 PR Day 18
參考資料