Golangのx.text.transformが便利だった
タイトルにある様にGolangのx.text.transformパッケージについてです。
このパッケージを使うと、readerやwriter内のデータを変換することができます。
良くある用途としては、readerで読み込んだ文字列の一部を変換して出力する、などがあると思います。
このパッケージを知った切っ掛けは以下のSlideShareです。
オススメの標準・準標準パッケージ20選
SlideShareで言及されていますが、パッケージのドキュメントは以下となり、Exampleを見れば使い方は分かるかと思います。
https://godoc.org/golang.org/x/text/transform#Transformer
https://godoc.org/github.com/tenntenn/text/transform#example-ReplaceTable
transformパッケージ自体については上記のリンクを見れば分かるのですが
自分が理解するために書いたサンプルソースもメモ代わりに上げておきます。
Golangで2つのgzファイルを連結してみる - ソースコードから理解する技術-UnderSourceCode
以前書いた上記のソースを改修したもので、2つの圧縮ファイル(中身はjson)を読み込み、値を変換して、圧縮ファイルに出力するものです。
サンプルソース
「sample1.json.gz」「sample2.json.gz」というgzファイルをあらかじめ用意しておき、実行すると中身が連結されて「result.json.gz」というファイルに出力されます。
sample1、sample2のjsonの中身は以下のような形式で、「abc」「fgh」をそれぞれ大文字に変換して出力しています。
sample1
{ "data":"abcde" }
sample2
{ "data":"fghij" }
メインの処理は以下のようになります。
package main import ( "compress/gzip" "fmt" "io" "log" "os" . "github.com/tenntenn/text/transform" "golang.org/x/text/transform" ) func write(br1 io.Reader, br2 io.Reader) error { writeFile, err := os.OpenFile("./result.json.gz", os.O_WRONLY|os.O_CREATE, 0644) if err != nil { return err } defer writeFile.Close() zw := gzip.NewWriter(writeFile) defer zw.Close() _, err = io.Copy(zw, br1) if err != nil { return err } _, err = zw.Write([]byte("\n")) if err != nil { return err } _, err = io.Copy(zw, br2) if err != nil { return err } return nil } func doTransform(zr *gzip.Reader, old, new []byte) io.Reader { t := ReplaceByteTable{ old, new, } return transform.NewReader(zr, ReplaceAll(t)) } func main() { readFile1, err := os.Open("./sample1.json.gz") if err != nil { log.Fatal(err) } defer readFile1.Close() zr1, err := gzip.NewReader(readFile1) if err != nil { log.Fatal(err) } defer zr1.Close() readFile2, err := os.Open("./sample2.json.gz") if err != nil { log.Fatal(err) } defer readFile2.Close() zr2, err := gzip.NewReader(readFile2) if err != nil { log.Fatal(err) } defer zr2.Close() tr1 := doTransform(zr1, []byte(`abc`), []byte(`ABC`)) tr2 := doTransform(zr2, []byte(`fgh`), []byte(`FGH`)) err = write(tr1, tr2) if err != nil { log.Fatal(err) } fmt.Println("-----finish-----") }
transformパッケージを使っているのはdoTransform()メソッドになります。
.gzファイルを読み込んだreaderを受け取り、変換するルールをReplaceByteTableに定義し、新たに別のreaderを生成して返却しています。
返却したreaderはwrite()に渡し、そのままresult.json.gzに出力しています。
このような感じにreaderの中身を変換して出力できることが確認できました。