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