💻
iota 出現時の値はゼロとは限らない
今回も小ネタ。
「第16回『プログラミング言語Go』オンライン読書会」の『プログラミング言語Go』の 3.6.1章「定数生成器 iota」で出た話で,書籍には
const 宣言では、 iota の値はゼロから始まり、順番に個々の項目ごとに1増加します。
とあるが,ここで翻訳者であり読書会の主宰である柴田芳樹さんの解説があった。今回はその話。
元々 const では
package main
import "fmt"
const (
one = 1
two
three
four
)
func main() {
fmt.Println(one, two, three, four)
// Output:
// 1 1 1 1
}
と書くと直前の定数と同じ値がセットされるという特徴がある。この性質と定数生成器 iota を組み合わせることで
package main
import "fmt"
const (
one = 1 + iota
two
three
four
)
func main() {
fmt.Println(one, two, three, four)
// Output:
// 1 2 3 4
}
ひとつづつインクリメントした値をセットすることができる。じゃあ iota の初期値は常にゼロなのかというと,そこは微妙で,たとえば
package main
import "fmt"
const (
zero = "0"
one = 1
two
three
four = iota
)
func main() {
fmt.Println(zero, one, two, three, four)
// Output:
// 0 1 1 1 4
}
てな風に書くと iota 出現時の値は 4 になる。つまり iota は出現する前から(見かけ上[1])カウントしているわけだ。
iota 出現時の値が常にゼロだと思いこんで,うっかり
package main
import "fmt"
const (
one = 1 + iota
two
three
four
zero = iota
)
func main() {
fmt.Println(zero, one, two, three, four)
// Output:
// 4 1 2 3 4
}
てなコードを書くと zero
がゼロにならず「とひょーん」となってしまう。恥ずかしい話だが,実は昔このパターンでハマったことがあるのだ(テストが通らず,しばらく悩んだ)。
これを回避するには
package main
import "fmt"
const (
one = 1 + iota
two
three
four
)
const (
zero = iota
)
func main() {
fmt.Println(zero, one, two, three, four)
// Output:
// 0 1 2 3 4
}
という感じに iota 毎に別の const 宣言で括ってやればよい。
-
正しくは iota はカウンタではない。この辺の話については拙文「定数生成器 iota についてちゃんと書く」で纒めてみた。 ↩︎
Discussion