
こんにちは。よっしーです(^^)
本日は、Go言語の言語仕様について解説しています。
背景
Go言語を学び始めて、公式の「The Go Programming Language Specification(言語仕様書)」を開いてみたものの、「英語で書かれていて読むのが大変…」「専門用語ばかりで何を言っているのかわからない…」と感じたことはありませんか? 実は、多くのGo初心者が同じ壁にぶつかっています。
言語仕様書は、Go言語の「正式な取扱説明書」のような存在です。プログラミング言語がどのように動くのか、どんなルールで書くべきなのかが詳しく書かれていますが、その分、初めて読む人には難しく感じられるのも事実です。
そこでこの記事では、言語仕様書の導入部分を丁寧な日本語訳とともに、初心者の方でも理解しやすい補足説明を加えてお届けします。「強く型付けされている」「ガベージコレクション」「並行プログラミング」といった専門用語も、具体例を交えながらわかりやすく解説していきます。
言語仕様書は難しそうに見えますが、一つひとつの概念を丁寧に読み解いていけば、必ず理解できます。一緒に、Go言語の基礎をしっかり学んでいきましょう!
エクスポートされた識別子(Exported identifiers)
識別子は、他のパッケージからのアクセスを許可するためにエクスポートすることができます。識別子がエクスポートされるのは、以下の両方の条件を満たす場合です。
- 識別子の名前の最初の文字が、Unicodeの大文字(Unicode文字カテゴリ Lu)であること。
- その識別子がパッケージブロックで宣言されているか、フィールド名またはメソッド名であること。
上記以外の識別子はすべてエクスポートされません。
解説
たとえ話
エクスポートの仕組みをレストランの厨房とホールに例えてみましょう。
パッケージは「レストランの厨房」です。厨房の中にはたくさんの道具や食材(変数・関数・型など)がありますが、お客さん(他のパッケージ)に見せるのはメニューに載った料理だけです。
Goでは、名前の先頭を大文字にする=メニューに載せる(エクスポート)、先頭を小文字にする=厨房の中だけで使う(非エクスポート) というルールになっています。
他の多くの言語では public / private といったキーワードを使いますが、Goは名前の先頭1文字だけで可視性を決めるという、非常にシンプルで独特なアプローチを採用しています。
コード例
// ══════════════════════════════════════
// パッケージ: user(user/user.go)
// ══════════════════════════════════════
package user
import "fmt"
// ── 大文字始まり → エクスポートされる(外部から見える) ──
// User は他のパッケージから使える「型」
type User struct {
Name string // 大文字始まり → 外部からアクセスできるフィールド
Email string // 大文字始まり → 外部からアクセスできるフィールド
age int // 小文字始まり → 外部からアクセスできないフィールド
}
// NewUser は他のパッケージから呼べる「関数」
func NewUser(name, email string, age int) User {
return User{Name: name, Email: email, age: age}
}
// Greet は他のパッケージから呼べる「メソッド」
func (u User) Greet() string {
return fmt.Sprintf("こんにちは、%sです!", u.Name)
}
// ── 小文字始まり → エクスポートされない(外部から見えない) ──
// validate はこのパッケージ内でしか使えない関数
func validate(email string) bool {
return len(email) > 0
}
// formatAge はこのパッケージ内でしか使えないメソッド
func (u User) formatAge() string {
return fmt.Sprintf("%d歳", u.age)
}
// ══════════════════════════════════════
// パッケージ: main(main.go)
// ══════════════════════════════════════
package main
import (
"fmt"
"example/user"
)
func main() {
// ✅ エクスポートされた関数を呼び出す
u := user.NewUser("太郎", "taro@example.com", 25)
// ✅ エクスポートされたフィールドにアクセス
fmt.Println(u.Name) // → 太郎
fmt.Println(u.Email) // → taro@example.com
// ✅ エクスポートされたメソッドを呼び出す
fmt.Println(u.Greet()) // → こんにちは、太郎です!
// ❌ エクスポートされていないフィールドにはアクセスできない
// fmt.Println(u.age) // コンパイルエラー: u.age undefined
// ❌ エクスポートされていない関数は呼べない
// user.validate("test") // コンパイルエラー: cannot refer to unexported name
// ❌ エクスポートされていないメソッドも呼べない
// u.formatAge() // コンパイルエラー
}
package main
import "fmt"
// ── Unicodeの大文字であればエクスポートされる ──
// 日常的にはASCIIの大文字(A-Z)を使うが、
// 仕様上はUnicodeの大文字カテゴリ(Lu)であればよい
type Über struct { // Ü は Unicode 大文字なのでエクスポートされる
Ñame string // Ñ も Unicode 大文字なのでエクスポートされる
}
// ただし、実務では ASCII の A-Z を使うのが一般的です
// 上記は仕様の説明用であり、推奨されるスタイルではありません
func main() {
v := Über{Ñame: "test"}
fmt.Println(v.Ñame)
}
よくある間違い・注意点
1. 「2つの条件の両方」を満たす必要がある
大文字で始まるだけではエクスポートされません。パッケージブロックでの宣言、またはフィールド名・メソッド名である必要があります。関数内部のローカル変数は、大文字で始まっていてもエクスポートされません。
func example() {
// 大文字始まりだが、関数内のローカル変数なのでエクスポートされない
Message := "これは外部から見えない"
_ = Message
}
2. 構造体のフィールドを小文字にすると JSON 変換で困る
type Item struct {
name string // 小文字 → encoding/json からもアクセスできない
Price int // 大文字 → JSON に含まれる
}
// json.Marshal(Item{name: "本", Price: 500})
// → {"Price":500} ← name が出力されない!
encoding/json などの外部パッケージはリフレクションを使ってフィールドにアクセスしますが、非エクスポートフィールドにはアクセスできません。JSONに含めたいフィールドは必ず大文字始まりにしましょう。
3. エクスポート=公開APIなので慎重に
一度エクスポートした識別子は、他のパッケージから使われる可能性があります。後から名前を変えると利用者のコードが壊れるため、エクスポートする識別子は慎重に設計しましょう。必要最小限だけをエクスポートするのがGoの設計哲学です。
// ✅ 良い設計:必要なものだけエクスポート
type Client struct {
Timeout int // 利用者が設定する必要がある → エクスポート
baseURL string // 内部実装の詳細 → 非エクスポート
retries int // 内部実装の詳細 → 非エクスポート
}
まとめ
- Goでは、識別子の先頭文字が大文字ならエクスポート(公開)、小文字なら非エクスポート(非公開)。
- エクスポートの条件は2つ:①先頭がUnicode大文字、②パッケージブロックで宣言されているかフィールド名・メソッド名であること。
- 他の言語の
public/privateに相当する仕組みだが、Goは命名規則だけで実現しているのが特徴。 - 必要最小限だけをエクスポートし、内部実装は小文字で隠すのがGoらしい設計。
- JSONエンコードやリフレクションなど、外部パッケージからのアクセスにも影響するため、フィールドの可視性は意識して設計すること。
「大文字=公開、小文字=非公開」というGoのルールは、コードを一目見ただけでAPIの境界が分かるという大きな利点があります。とてもシンプルですが奥が深い仕組みなので、パッケージ設計の際にはぜひ意識してみてください!
おわりに
本日は、Go言語の言語仕様について解説しました。

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

コメント