Go言語入門:言語仕様 -Vol.5-

スポンサーリンク
Go言語入門:言語仕様 -Vol.5- 用語解説
Go言語入門:言語仕様 -Vol.5-
この記事は約11分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

本日は、Go言語の言語仕様について解説しています。

スポンサーリンク

背景

Go言語を学び始めて、公式の「The Go Programming Language Specification(言語仕様書)」を開いてみたものの、「英語で書かれていて読むのが大変…」「専門用語ばかりで何を言っているのかわからない…」と感じたことはありませんか? 実は、多くのGo初心者が同じ壁にぶつかっています。

言語仕様書は、Go言語の「正式な取扱説明書」のような存在です。プログラミング言語がどのように動くのか、どんなルールで書くべきなのかが詳しく書かれていますが、その分、初めて読む人には難しく感じられるのも事実です。

そこでこの記事では、言語仕様書の導入部分を丁寧な日本語訳とともに、初心者の方でも理解しやすい補足説明を加えてお届けします。「強く型付けされている」「ガベージコレクション」「並行プログラミング」といった専門用語も、具体例を交えながらわかりやすく解説していきます。

言語仕様書は難しそうに見えますが、一つひとつの概念を丁寧に読み解いていけば、必ず理解できます。一緒に、Go言語の基礎をしっかり学んでいきましょう!

Letters and digits(文字と数字)

アンダースコア文字_(U+005F)は、小文字として扱われます。

letter        = unicode_letter | "_" .
decimal_digit = "0" … "9" .
binary_digit  = "0" | "1" .
octal_digit   = "0" … "7" .
hex_digit     = "0" … "9" | "A" … "F" | "a" … "f" .

解説

アンダースコアは「文字」として扱われる

この章では、Goで使える文字(letter)数字(digit) の具体的な定義を示しています。

最も重要なポイントは、アンダースコア_が文字として扱われるということです。

package main

func main() {
    // アンダースコアは「文字」なので、識別子の先頭に使える
    var _name string = "太郎"
    var __temp int = 42
    var _123 int = 100  // アンダースコア + 数字もOK
    
    // アンダースコアだけの変数も作れる(特殊な用途)
    _ = "この値は使わない"  // 空白識別子(blank identifier)
}

たとえ話: アンダースコアは、プログラミングの世界では「スペースの代わりに使える特別な文字」のようなものです。変数名に空白は使えませんが、アンダースコアを使えば単語を区切れます。

// スペースは使えない
// var user name string  // エラー!

// アンダースコアで区切れる
var user_name string = "Alice"  // OK!

letter(文字)の定義

letter = unicode_letter | "_" .

これは「letter(文字) は、unicode_letter(Unicode文字)またはアンダースコアのどちらか」という意味です。

つまり、識別子の先頭に使えるのは:

  • アルファベット(A-Z, a-z)
  • 日本語、中国語、ギリシャ文字など(unicode_letter)
  • アンダースコア(_)
package main

func main() {
    // すべて正しい(letterで始まる)
    var name string
    var Name string
    var _temp int
    var 名前 string
    var α float64
    
    // 間違い(数字で始まっている)
    // var 1name string  // エラー!
}

数字の4つの表記法

Goでは、数値を4種類の表記法で書けます。それぞれに使える数字が定義されています。

1. decimal_digit(10進数)

decimal_digit = "0" … "9" .

10進数は、私たちが日常的に使う0から9までの数字です。

package main

import "fmt"

func main() {
    var age int = 25        // 10進数
    var count int = 100     // 10進数
    var price float64 = 1980.50  // 10進数(小数も含む)
    
    fmt.Println(age, count, price)
}

使用場面: 最も一般的な数値表記で、日常的な計算や数値入力に使います。

2. binary_digit(2進数)

binary_digit = "0" | "1" .

2進数は、0と1だけを使う表記法です。コンピュータ内部では、すべてのデータが2進数で表現されています。

Goでは、0bまたは0Bを先頭に付けて2進数を表現します。

package main

import "fmt"

func main() {
    var flags int = 0b1010  // 2進数: 1010 = 10進数の10
    var mask int = 0b1111   // 2進数: 1111 = 10進数の15
    
    fmt.Println(flags)  // 出力: 10
    fmt.Println(mask)   // 出力: 15
    
    // ビット演算でよく使われる
    result := flags & mask  // ビット積(AND演算)
    fmt.Println(result)     // 出力: 10
}

使用場面:

  • ビット演算(フラグ管理、権限設定など)
  • 低レベルプログラミング
  • ネットワークプロトコルの実装

たとえ話: 電気のスイッチが「ON(1)」か「OFF(0)」かで表現されるように、2進数はコンピュータの基本言語です。

// 権限管理の例
const (
    読み取り = 0b0001  // 1
    書き込み = 0b0010  // 2
    実行    = 0b0100  // 4
)

権限 := 読み取り | 書き込み  // 0b0011 = 3(読み書き可能)

3. octal_digit(8進数)

octal_digit = "0" … "7" .

8進数は、0から7までの数字を使う表記法です。

Goでは、0oまたは0Oを先頭に付けて8進数を表現します(Go 1.13以降)。古い書き方として、単に0で始める方法もありますが、混乱を避けるため新しい書き方が推奨されます。

package main

import "fmt"

func main() {
    // 新しい書き方(推奨)
    var perm1 int = 0o755  // 8進数: 755
    
    // 古い書き方(非推奨だが動作する)
    var perm2 int = 0755   // 8進数: 755
    
    fmt.Println(perm1)  // 出力: 493 (10進数に変換)
    fmt.Println(perm2)  // 出力: 493
}

使用場面:

  • Unixのファイルパーミッション(権限設定)
  • 一部のハードウェア制御

実例: ファイルパーミッション

package main

import (
    "fmt"
    "os"
)

func main() {
    // ファイルを作成(パーミッション: 0o644)
    // 0o644 = 所有者:読み書き、グループ:読み、その他:読み
    file, err := os.OpenFile("test.txt", os.O_CREATE|os.O_WRONLY, 0o644)
    if err != nil {
        fmt.Println("エラー:", err)
        return
    }
    defer file.Close()
    
    fmt.Println("ファイルを作成しました(パーミッション: 0o644)")
}

たとえ話: 8進数は、「3ビットずつ」まとめて表現できるので、2進数と10進数の中間的な使いやすさがあります。

4. hex_digit(16進数)

hex_digit = "0" … "9" | "A" … "F" | "a" … "f" .

16進数は、0から9と、A(10)からF(15)までを使う表記法です。大文字でも小文字でもOKです。

Goでは、0xまたは0Xを先頭に付けて16進数を表現します。

package main

import "fmt"

func main() {
    var color int = 0xFF5733  // 16進数(色コード)
    var addr int = 0x1000     // 16進数(メモリアドレスなど)
    
    // 大文字でも小文字でもOK
    var hex1 int = 0xABCD
    var hex2 int = 0xabcd
    
    fmt.Println(color)  // 出力: 16733815
    fmt.Println(addr)   // 出力: 4096
    fmt.Println(hex1 == hex2)  // 出力: true
}

使用場面:

  • 色の表現(RGB、HTMLカラーコード)
  • メモリアドレス
  • バイトデータの表現
  • 暗号化やハッシュ値

実例: 色の表現

package main

import "fmt"

func main() {
    // HTMLカラーコード風
    赤 := 0xFF0000    // R:255, G:0,   B:0
    緑 := 0x00FF00    // R:0,   G:255, B:0
    青 := 0x0000FF    // R:0,   G:0,   B:255
    白 := 0xFFFFFF    // R:255, G:255, B:255
    黒 := 0x000000    // R:0,   G:0,   B:0
    
    fmt.Printf("赤: %06X\n", 赤)  // 出力: 赤: FF0000
    fmt.Printf("緑: %06X\n", 緑)  // 出力: 緑: 00FF00
    fmt.Printf("青: %06X\n", 青)  // 出力: 青: 0000FF
}

実例: バイトデータの表現

package main

import "fmt"

func main() {
    // バイト配列を16進数で初期化
    data := []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F}  // "Hello"のASCIIコード
    
    fmt.Printf("16進数: % X\n", data)  // 出力: 16進数: 48 65 6C 6C 6F
    fmt.Printf("文字列: %s\n", data)    // 出力: 文字列: Hello
}

たとえ話: 16進数は、「4ビットずつ」を1文字で表現できるので、バイナリデータを人間が読みやすい形にするのに便利です。たとえば、8ビット(1バイト)は、16進数2文字で表現できます。

数値表記法の比較表

同じ数値を異なる表記法で書いてみましょう:

package main

import "fmt"

func main() {
    // すべて10進数の「15」を表している
    var dec int = 15       // 10進数
    var bin int = 0b1111   // 2進数
    var oct int = 0o17     // 8進数
    var hex int = 0xF      // 16進数
    
    fmt.Println(dec, bin, oct, hex)  // 出力: 15 15 15 15
    fmt.Println(dec == bin && bin == oct && oct == hex)  // 出力: true
}
10進数2進数8進数16進数
00b00o00x0
10b10o10x1
80b10000o100x8
150b11110o170xF
160b100000o200x10
2550b111111110o3770xFF

どの表記法をいつ使う?

10進数: 最も一般的。日常的な計算、ユーザー入力、ビジネスロジックなど

var age int = 25
var price float64 = 1980.50

2進数: ビット演算、フラグ管理、低レベルプログラミング

const (
    読み取り = 0b0001
    書き込み = 0b0010
    実行    = 0b0100
)

8進数: Unixファイルパーミッション

os.OpenFile("file.txt", os.O_CREATE, 0o644)

16進数: 色コード、バイトデータ、メモリアドレス、ハッシュ値

color := 0xFF5733
data := []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F}

まとめ: 文字と数字の定義で覚えておくべきこと

  1. アンダースコア_は文字として扱われる → 識別子の先頭に使える
  2. 10進数 → 日常的な数値表現(0-9)
  3. 2進数 → ビット演算に便利(0b prefix、0と1のみ)
  4. 8進数 → ファイルパーミッションで使用(0o prefix、0-7)
  5. 16進数 → 色やバイトデータに便利(0x prefix、0-9とA-F)

実用的なアドバイス:

  • 基本的には10進数を使う
  • ビット演算では2進数が直感的
  • ファイル操作では8進数が必要なことも
  • 色やバイナリデータは16進数が便利
// 実用的な使い分け例
package main

import (
    "fmt"
    "os"
)

func main() {
    // 10進数: 通常の計算
    count := 100
    
    // 2進数: フラグ管理
    flags := 0b1010
    
    // 8進数: ファイルパーミッション
    os.OpenFile("file.txt", os.O_CREATE, 0o644)
    
    // 16進数: 色コード
    backgroundColor := 0xFFFFFF
    
    fmt.Println(count, flags, backgroundColor)
}

どの表記法も内部的には同じバイナリデータとして扱われますが、人間が読みやすく、目的に合った表記法を選ぶことが大切です!

おわりに 

本日は、Go言語の言語仕様について解説しました。

よっしー
よっしー

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

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました