お題
Goの1.10からstrings.Builderというのが追加されて文字列連結が効率的になった様子。
ただ、JavaのStringBuilderを使ってきた身からするとメソッドチェーンでつなげていきたい。Goの作法に則っていなくても。
というわけで、お試しでラッパー作ってみた。
開発環境
# OS
$ $ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
# 言語
$ go version
go version go1.11.4 linux/amd64
実践
strings.Builderラッパー
こんな感じ。
// NewStringBuilder ...
func NewStringBuilder() StringBuilder {
return &stringBuilder{sb: strings.Builder{}, anyErrors: []error{}}
}
// StringBuilder ...
type StringBuilder interface {
Append(str string) StringBuilder
AppendInt(num int) StringBuilder
ToString() string
Errors() []error
}
type stringBuilder struct {
sb strings.Builder
anyErrors []error
}
// Append ...
func (b *stringBuilder) Append(str string) StringBuilder {
_, err := b.sb.WriteString(str)
if err != nil {
b.anyErrors = append(b.anyErrors, err)
}
return b
}
// AppendInt ...
func (b *stringBuilder) AppendInt(num int) StringBuilder {
_, err := b.sb.WriteString(fmt.Sprintf("%d", num))
if err != nil {
b.anyErrors = append(b.anyErrors, err)
}
return b
}
// ToString ...
func (b *stringBuilder) ToString() string {
if len(b.anyErrors) > 0 {
return ""
}
return b.sb.String()
}
// Errors ...
func (b *stringBuilder) Errors() []error {
return b.anyErrors
}
ただラップして、ご丁寧にWriteString
をAppend
と呼び変え、WriteString
がerror
を返すので、返されたエラーをいったん溜めておくようにしただけ。
実行
以下のようにmainで実行
type book struct {
ID int
Name string
Author string
Price int
}
func main() {
b := book{
ID: 1,
Name: "何かの本",
Author: "著者A",
Price: 100,
}
builder := NewStringBuilder()
jsonLog := builder.
Append(`{`).
Append(`"book": {`).
Append(`"id": `).AppendInt(b.ID).Append(", ").
Append(`"name": `).Append(b.Name).Append(", ").
Append(`"author": `).Append(b.Author).Append(", ").
Append(`"price": `).AppendInt(b.Price).Append("").
Append(`}`).
Append(`}`).
ToString()
fmt.Println(jsonLog)
}
実行結果
{"book": {"id": 1, "name": 何かの本, "author": 著者A, "price": 100}}
まとめ
Goの「エラーを戻り値で返す主義」と「メソッドチェーン」は、やっぱり相容れないものがある。
Goらしく書くならメソッドチェーンは避けるべきかな。。。