
こんにちは。よっしーです(^^)
本日は、Go言語の言語仕様について解説しています。
背景
Go言語を学び始めて、公式の「The Go Programming Language Specification(言語仕様書)」を開いてみたものの、「英語で書かれていて読むのが大変…」「専門用語ばかりで何を言っているのかわからない…」と感じたことはありませんか? 実は、多くのGo初心者が同じ壁にぶつかっています。
言語仕様書は、Go言語の「正式な取扱説明書」のような存在です。プログラミング言語がどのように動くのか、どんなルールで書くべきなのかが詳しく書かれていますが、その分、初めて読む人には難しく感じられるのも事実です。
そこでこの記事では、言語仕様書の導入部分を丁寧な日本語訳とともに、初心者の方でも理解しやすい補足説明を加えてお届けします。「強く型付けされている」「ガベージコレクション」「並行プログラミング」といった専門用語も、具体例を交えながらわかりやすく解説していきます。
言語仕様書は難しそうに見えますが、一つひとつの概念を丁寧に読み解いていけば、必ず理解できます。一緒に、Go言語の基礎をしっかり学んでいきましょう!
Identifiers(識別子)
識別子は、変数や型などのプログラム要素に名前を付けます。識別子は、1文字以上の文字と数字の列です。識別子の最初の文字は、文字でなければなりません。
identifier = letter { letter | unicode_digit } .
a
_x9
ThisVariableIsExported
αβ
一部の識別子は事前宣言されています。
解説
識別子とは何か?
識別子(identifier) は、プログラムの中で「名前」として使われる文字列です。変数、関数、型、パッケージなど、あらゆるものに名前を付けるときに使います。
たとえ話: 人に名前があるように、プログラムの中の要素にも名前が必要です。「太郎さん」「花子さん」と呼ぶように、変数にも「userName」「age」といった名前を付けます。
package main
import "fmt"
func main() {
// これらはすべて識別子
var userName string = "太郎" // userName が識別子
var age int = 25 // age が識別子
var isAdult bool = true // isAdult が識別子
calculateTotal(100, 200) // calculateTotal が識別子
fmt.Println(userName, age, isAdult) // Println も識別子
}
// calculateTotal も識別子
func calculateTotal(price1, price2 int) int { // price1, price2 も識別子
return price1 + price2
}
識別子の構文ルール
識別子は以下のルールに従って作られます:
identifier = letter { letter | unicode_digit } .
これを分解すると:
- 最初は必ず文字(letter)
letter= アルファベット、日本語、ギリシャ文字、アンダースコア(_)など
- 2文字目以降は文字または数字
letterまたはunicode_digit(0-9など)を何文字でも
ルール1: 最初の文字は必ず「文字」
package main
func main() {
// ✅ 正しい例
var name string // 英字で始まる
var _temp int // アンダースコアで始まる
var 名前 string // 日本語で始まる
var α float64 // ギリシャ文字で始まる
// ❌ 間違った例
// var 1name string // エラー! 数字で始まっている
// var 9lives int // エラー! 数字で始まっている
}
なぜ数字で始められないの?
数字で始まると、数値リテラル(例: 123)と区別がつかなくなるためです。
// もし数字で始められたら...
// var 123 int = 456 // これは何を意味する? 123という変数? それとも数値?
ルール2: 2文字目以降は文字または数字
package main
func main() {
// ✅ すべて正しい
var name1 string // 文字 + 数字
var user_name string // 文字 + アンダースコア + 文字
var test123 int // 文字 + 数字の連続
var 変数2 int // 日本語 + 数字
var _123 int // アンダースコア + 数字
var αβγ123 float64 // ギリシャ文字 + 数字
}
識別子の具体例
仕様書に挙げられている例を見てみましょう:
例1: a
package main
func main() {
var a int = 10 // 1文字だけの識別子も有効
// 短い識別子はループ変数などでよく使う
for i := 0; i < 10; i++ { // i, j, k などもよく使われる
// ...
}
}
使用場面:
- ループのカウンタ変数(
i,j,k) - 一時的な変数
- 数学的な変数(
x,y,z)
例2: _x9
package main
func main() {
var _x9 int = 42 // アンダースコアで始まり、数字を含む
// アンダースコアで始まる識別子は、
// 内部的な変数やプライベートな変数によく使われる
var _temp string = "一時データ"
var _cache map[string]int = make(map[string]int)
}
使用場面:
- 内部使用の変数(パブリックにしたくない)
- 一時的な変数
- テストコード
特殊なアンダースコア _:
package main
import "fmt"
func getValues() (int, string) {
return 42, "太郎"
}
func main() {
// アンダースコアだけの識別子は「空白識別子」
// 値を無視したいときに使う
value, _ := getValues() // 2番目の戻り値を無視
fmt.Println(value)
// 複数の値を無視することも可能
_, name := getValues() // 1番目の戻り値を無視
fmt.Println(name)
}
例3: ThisVariableIsExported
package main
import "fmt"
// 大文字で始まる識別子は「エクスポートされる」(公開される)
var ThisVariableIsExported string = "公開変数"
// 小文字で始まる識別子は「エクスポートされない」(非公開)
var thisVariableIsNotExported string = "非公開変数"
func main() {
fmt.Println(ThisVariableIsExported)
}
重要な慣習: Goでは、大文字で始まるか小文字で始まるかで公開範囲が変わります。
| 先頭文字 | 公開範囲 | 例 |
|---|---|---|
| 大文字 | パッケージ外からアクセス可能(public) | UserName, GetValue() |
| 小文字 | パッケージ内のみアクセス可能(private) | userName, getValue() |
package mypackage
// Public: 他のパッケージから使える
var PublicVariable int = 100
func PublicFunction() {}
type PublicStruct struct {}
// Private: このパッケージ内でのみ使える
var privateVariable int = 200
func privateFunction() {}
type privateStruct struct {}
命名規則(CamelCase):
Goでは、複数の単語を組み合わせるときにキャメルケース(らくだのこぶのように大文字小文字が交互に来る)を使うのが一般的です。
package main
// ✅ 推奨される命名(CamelCase)
var userName string // 先頭小文字 = private
var UserName string // 先頭大文字 = public
var maxConnectionCount int // 複数単語をつなげる
var HTTPServer string // 略語は大文字で統一
// ❌ Goではあまり使わない命名(snake_case)
// var user_name string // 他の言語では一般的だが、Goでは非推奨
// var max_connection_count int
例4: αβ
package main
import "fmt"
func main() {
// ギリシャ文字も識別子として使える
var α float64 = 3.14159 // alpha
var β float64 = 2.71828 // beta
var γ float64 = 1.61803 // gamma
// 数学的なコードで便利
var π float64 = 3.14159
var Δ float64 = 0.001 // delta(変化量)
var Σ int // sigma(合計)
fmt.Println(α, β, γ, π, Δ, Σ)
}
使用場面:
- 科学計算、数学的なコード
- 物理シミュレーション
- 統計処理
注意点: ギリシャ文字は便利ですが、チーム開発では入力しやすさや読みやすさも考慮しましょう。
事前宣言された識別子(Predeclared identifiers)
Goには、最初から定義されている識別子があります。これらは特別なインポートなしで使えます。
型
package main
func main() {
// 事前宣言された型
var b bool // 真偽値
var i int // 整数
var i8 int8 // 8ビット整数
var i16 int16 // 16ビット整数
var i32 int32 // 32ビット整数
var i64 int64 // 64ビット整数
var u uint // 符号なし整数
var u8 uint8 // 8ビット符号なし整数
var u16 uint16 // 16ビット符号なし整数
var u32 uint32 // 32ビット符号なし整数
var u64 uint64 // 64ビット符号なし整数
var f32 float32 // 32ビット浮動小数点
var f64 float64 // 64ビット浮動小数点
var c64 complex64 // 64ビット複素数
var c128 complex128 // 128ビット複素数
var s string // 文字列
var r rune // ルーン(= int32)
var bt byte // バイト(= uint8)
// 特殊な型
var e error // エラー型
}
定数
package main
import "fmt"
func main() {
// 事前宣言された定数
var t bool = true // 真
var f bool = false // 偽
// iota(連続した整数を生成)
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
)
fmt.Println(t, f, Sunday, Monday, Tuesday)
}
ゼロ値
package main
func main() {
// nil: ゼロ値(ポインタ、スライス、マップ、チャネルなど)
var ptr *int = nil
var slice []int = nil
var m map[string]int = nil
}
組み込み関数
package main
import "fmt"
func main() {
// 事前宣言された関数
// make: スライス、マップ、チャネルを作成
slice := make([]int, 5)
m := make(map[string]int)
// new: ポインタを作成
ptr := new(int)
// len: 長さを取得
length := len(slice)
// cap: 容量を取得
capacity := cap(slice)
// append: スライスに要素を追加
slice = append(slice, 10)
// copy: スライスをコピー
copied := make([]int, len(slice))
copy(copied, slice)
// delete: マップから要素を削除
delete(m, "key")
// panic: パニックを発生させる
// panic("エラーが発生しました")
// recover: パニックから回復
// defer func() {
// if r := recover(); r != nil {
// fmt.Println("回復しました:", r)
// }
// }()
// close: チャネルを閉じる
ch := make(chan int)
close(ch)
// print, println: デバッグ用(非推奨、fmtパッケージを使う)
println("デバッグメッセージ")
fmt.Println(length, capacity, ptr, copied)
}
注意: これらの事前宣言された識別子は、自分で再定義できます(ただし非推奨)。
package main
import "fmt"
func main() {
// ❌ 悪い例: 事前宣言された識別子を再定義
var true int = 42 // コンパイルは通るが非常に混乱する!
fmt.Println(true) // 42 が出力される
// これは絶対に避けるべき
}
識別子の命名規則とベストプラクティス
推奨される命名スタイル
package main
// ✅ 良い命名例
// 変数: キャメルケース、意味のある名前
var userName string
var maxRetryCount int
var isAuthenticated bool
// 関数: キャメルケース、動詞で始める
func getUserName() string { return "" }
func calculateTotal(items []int) int { return 0 }
func isValid(input string) bool { return true }
// 型: キャメルケース、名詞
type User struct {
Name string
Age int
}
type HTTPClient struct { // 略語は大文字で統一
// ...
}
// 定数: キャメルケースまたは全部大文字
const MaxConnections = 100
const APIEndpoint = "https://api.example.com"
// パッケージレベルの変数: 説明的な名前
var DefaultTimeout = 30
var ErrNotFound = errors.New("not found")
避けるべき命名
package main
// ❌ 悪い命名例
// 意味不明な略語
var usrnm string // userNameの方が良い
var cnt int // countの方が良い
// ハンガリアン記法(型を名前に含める)
var strName string // Goでは不要
var intAge int // 型はコンパイラが知っている
// スネークケース(Goの慣習ではない)
var user_name string // userNameの方が良い
var max_retry_count int // maxRetryCountの方が良い
// 長すぎる名前
var theNumberOfItemsInTheShoppingCart int // itemCountなどで十分
// 短すぎる名前(スコープが広い場合)
var x string // グローバル変数には不適切
スコープに応じた命名
package main
func main() {
// ✅ 短いスコープでは短い名前でOK
for i := 0; i < 10; i++ { // i は数行で終わるのでOK
// ...
}
// ✅ 長いスコープでは説明的な名前
var userSessionTimeout int = 3600 // グローバルレベルでは詳しく
}
まとめ: 識別子で覚えておくべきこと
- 識別子は文字で始まる(数字で始められない)
- 2文字目以降は文字または数字
- アンダースコア
_は文字として扱われる - 大文字で始まる = 公開(public)、小文字で始まる = 非公開(private)
- キャメルケースが推奨(スネークケースは非推奨)
- 事前宣言された識別子がある(型、定数、関数など)
- 日本語やギリシャ文字も使える(ただしチーム規約に従う)
実用的なアドバイス:
package main
import "fmt"
// 公開する構造体(大文字で始まる)
type User struct {
Name string // 公開フィールド
age int // 非公開フィールド
}
// 公開する関数(大文字で始まる)
func GetUserName(u User) string {
return u.Name
}
// 非公開の関数(小文字で始まる)
func calculateAge(birthYear int) int {
currentYear := 2024
return currentYear - birthYear
}
func main() {
// 意味のある変数名を使う
user := User{Name: "太郎", age: 25}
// 短いスコープでは短い名前もOK
for i := 0; i < 3; i++ {
fmt.Println(i)
}
fmt.Println(GetUserName(user))
}
良い識別子の命名は、読みやすく、保守しやすいコードを書くための第一歩です!
おわりに
本日は、Go言語の言語仕様について解説しました。

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

コメント