コンテンツにスキップ

Go/:=

出典: フリー教科書『ウィキブックス(Wikibooks)』
< Go

Goにおける 区切り子 := は、短縮変数宣言(short variable declaration) を表す演算子で、Go言語の 最も特徴的で便利な機能 の一つです。変数の宣言と初期化を同時に行い、型推論によってコードを簡潔に書くことができます。

区切り子 := の基本

[編集]
短縮変数宣言の基本形
// 基本的な短縮変数宣言
x := 42        // var x int = 42 と同等
name := "Go"   // var name string = "Go" と同等
pi := 3.14159  // var pi float64 = 3.14159 と同等
  • :=変数の宣言、型推論、初期化 を一度に行います
  • 右辺の値から自動的に型が決定されます
従来の宣言との比較
// 従来の変数宣言
var x int = 42
var name string = "Go"

// 短縮変数宣言
x := 42
name := "Go"

:= の使用制限

[編集]
関数内でのみ使用可能
package main

// var globalVar := 42  // エラー: パッケージレベルでは使用不可
var globalVar = 42     // OK: 型推論ありの通常宣言

func main() {
    localVar := 42     // OK: 関数内では使用可能
}
  • :=関数内でのみ 使用できます
  • パッケージレベルでは var キーワードが必要です
既存変数への代入では使用不可
var x int
// x := 42  // エラー: x は既に宣言済み
x = 42      // OK: 通常の代入

多重短縮変数宣言

[編集]
複数変数の同時宣言
// 複数変数の同時宣言と初期化
a, b := 10, 20
name, age := "Alice", 30
x, y, z := 1.0, 2.0, 3.0
関数の戻り値との組み合わせ
// 関数の複数戻り値を直接受け取る
value, ok := myMap["key"]
data, err := os.ReadFile("file.txt")
result, success := strconv.Atoi("123")

混在パターンでの :=

[編集]
新規変数と既存変数の混在
var err error  // 既存変数

// 新規変数 result と既存変数 err の混在
result, err := someFunction()  // OK: result は新規宣言、err は代入
  • 少なくとも一つの新しい変数 があれば := を使用できます
複雑な混在例
var a, b int
var err error

// a は既存、c は新規、err は既存
a, c, err := complexFunction()  // OK: c が新規変数

型推論の詳細

[編集]
基本型の推論
i := 42        // int
f := 3.14      // float64
s := "hello"   // string
b := true      // bool
r := 'A'       // rune (int32)
複合型の推論
slice := []int{1, 2, 3}           // []int
m := map[string]int{"a": 1}       // map[string]int
ch := make(chan int)              // chan int
fn := func() { fmt.Println("Hi") } // func()
インターフェース型の推論
var w io.Writer
w = os.Stdout

// w2 := os.Stdout  // *os.File型として推論
// w2 = otherWriter // エラー: 型が固定されている

特殊な使用パターン

[編集]
(1) ブランク識別子との組み合わせ
_, err := os.Open("file.txt")     // 戻り値の一部を無視
value, _ := strconv.Atoi("123")   // エラーを無視
(2) 型アサーションでの使用
var i interface{} = 42
value, ok := i.(int)  // 型アサーション
(3) チャンネル操作での使用
ch := make(chan int, 1)
ch <- 42

value, ok := <-ch  // チャンネルからの受信
(4) range文での使用
slice := []string{"a", "b", "c"}
for i, v := range slice {  // インデックスと値を同時に取得
    fmt.Printf("%d: %s\n", i, v)
}

エラーハンドリングでの活用

[編集]
典型的なエラーハンドリングパターン
file, err := os.Open("data.txt")
if err != nil {
    return err
}
defer file.Close()

data, err := io.ReadAll(file)
if err != nil {
    return err
}
連鎖的なエラーハンドリング
func processFile(filename string) error {
    content, err := os.ReadFile(filename)
    if err != nil {
        return err
    }
    
    result, err := processData(content)
    if err != nil {
        return err
    }
    
    return saveResult(result)
}

他の言語との比較

[編集]
Python
# Python の多重代入
a, b = 1, 2
name, age = "Alice", 30
JavaScript
// JavaScript の分割代入
const [a, b] = [1, 2];
const {name, age} = {name: "Alice", age: 30};
C++
// C++17 の構造化束縛
auto [a, b] = std::make_pair(1, 2);
Go
  • :=関数スコープ限定 で型安全
  • エラーハンドリングのイディオムと密接に結びついている
  • シンプルで一貫性のある文法

注意点とベストプラクティス

[編集]
型の明示が必要な場合
// 明示的な型指定が必要な場合
var timeout time.Duration = 30 * time.Second
// timeout := 30 * time.Second  // OK: 型推論も可能
スコープの注意
var err error
if condition {
    result, err := someFunction()  // 新しい err がシャドウイング
    // この err は if ブロック内のみ有効
}
// ここでの err は元の変数
再宣言の制限
x := 42
// x := 43  // エラー: 同じスコープ内での再宣言は不可
x = 43     // OK: 代入

パフォーマンスへの影響

[編集]
ゼロコスト抽象化
// コンパイル時に最適化される
x := 42        // 実行時オーバーヘッドなし
y := getValue() // 関数呼び出し自体のコストのみ
メモリ効率
// 不要な変数宣言を避ける
if result, err := expensiveOperation(); err != nil {
    return err
}
// result はここでスコープ外

まとめ

[編集]
  • Goの :=「短縮変数宣言」 を表し、変数の宣言・型推論・初期化を一度に行います
  • 関数内でのみ使用可能 で、パッケージレベルでは使用できません
  • 多重代入エラーハンドリング において、Goらしい簡潔で読みやすいコードを書くことができます
  • 型推論により、冗長な型宣言を避けながら型安全性を保ちます
  • 新規変数と既存変数の混在が可能で、柔軟な変数操作を実現します

:= は単なる短縮記法ではなく、Goの 『簡潔性と型安全性の両立』 を象徴する、言語設計の核心的な機能です!