Help us understand the problem. What is going on with this article?

Golangのconst識別子iotaの紹介

More than 1 year has passed since last update.

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)
}

https://play.golang.org/p/IFkQnrwujr

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))
}

https://play.golang.org/p/851VyBBlgs

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

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

curepine
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした