Skip to content

Go 定数

定数の値は実行時に変更できません。一度代入すると変更できず、その値は以下のソースからのみ取得できます。

  • リテラル
  • 他の定数識別子
  • 定数式
  • 定数になる型変換
  • iota

定数は基本データ型のみで、以下にはできません。

  • 基本型以外の他の型(構造体、インターフェース、スライス、配列など)
  • 関数の戻り値

定数の値は変更できません。変更するとコンパイルできません。

初期化

定数の宣言には const キーワードが必要です。定数の宣言時には値を初期化する必要があり、定数の型は省略できます。

go
const name string = "Jack" // リテラル

const msg = "hello world" // リテラル

const num = 1 // リテラル

const numExpression = (1+2+3) / 2 % 100 + num // 定数式

単に宣言するだけで値を指定しないと、コンパイルできません。

go
const name string

コンパイラエラー

missing init expr for name

定数のバッチ宣言では () で囲んで可読性を向上できます。() は複数存在してグループ分けの効果を達成できます。

go
const (
   Count = 1
   Name  = "Jack"
)

const (
   Size = 16
   Len  = 25
)

同じ定数グループ内で、値が代入された定数の後にある定数は値を代入する必要がありません。その値はデフォルトで前の値になります。

go
const (
  A = 1
  B // 1
  C // 1
  D // 1
  E // 1
)

iota

iota は組み込みの定数識別子で、通常は定数宣言内の型なし整数序数を表すために使用され、一般的には括弧内で使用されます。

go
const iota = 0

いくつかの使用例を見てみましょう。

go
const (
   Num = iota // 0
   Num1 // 1
   Num2 // 2
   Num3 // 3
   Num4 // 4
)

このようにも書けます。

go
const (
   Num = iota*2 // 0
   Num1 // 2
   Num2 // 4
   Num3 // 6
   Num4 // 8
)

さらにこうもできます。

go
const (
   Num = iota << 2*3 + 1 // 1
   Num1 // 13
   Num2 // 25
   Num3 = iota // 3
   Num4 // 4
)

上記のいくつかの例から、iota は増加していくことがわかります。最初の定数で iota 値の式を使用すると、後続の定数には序号値の変化に基づいて自動的に値が代入され、新しい const でリセットされるまで続きます。この序号其实就是コードの相対行番号で、現在のグループの開始行からの相対行番号です。以下の例を見てください。

go
const (
  Num  = iota<<2*3 + 1 // 1 1 行目
  Num2 = iota<<2*3 + 1 // 13 2 行目
  _ // 25 3 行目
  Num3 //37 4 行目
  Num4 = iota // 4 5 行目
  _ // 5 6 行目
  Num5 // 6 7 行目
)

例では匿名識別子 _ を使用して 1 行を占めています。iota の値は本質的に、iota が存在する行と現在の const グループの最初の行との差です。異なる const グループは相互に影響しません。

列挙型

Go 言語には列挙型のために特別なデータ型が設計されていません。他の言語では通常 enum を使用して表しますが、Go では通常、カスタム型 + const + iota を使用して列挙型を実装します。以下に簡単な例を示します。

go
type Season uint8

const (
  Spring Season = iota
  Summer
  Autumn
  Winter
)

これらの列挙型は実際には数字であり、Go はこれらを直接文字列に変換することをサポートしていませんが、カスタム型にメソッドを追加して文字列表現を返すことで、Stringer インターフェースを実装できます。

go
func (s Season) String() string {
  switch s {
  case Spring:
    return "spring"
  case Summer:
    return "summer"
  case Autumn:
    return "autumn"
  case Winter:
    return "winter"
  }
  return ""
}

これでシンプルな列挙型の実装が完成します。Stringer 公式ツールを使用して列挙型を自動生成することもできます。

ただし、以下の欠点があります。

  • 型安全ではありません。Season はカスタム型であるため、強制型変換を使用して他の数字もこの型に変換できます。

    go
    Season(6)
  • 煩雑です。文字列表現は自分で実装する必要があります。

  • 表現力が弱いです。const は基本データ型のみをサポートしているため、これらの列挙値も文字列と数字のみで表現できます。

言語レベルで列挙型をサポートしない理由は、筆者が非常に理解できないことの 1 つです。これは明らかに弊害よりも利益が大きいと思います。

Golang by www.golangdev.cn edit