Go言語(Golang)を学び始めると、変数の宣言方法に2つの主要な形式があることに気づきます。
一つはキーワード var を使用する方法で、もう一つは短縮変数宣言と呼ばれる := を使用する方法です。
プログラミング初心者だけでなく、他の言語から移行してきたエンジニアにとっても、この2つの使い分けはしばしば混乱の種になります。
「どちらを使っても動くなら、短くて便利な := だけで良いのではないか」と考える方も少なくありません。
しかし、Go言語の設計思想において、これらには明確な役割の違いと適切な使用シーンが定義されています。
本記事では、2026年現在のモダンな開発スタイルを踏まえ、 var と := の仕様上の違いから、実務で推奨される使い分けのルールまでを詳しく解説します。
Goにおける変数宣言の基本
まずは、それぞれの宣言方法がどのような構文を持ち、どのような挙動をするのかを整理しましょう。
var による宣言
var は、Go言語において最も基本的かつ明示的な変数宣言の方法です。
この形式では、変数名、型、そして必要に応じて初期値を指定することができます。
package main
import "fmt"
func main() {
// 型を明示して宣言(初期値なし)
var message string
message = "Hello, Go!"
// 型を明示して宣言(初期値あり)
var count int = 10
// 型推論を利用した宣言
var isActive = true
fmt.Println(message, count, isActive)
}
Hello, Go! 10 true
var を使った宣言の大きな特徴は、変数の「型」をプログラマが明示的にコントロールできる点にあります。
また、初期値を与えずに宣言した場合は、その型の「ゼロ値」で初期化されるという性質を持っています。
:= による短縮変数宣言
一方、 := は「短縮変数宣言」と呼ばれ、 var キーワードと型指定を省略して記述できる便利な構文です。
この構文は、右辺の型から左辺の変数の型を自動的に決定する「型推論」を前提としています。
package main
import "fmt"
func main() {
// 短縮変数宣言
name := "Gopher"
age := 15
fmt.Printf("Name: %s, Age: %d\n", name, age)
}
Name: Gopher, Age: 15
短縮変数宣言は、コードを簡潔に保つために非常に有効であり、Go言語の関数内では最も一般的に利用される宣言方法です。
しかし、便利な反面、使用できる場所に制限があるなど、いくつかの制約が存在します。
var と := の決定的な違い
これら2つの宣言方法には、単なる記述の長さ以外に4つの大きな違いがあります。
1. 宣言可能な場所(スコープ)の違い
最も重要な違いは、その変数をどこで宣言できるかという点です。
var は、関数の外(パッケージレベル)と関数の内の両方で使用することが可能です。
対して、 短縮変数宣言(:=)は関数の中でしか使用できません。
package main
// パッケージレベルでの宣言(OK)
var globalVar = "I am global"
// パッケージレベルでの短縮宣言(NG: コンパイルエラー)
// shortVar := "I will fail"
func main() {
// 関数内であればどちらも可能
var localVar = "I am local"
shortVar := "I am also local"
}
パッケージ全体で共有するグローバル変数や、定数に近い扱いをする変数を定義する場合は、必ず var を使用する必要があります。
2. ゼロ値の利用可否
Go言語では、変数に初期値を与えない場合、その型のデフォルト値である「ゼロ値」が割り当てられます。
var は初期値を省略できるため、ゼロ値での初期化を意図する場合に最適です。
しかし、 := は右辺の値を参照して型を決める仕組みであるため、必ず初期値を指定しなければなりません。
var i int // i は 0 で初期化される
var s string // s は ""(空文字)で初期化される
var slice []int // slice は nil で初期化される
後から値を代入するために変数だけを先に用意しておきたいシーンでは、 var が必須となります。
3. 型の明示的な指定
:= は常に右辺の型を採用します。
例えば、数値の 10 を代入すると、型推論によってデフォルトの int 型になります。
もし特定のサイズ(int64 や float32 など)を指定したい場合、 := ではキャスト(型変換)が必要になります。
// var を使った場合
var price int64 = 1500
// := を使った場合(明示的な変換が必要)
amount := int64(2000)
このように、特定の型であることを強調したい、あるいは推論される型とは異なる型を適用したい場合は var を使う方がコードの意図が伝わりやすくなります。
4. 再宣言の挙動
同じスコープ内で var を使って同じ変数名を二度宣言することはできません。
しかし、 := には特別なルールがあり、「複数の変数を同時に宣言・代入する場合、少なくとも1つが新しい変数であれば既存の変数の再利用が許される」という性質があります。
これは、エラーハンドリングなどの処理で頻繁に利用されます。
func main() {
f, err := os.Open("file1.txt")
if err != nil {
return
}
// err は既に宣言済みだが、f2 が新規変数なので := が使える
f2, err := os.Open("file2.txt")
if err != nil {
return
}
}
比較表:var と := の特徴まとめ
ここまでの違いを、一目でわかるように表にまとめました。
| 特徴 | var | := |
|---|---|---|
| 使用可能な場所 | どこでも(関数外/内) | 関数内のみ |
| 型の指定 | 明示・推論の両方可能 | 型推論のみ |
| 初期値の省略 | 可能(ゼロ値になる) | 不可 |
| 主な用途 | グローバル、ゼロ値初期化 | ローカル変数の即時利用 |
実務における最適な使い分けガイド
Go言語のコミュニティや公式ドキュメント(Effective Goなど)が推奨する、実践的な使い分けのベストプラクティスを紹介します。
原則として関数内では := を選ぶ
ローカル変数において、初期値が明確である場合は := を使用するのが標準的です。
これにより、冗長な var キーワードを排除し、コードの可読性を高めることができます。
特に、関数の戻り値を直接受け取る場合は、ほぼ 100% のケースで := が選択されます。
意図的に var を選ぶべきシーン
以下のようなケースでは、 := ではなく var を積極的に使用します。
1. ゼロ値を利用する場合
変数を宣言した時点では具体的な値が決まっておらず、後で代入や追加を行う場合は var を使います。
// スライスを用意して、後から append する場合
var names []string
names = append(names, "Alice")
これを names := []string{} と書くこともできますが、 var を使う方が「空の状態から始める」という意図が明確になります。
2. 型を厳密に制御したい場合
Goの型推論は強力ですが、インターフェース型として変数を保持したい場合など、推論に任せたくないことがあります。
// Buffer型ではなく、io.Writerインターフェースとして扱いたい場合
var w io.Writer = new(bytes.Buffer)
このように宣言することで、変数 w が io.Writer に準拠していることをコンパイル時に保証し、設計の意図を明示できます。
3. パッケージレベルの変数
先述の通り、関数の外では var しか使えません。
設定値や、複数の関数から参照される共有リソースを定義する際は、迷わず var を選択しましょう。
注意点:変数のシャドウイング(Shadowing)
:= を多用する際に最も注意すべきなのが「変数のシャドウイング」です。
これは、外側のスコープで定義された変数と同じ名前を、内側のスコープで := を使って宣言してしまうことで発生します。
func main() {
x := 10
if x > 5 {
// 外側の x を更新するのではなく、新しい x を宣言してしまう
x := 20
fmt.Println("Inner:", x)
}
fmt.Println("Outer:", x)
}
Inner: 20
Outer: 10
このミスはバグの原因になりやすいため、既存の変数に新しい値を代入したいだけのときは =(単純代入演算子)を使うよう徹底してください。
まとめ
Go言語における var と := の違いを理解することは、クリーンでメンテナンスしやすいコードを書くための第一歩です。
:= は関数内での記述を簡潔にし、開発スピードを向上させてくれます。
一方で var は、型の明示やゼロ値の活用、パッケージレベルでの宣言といった、プログラムの構造を決定づける重要な場面で力を発揮します。
「基本は := を使い、必要性があるときだけ var を選ぶ」という方針を持っておけば、迷うことは少なくなります。
それぞれの特性を正しく把握し、状況に応じた最適な宣言方法を選択できるようになりましょう。
こうした細かな使い分けの積み重ねが、Goらしいシンプルで読みやすいコードを作り上げます。
