
こんにちは。よっしーです(^^)
本日は、Go言語の言語仕様について解説しています。
背景
Go言語を学び始めて、公式の「The Go Programming Language Specification(言語仕様書)」を開いてみたものの、「英語で書かれていて読むのが大変…」「専門用語ばかりで何を言っているのかわからない…」と感じたことはありませんか? 実は、多くのGo初心者が同じ壁にぶつかっています。
言語仕様書は、Go言語の「正式な取扱説明書」のような存在です。プログラミング言語がどのように動くのか、どんなルールで書くべきなのかが詳しく書かれていますが、その分、初めて読む人には難しく感じられるのも事実です。
そこでこの記事では、言語仕様書の導入部分を丁寧な日本語訳とともに、初心者の方でも理解しやすい補足説明を加えてお届けします。「強く型付けされている」「ガベージコレクション」「並行プログラミング」といった専門用語も、具体例を交えながらわかりやすく解説していきます。
言語仕様書は難しそうに見えますが、一つひとつの概念を丁寧に読み解いていけば、必ず理解できます。一緒に、Go言語の基礎をしっかり学んでいきましょう!
Semicolons(セミコロン)
形式的な構文では、多くの生成規則において終端記号としてセミコロン";"を使用します。Goプログラムは、以下の2つのルールを使用して、これらのセミコロンのほとんどを省略できます。
- 入力がトークンに分割される際、行の最後のトークンが以下のいずれかである場合、トークンストリーム内のそのトークンの直後に自動的にセミコロンが挿入されます。
- 識別子
- 整数、浮動小数点、虚数、ルーン、または文字列リテラル
- キーワード
break,continue,fallthrough, またはreturnのいずれか - 演算子と句読点
++,--,),], または}のいずれか
- 複雑な文を1行に収めることができるように、閉じ括弧
")"または"}"の前ではセミコロンを省略できます。
慣用的な使い方を反映するため、このドキュメント内のコード例では、これらのルールを使用してセミコロンを省略しています。
解説
セミコロンとは何か?
セミコロン(;) は、プログラミング言語で「文の終わり」を示す記号です。C言語やJavaでは、すべての文の最後にセミコロンを書く必要がありますが、Goではほとんどの場合、セミコロンを省略できます。
たとえ話: 日本語の文章で句点(。)を使うように、プログラミングでもセミコロンで文を区切ります。ただし、Goは賢いので「ここで文が終わるな」と自動的に判断してくれます。
package main
import "fmt"
func main() {
// セミコロンなしで書ける(推奨)
var x int = 10
var y int = 20
fmt.Println(x + y)
// セミコロンを明示的に書いてもOK(非推奨)
var a int = 10;
var b int = 20;
fmt.Println(a + b);
}
ルール1: セミコロンが自動挿入される場合
行の最後のトークンが以下のいずれかの場合、その行末に自動的にセミコロン;が挿入されます。
1-1. 識別子
package main
import "fmt"
func main() {
var userName string
// ↑ この行末に自動的に ; が挿入される
userName = "太郎"
// ↑ この行末にも ; が挿入される
fmt.Println(userName)
// ↑ この行末にも ; が挿入される
}
実際にコンパイラが見ているのは:
var userName string;
userName = "太郎";
fmt.Println(userName);
1-2. リテラル(整数、浮動小数点、虚数、ルーン、文字列)
package main
import "fmt"
func main() {
var age int = 25
// ↑ 最後が数値リテラル "25" → ; が挿入
var name string = "太郎"
// ↑ 最後が文字列リテラル "太郎" → ; が挿入
var pi float64 = 3.14
// ↑ 最後が浮動小数点リテラル "3.14" → ; が挿入
var char rune = 'A'
// ↑ 最後がルーンリテラル 'A' → ; が挿入
fmt.Println(age, name, pi, char)
}
1-3. 特定のキーワード(break, continue, fallthrough, return)
これらのキーワードで行が終わる場合、セミコロンが自動挿入されます。
package main
import "fmt"
func getValue() int {
return 42
// ↑ "return" で終わるので ; が自動挿入
}
func main() {
for i := 0; i < 10; i++ {
if i == 5 {
break
// ↑ "break" で終わるので ; が自動挿入
}
if i%2 == 0 {
continue
// ↑ "continue" で終わるので ; が自動挿入
}
fmt.Println(i)
}
}
注意点: returnの後に値を書く場合は同じ行に書く必要があります。
package main
// 正しい書き方
func add(a, b int) int {
return a + b // returnと値を同じ行に
}
// 間違った書き方
func subtract(a, b int) int {
return // ここで ; が自動挿入されてしまう!
a - b // この行は到達不能コードになる(エラー)
}
1-4. 特定の演算子と句読点(++, –, ), ], })
package main
import "fmt"
func main() {
// インクリメント演算子 ++
x := 10
x++
// ↑ "++" で終わるので ; が自動挿入
// デクリメント演算子 --
y := 20
y--
// ↑ "--" で終わるので ; が自動挿入
// 閉じ括弧類
numbers := []int{1, 2, 3}
// ↑ "}" で終わるので ; が自動挿入
result := getValue()
// ↑ ")" で終わるので ; が自動挿入
fmt.Println(x, y, numbers, result)
}
func getValue() int {
return 100
}
// ↑ "}" で終わるので ; が自動挿入
これが最も重要な理由: 波括弧{}の位置に影響します。
package main
func main() {
// 正しい書き方: 波括弧は同じ行に
if true {
// ...
}
// 間違った書き方: コンパイルエラー!
if true
{ // "true" で行が終わるので、前の行末に ; が自動挿入され、
// "if true;" となってしまい、{ が単独で出現してエラー
// ...
}
}
正しい波括弧の書き方:
package main
import "fmt"
func main() {
// if文: 波括弧は同じ行に
if x := 10; x > 5 {
fmt.Println("大きい")
}
// for文: 波括弧は同じ行に
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// 関数定義: 波括弧は同じ行に
myFunc := func() {
fmt.Println("無名関数")
}
myFunc()
}
ルール2: 閉じ括弧の前ではセミコロンを省略できる
複雑な文を1行に書くとき、閉じ括弧)や}の直前ではセミコロンを省略できます。
複数の文を1行に書く場合
通常、複数の文を1行に書くにはセミコロンで区切る必要があります:
package main
import "fmt"
func main() {
// 1行に複数の文を書く(非推奨だが可能)
x := 10; y := 20; fmt.Println(x + y)
// 閉じ括弧の前ならセミコロン省略可能
if x := 10; x > 5 { fmt.Println("OK") }
// ↑ "}" の前なのでセミコロン不要
}
スライスやマップの初期化
package main
import "fmt"
func main() {
// 最後の要素の後のカンマ: あってもなくても良い
numbers1 := []int{1, 2, 3} // OK: カンマなし
numbers2 := []int{1, 2, 3,} // OK: カンマあり(推奨)
// 複数行の場合
numbers3 := []int{
1,
2,
3, // 最後のカンマを付ける(推奨)
} // "}" の前なのでセミコロン不要
// カンマがないとエラー
numbers4 := []int{
1,
2,
3 // カンマがない!
} // エラー: "3" で行が終わるので ; が自動挿入され、
// "3; }" となって構文エラー
fmt.Println(numbers1, numbers2, numbers3)
}
推奨される書き方:
package main
func main() {
// 複数行の場合は最後にカンマを付ける
user := User{
Name: "太郎",
Age: 25,
City: "東京", // ← カンマを付ける
}
// 配列・スライス
numbers := []int{
1,
2,
3, // ← カンマを付ける
}
// マップ
prices := map[string]int{
"りんご": 100,
"バナナ": 80,
"みかん": 60, // ← カンマを付ける
}
}
type User struct {
Name string
Age int
City string
}
慣用的なGoのスタイル
このドキュメントやGoの標準ライブラリのコード例では、セミコロンを省略しています。これがGoの慣用的なスタイルです。
package main
import "fmt"
// Goの標準的な書き方: セミコロンなし
func main() {
name := "太郎"
age := 25
if age >= 20 {
fmt.Printf("%sは成人です\n", name)
} else {
fmt.Printf("%sは未成年です\n", name)
}
for i := 0; i < 3; i++ {
fmt.Println(i)
}
}
// セミコロンを明示的に書く(非推奨)
func mainWithSemicolons() {
name := "太郎";
age := 25;
if age >= 20 {
fmt.Printf("%sは成人です\n", name);
} else {
fmt.Printf("%sは未成年です\n", name);
};
for i := 0; i < 3; i++ {
fmt.Println(i);
};
}
よくある間違いと対処法
間違い1: 波括弧を次の行に書く
package main
// ❌ 間違い
func main()
{ // エラー! ")" で行が終わるので ; が自動挿入
// ...
}
// ✅ 正しい
func main() {
// ...
}
間違い2: returnの後に改行を入れる
package main
// ❌ 間違い
func getValue() int {
return // ここで ; が自動挿入される!
42 // 到達不能コード(エラー)
}
// ✅ 正しい
func getValue() int {
return 42
}
// ✅ 長い式の場合は括弧で囲む
func getComplexValue() int {
return (
10 +
20 +
30
)
}
間違い3: 複数行リテラルの最後にカンマを付けない
package main
// ❌ 間違い
func main() {
numbers := []int{
1,
2,
3 // カンマがない!
} // エラー!
}
// ✅ 正しい
func main() {
numbers := []int{
1,
2,
3, // カンマを付ける
}
}
セミコロンを明示的に書く場合
稀に、1行に複数の文を書きたい場合はセミコロンを使います(ただし非推奨):
package main
import "fmt"
func main() {
// 1行に複数の文を書く(デバッグ時など)
x := 10; fmt.Println(x)
// for文の初期化、条件、後処理(これはOK)
for i := 0; i < 3; i++ {
fmt.Println(i)
}
// ifの短縮構文(これもOK)
if x := getValue(); x > 5 {
fmt.Println("大きい")
}
}
func getValue() int {
return 10
}
まとめ: セミコロンで覚えておくべきこと
- Goではセミコロンを省略できる(自動挿入される)
- 識別子、リテラル、特定のキーワード、特定の演算子で行が終わるとセミコロンが自動挿入される
- 波括弧
{は同じ行に書く(次の行に書くとエラー) - returnの後に値を書く場合は同じ行に(改行するとエラー)
- 複数行リテラルの最後の要素にカンマを付ける(セミコロン自動挿入対策)
- 閉じ括弧の前ではセミコロンを省略できる
実用的なアドバイス:
package main
import "fmt"
// ✅ 推奨される書き方
func main() {
// 波括弧は同じ行
if true {
fmt.Println("OK")
}
// returnは同じ行
result := func() int {
return 42
}
// 複数行リテラルは最後にカンマ
numbers := []int{
1,
2,
3, // ← カンマを忘れずに
}
fmt.Println(result(), numbers)
}
セミコロンの自動挿入ルールを理解すると、「なぜ波括弧を次の行に書けないのか」「なぜ最後にカンマが必要なのか」といった疑問が解消されます。Goらしいコードを書くための重要な知識です!
おわりに
本日は、Go言語の言語仕様について解説しました。

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)

コメント