🚶‍♂️

Go言語でテストデータを生成してみる

2024/12/03に公開

前置き

本記事は、みすてむずアドカレ レシピの3日目の記事です。

みすてむずアドカレ2024の一覧

(レシピじゃないけど許して)

今日何すんの?

  • 標準出力で、json形式で渡せるようにする。
  • sqlファイルを吐けるようにしてみる

つまり、読んで欲しい人は?

  • テストデータをGo言語で生成してみたい人
  • Go言語の可能性を感じてみたい人
    です。

注意事項

  • テストデータ生成は、brianvoe/gofakeitを使います。
    • go-faker/fakerとかもあったりしますが、更新が(執筆時に)一番新しかったので、gofakeitを使っています。
  • main.goしか使わないので、ここに貼っているコードをコピペしながら一緒にやってみたい人は、main.goに上書きしていってください。
  • エラーハンドリングは、基本的にpanicさせてハンドリングします。
    • 本当はダメですが、エラーハンドリングだけで1つ記事が書けてしまうので、勘弁してください。

0. Setup

  1. go mod init ~
  2. go get "github.com/spf13/cobra@v1.8.1"を実行
  3. go get "github.com/brianvoe/gofakeit/v7"を実行
    だけしてあればとりあえず行けるはず

1. ライブラリの動作確認

まずは、ちゃんと動くかの確認から。

package main

import (
	"fmt"

	"github.com/brianvoe/gofakeit/v7"
)

func main() {
	fmt.Println(gofakeit.Name())
}

実行例(毎回変わると思います)

$ go run main.go
Maude Hoeger

人の名前っぽいものが出力されると思います。
これで、gofakeitが動いているかの確認は完了です!
(もし動いていない場合、Setupができていないかもしれないので、もう一回プロジェクトを作り直してみてください。)

2. 一通り、名前とかの基本情報を生成させてみる

とりあえず、テストデータに必要そうな基本情報を全部生成させてみましょう!
(あとから、いらないデータは生成しないようにすればいいので...)

package main

import (
	"fmt"

	"github.com/brianvoe/gofakeit/v7"
)

func main() {
	fmt.Println("Name:", gofakeit.Name())
	fmt.Println("Email:", gofakeit.Email())
	fmt.Println("Phone:", gofakeit.Phone())
	fmt.Println("Country:", gofakeit.Country())
	fmt.Println("City:", gofakeit.City())
	fmt.Println("CreditCardNumber:", gofakeit.CreditCard().Number)
}

実行例(毎回変わると思います)

$ go run main.go
Name: Uriah Monahan
Email: erabrown@donnelly.org
Phone: 2563196012
Country: Falkland Islands (Malvinas)
City: Lubbock
CreditCardNumber: 6264090951199818

お手軽に一人分のデータが生成できました。
次は、データをjsonで出力していきましょう!

3. その前にちょっと工夫

このままではjsonに変換するのが大変なので構造体を作って楽をします。

さっき出力していたデータを一つの構造体の定義に起こしてみました。

type FakeUserData struct {
	Name             string // 名前
	Email            string // メールアドレス
	Phone            string // 電話番号
	Country          string // 国名
	City             string // 都市名
	CreditCardNumber string // クレジットカードの番号
}

この構造体を使って生成する関数を書いてみましょう!

実装例
func generateFakeData() FakeUserData {
	return FakeUserData{
		Name:             gofakeit.Name(),
		Email:            gofakeit.Email(),
		Phone:            gofakeit.Phone(),
		Country:          gofakeit.Country(),
		City:             gofakeit.City(),
		CreditCardNumber: gofakeit.CreditCard().Number,
	}
}

実は、お手軽にテストデータの入った構造体を生成してくれる機能もあったりするのですが、見やすいので今回はこっちで行きます。

お待たせしました。いよいよ、データをjsonで出力していきます。

4. json形式での出力

一番簡単なjson形式での出力をやっていきます。
ロジックとしては、

  1. データを生成
  2. jsonに変換
  3. 出力 (今回は、標準出力です。)
    の3ステップです。
    (なんなら、step1は前の章でやってますね)

Go言語はjsonの変換を簡単にできる仕組みが整っているので、たったコレだけで全てのステップが終わります。

~~~コード省略~~~

func main() {
	_j, err := json.Marshal(generateFakeData())
	if err != nil {
		panic(err)
	}
	fmt.Println(string(_j))
}

実行してみると、

$ go run main.go
{"Name":"Maxie Koelpin","Email":"adellveum@tillman.net","Phone":"8673761625","Country":"Burkina Faso","City":"Seattle","CreditCardNumber":"5577385768867704"}

みたいな、めっちゃ長い一文でjsonが表示されると思います。
これだけで、jsonへの変換は終わりです。

コード全体
package main

import (
	"encoding/json"
	"fmt"

	"github.com/brianvoe/gofakeit/v7"
)

type FakeUserData struct {
	Name             string
	Email            string
	Phone            string
	Country          string
	City             string
	CreditCardNumber string
}

func generateFakeData() FakeUserData {
	return FakeUserData{
		Name:             gofakeit.Name(),
		Email:            gofakeit.Email(),
		Phone:            gofakeit.Phone(),
		Country:          gofakeit.Country(),
		City:             gofakeit.City(),
		CreditCardNumber: gofakeit.CreditCard().Number,
	}
}

func main() {
	_j, err := json.Marshal(generateFakeData())
	if err != nil {
		panic(err)
	}
	fmt.Println(string(_j))
}

5. もっとたくさんデータを生成してみる。

ここからは、発展的な内容になります。
作るロジック

  1. 大量のデータを生成して、一旦リストに保存
  2. リストをjsonに変換する。
  3. ファイルに出力する。
    です。
    「さっきと同じ3stepしかないじゃん!」と思う方もいると思いますが、やることが増える分だけ大変になります。

まずは、大量のデータを生成して、一旦リストに保存します。

var (
	generateSize int = 100 // 生成する個数
)

func main() {
	fakeDataList := make([]FakeUserData, 0)
	for range generateSize {
		// データを生成して、リストの末尾に追加
		fakeDataList = append(fakeDataList, generateFakeData())
	}
}

コメントでの説明だけにしておきますが、一応これでデータの生成が完了しています。

あとは、さっきと同じ感じで...

func main() {
	fakeDataList := make([]FakeUserData, generateSize)
	for range generateSize {
		fakeDataList = append(fakeDataList, generateFakeData())
	}
	// === ここから先を追加した ===
	_j, err := json.Marshal(fakeDataList)
	if err != nil {
		panic(err)
	}
}

jsonに変換します!

最後は、ファイルへの保存です。

func main() {
	fakeDataList := make([]FakeUserData, 0)
	for range generateSize {
		fakeDataList = append(fakeDataList, generateFakeData())
	}
	_j, err := json.Marshal(fakeDataList)
	if err != nil {
		panic(err)
	}

	// === ここから先を追加した ===
	err = os.WriteFile("output.json", _j, 0644)
	if err != nil {
		panic(err)
	}
}

実行してみると、output.jsonという名前のjsonファイルができて、中に大量のデータが詰まっていると思います!

0644って何

作った人が読み書きできて、他の人は読み込みしかできない権限のこと!
(chmodとかを触ったことある人だったら見たことあるかも?)

おわり

駆け足になってしまいましたが、Go言語の可能性を少しでも感じていただけたら幸いです。

Discussion