KDOC 402: Goの識別子の境界を探る

この文書のステータス

  • 作成
    • 2025-06-21 貴島
  • レビュー
    • <署名>

概要

多くの現代的なプログラミング言語では識別子にUnicodeの文字(コードポイント)を使えるということを知っていたが、ちゃんとGoの仕様を調べたことはなかった。確認する。

最初に、何も調べずに実行してみて確かめてみる。違和感がすごいが、英語ネイティブが見ているのはこういう景色なのだろう。

import "fmt"
func main() {
        // 変数名に日本語が使える
        あ := "a"
        fmt.Println(あ)

        // 関数名に日本語が使える
        漢字()

        // 型名に日本語が使える
        type 地名 struct {}
        var 江戸川橋 地名
        fmt.Println(江戸川橋)
}

func 漢字() {}
a
{}

調べてみる。

言語仕様書によると、識別子(identifier)の定義はこうだ。出てきた letter, unicode_letter も辿って調べた。

identifier = letter { letter | unicode_digit } .
letter     = unicode_letter | "_" .
unicode_letter = /* a Unicode code point categorized as "Letter" */ .

ここからわかること、考察。

  • Unicodeにはカテゴリという概念がある。letter(文字), mark(結合記号), number(数字), punctuation(句読点), …
    • 結合記号はアクセント記号のように、ほかの文字と組み合わせて使う記号のことである
    • たとえば漢字はletterのサブカテゴリotherに属する
  • 識別子の先頭にletterカテゴリの文字があれば、あとはなんでもいい。逆にいえば、結合記号、数字、句読点、…から開始できない
  • アンダースコア _ は句読点カテゴリの文字である。例外的にletterとして許容されている
    • 自然に使っていて、全く意識してなかった

以上から、無効なパターンを試した1

tmpfile=$(mktemp /tmp/tmpgo.XXXXXX.go)

cat > $tmpfile <<EOF
package main

func main() {
  // 先頭のアクセント記号は不可
  ◌̀ := "あ"
  print(◌̀)

  // 先頭の数字は不可
  9 := "あ"
  print(9)

  // 先頭の漢数字はletter扱いなので問題ない
  九 := "あ"
  print(九)

  // 先頭の句読点は不可
  、 := "あ"
  print(、)

  // 先頭のシンボルは不可
  👍 := "あ"
  print(👍)
}
EOF

go run $tmpfile 2>&1
rm $tmpfile
# command-line-arguments
/tmp/tmpgo.FO1KQz.go:5:3: invalid character U+25CC '◌' in identifier
/tmp/tmpgo.FO1KQz.go:5:6: invalid character U+0300 '̀' in identifier
/tmp/tmpgo.FO1KQz.go:6:9: invalid character U+25CC '◌' in identifier
/tmp/tmpgo.FO1KQz.go:6:12: invalid character U+0300 '̀' in identifier
/tmp/tmpgo.FO1KQz.go:9:3: identifier cannot begin with digit U+FF19 '9'
/tmp/tmpgo.FO1KQz.go:10:9: identifier cannot begin with digit U+FF19 '9'
/tmp/tmpgo.FO1KQz.go:17:3: invalid character U+3001 '、' in identifier
/tmp/tmpgo.FO1KQz.go:18:9: invalid character U+3001 '、' in identifier
/tmp/tmpgo.FO1KQz.go:21:3: invalid character U+1F44D '👍' in identifier
/tmp/tmpgo.FO1KQz.go:22:9: invalid character U+1F44D '👍' in identifier
/tmp/tmpgo.FO1KQz.go:22:9: too many errors

調べる前の認識は、正確ではなかったのがわかった。

関連

Footnotes:

1

org-babelで標準エラーを出すためシェルスクリプトから実行している。