配列の中身つ1つに対してPrintf系のフォーマットにかけることを考えます。
さらにそれを利用して独自のSprintf関数を作ったりしてみる。
まず配列をそのまま渡してしまうと、配列自体を1つの型としてフォーマットしてしまうため...
オペレータを使って渡してみる。
1 2 3 4 5 6 |
params := []string{"a", "b"} str := fmt.Sprintf("%s, %s", params) //[a b], %!s(MISSING str := fmt.Sprintf("%s, %s", params...) //error |
string配列を渡そうとしたらエラーになってしまった。
cannot use params (type []string) as type []interface {} in argument to fmt.Sprintf
関数を見てみると第2引数以降をインターフェース配列として受け取っている。
1 |
Sprintf func(format string, a ...interface{}) string |
つまりこんな感じで渡すことができる。
1 2 3 4 |
params := []interface{}{"a", "b"} str := fmt.Sprintf("%s, %s", params...) fmt.Println(str) //a, b |
interface{}
型の配列なのでかなり変な感じがする。
渡し方の特性上、追加するときは配列そのものに追加しないといけない。
1 2 3 4 5 6 7 8 9 |
//NG1 str := fmt.Sprintf("%s, %s, %s, %s", params...,"c", "d") //NG2 str := fmt.Sprintf("%s, %s, %s, %s", append(params, "c", "d")...) //OK params = append(params, "c", "d") str := fmt.Sprintf("%s, %s, %s, %s", params...) |
これを踏まえてSprintfに追加処理を加えた独自Sprintfを書いてみます。
前回やった桁数不明の数値を指数表記にせずに文字列にする方法を組み込みます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
func mySprintf(format string, a ...interface{}) string { _a := make([]interface{}, 0, len(a)) for _, arg := range a { switch v := arg.(type) { case float64: _a = append(_a, strconv.FormatFloat(v, 'f', -1, 64)) default: _a = append(_a, arg) } } format = strings.Replace(format, "%f", "%s", -1) return fmt.Sprintf(format, _a...) } |
1 2 3 4 5 |
fmt.Println(fmt.Sprintf("%d - %f + %f", 1000000, 0.0000001, 0.01)) //1000000 - 0.000000 + 0.010000 fmt.Println(mySprintf("%d - %f + %f", 1000000, 0.0000001, 0.01)) //1000000 - 0.0000001 + 0.01 |
苦労した数値の文字化が簡単にできました。
format
に関してはかなり面倒な実装になっているので今回は簡単な置き換え。
switch
内をいじれば他の型についてもやりたいように変更できます。