プロプログラマの皆様に於かれましては「何を当たり前のことを。。。」と思われるかもしれないが、仕事中めっちゃ詰まったので自分のためにメモ。
[ま か べ み ず き]
というスライスの先頭から5文字を取り出し、その末尾に な
をくっつけたかったので、以下のコードを書いた。
mizuki := []string{"ま", "か", "べ", "み", "ず", "き"} fmt.Println(mizuki) // -> [ま か べ み ず き] fmt.Println(append(mizuki[:5], "な")) // -> [ま か べ み ず な]
一件落着と言いたいところだが、このコードではappend後、mizuki
の中身までも書き換わってしまう。
fmt.Println(mizuki)
// ->[ま か べ み ず な]
考えてみれば当たり前のことで、append()はスライスに要素を追加するメソッドで、要素を追加したスライスを返してくれるメソッドではない。ず
のすぐ後ろに な
を追加しようとしたところ、き
を上書きしてしまった、んだと思う。
(詳しいことは公式ドキュメントに書かれてそうだが、ちょっと読むのめんどいので略)
対策としては、copy()を使ってスライスをコピーしてからappendする。
mizuki := []string{"ま", "か", "べ", "み", "ず", "き"} fmt.Println(mizuki) // -> [ま か べ み ず き] mizu := make([]string, 5) copy(mizu, mizuki[:5]) fmt.Println(append(mizu, "な")) // -> [ま か べ み ず な] fmt.Println(mizuki) // -> [ま か べ み ず き]
素晴らしい。
ここにも罠があって、コピー先のスライス(ここではmizu
)が十分な容量で初期化されていないと、コピーがうまくいかない。
mizuki := []string{"ま", "か", "べ", "み", "ず", "き"} var ma []string copy(ma, mizuki[:5]) fmt.Println(ma) // -> [] kabe := make([]string, 3) copy(kabe, mizuki[:5]) fmt.Println(kabe) // -> [ま か べ]
Go言語には罠がいっぱい!