如果要產生假資料的話,亂數產生器是必要的。
今天先建立一個中文字的資料結構,然後再由 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