LoginSignup
90

More than 5 years have passed since last update.

Golangのconst識別子iotaの紹介

Last updated at Posted at 2016-12-09

Go AdventCalendar2016の9日目(2016/12/09)の記事です。
前の記事は massa142さんの「Hacker Newsを一覧表示してくれるCLIツールを書いた」でした。

はじめに

ちょっとマイナーなGolangの言語仕様である、iotaについて紹介します。
結構入門書とかにも書いてあるんですが、読み飛ばしがちなんですよね。
特に新規性がある内容ではないので、タイトルでもう知ってるわ!という方はそっ閉じしてもらって大丈夫です。

iotaとは

iotaは、定数宣言(const)の内での既定された識別子です。
型なしの整数の連番を生成します。具体例を見ましょう。

package main

import "fmt"

const (
    zero  = iota
    one   = iota
    two   = iota
    three = iota
)

func main() {
    fmt.Printf("zero:%v\n", zero)
    fmt.Printf("one:%v\n", one)
    fmt.Printf("two:%v\n", two)
    fmt.Printf("three:%v\n", three)
}

https://play.golang.org/p/9uycXahdRE
結果はこうです。

zero:0
one:1
two:2
three:3

最初の1つのみ設定しておけば、あとは省略することが可能です。
(ちなみにこれはiotaに限らず、定義する値を省略すると、直前に定義されたものが流用されます。)

package main

import "fmt"

const (
    zero  = iota
    one
    two
    three
)

func main() {
    fmt.Printf("zero:%v\n", zero)
    fmt.Printf("one:%v\n", one)
    fmt.Printf("two:%v\n", two)
    fmt.Printf("three:%v\n", three)
}

ConstSpec毎にインクリメントされ、次の予約語constが現れたらリセットされます。

const (
    zero = iota // 0
    one  = iota // 1
)
const (
    two   = iota // 0
    three = iota // 1
)

また、constの中であれば、式のなかで利用することもできます。

const (
    zero  = iota * iota // 0
    one                 // 1
    two                 // 4
    three               // 9
)
const (
    zero  = iota != 1 // true
    one               // false
    two               // true
    three             // true
)

他の定義と混在しても、ConstSpecのたびにインクリメントしています。

const (
    zero  = "zero" // zero
    one   = iota   // 1
    two   = "弐"    // 弐
    three = iota   // 3
)

また、const内で先にiotaを設定すると結構面白かったです。iotaの機能ではなく、定数が優先されました。

const (
    iota  = "iota" // iota
    zero  = iota   // iota
    one            // iota
    two            // iota
    three          // iota
)

型なしの整数なのでconstで使用した定数をTypeOfするとintになります。

package main

import (
    "fmt"
    "reflect"
)

const (
    zero = iota
)

func main() {
    fmt.Printf("zero type:%v\n", reflect.TypeOf(zero))
}

ですので、このような定義をすると変換できないのでコンパイルエラーとなります。

const(
    zero string = iota
)

.../main.go:6: cannot convert 0 to type string

Githubではこういう感じで使われてたよ

軽く見た感じ単純にフラグ的なものをconstするソースが殆どだったんですが、

type ByteSize float64

const (
    _           = iota // ignore first value by assigning to blank identifier
    KB ByteSize = 1 << (10 * iota)
    MB
    GB
    TB
    PB
    EB
    ZB
    YB
)

https://github.com/golang/go/blob/964639cc338db650ccadeafb7424bc8ebb2c0f6c/doc/progs/eff_bytesize.go
このソースはシフト演算子でByteSize型の値作ってて面白かったです。

おわりに

というわけで、iota列挙子のご紹介でした。

ひらめき次第で楽しく使えそうなので、こういうとこで使うと便利、こういう感じで使ってるとこあった、などあったら教えていただけるとうれしいです。

参考文献

Iota · golang/go Wiki
https://github.com/golang/go/wiki/Iota

The Go Programming Language Specification - Iota
https://golang.org/ref/spec#Iota

Yosssi's blog - Go言語の識別子iotaについて
http://yosssi.hatenablog.com/entry/2014/01/27/000135

Big Sky:: Recent entries from same category
http://mattn.kaoriya.net/software/lang/go/20141208093852.htm

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
90