Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 19] ファイルの概要

このコミットは、Go言語の初期開発段階における文法定義の調整に関するものです。具体的には、構造体(struct)とインターフェース(interface)の型定義において、フィールドやメソッドの宣言の最後にセミコロンを記述することが任意となるように文法が修正されました。これにより、Go言語の設計思想である「簡潔さ」と「読みやすさ」がさらに強化され、開発者がより自然なコード記述を行えるようになりました。

コミット

commit 2aae3fcbafb35a483da59d08f31e1b96c840cf74
Author: Rob Pike <r@golang.org>
Date:   Fri Mar 7 18:01:09 2008 -0800

    fix grammar for struct and interface types to make final semicolon optional
    
    SVN=111810

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/2aae3fcbafb35a483da59d08f31e1b96c840cf74

元コミット内容

このコミットは、Go言語の構造体とインターフェースの型定義における文法を修正し、末尾のセミコロンをオプションにするものです。

変更の背景

Go言語は、C言語のようなコンパイル型言語の効率性と、動的型付け言語のシンプルさや可読性を兼ね備えることを目指して設計されました。その設計思想の一つに、コードの記述をより簡潔にし、視覚的なノイズを減らすというものがあります。

初期のGo言語の文法では、構造体のフィールド宣言やインターフェースのメソッド宣言の各行の終わりにセミコロンが必須でした。しかし、これは冗長であり、特に複数行にわたる定義の場合には、コードの可読性を損なう可能性がありました。Go言語の設計者たちは、セミコロンの自動挿入(Automatic Semicolon Insertion: ASI)というメカニズムを導入することで、ほとんどのセミコロンを省略可能にしました。このコミットは、その設計思想を構造体とインターフェースの型定義にも適用し、より一貫性のある、そしてよりGoらしい文法を実現するための変更です。

この変更は、Go言語がまだ初期の仕様策定段階にあった2008年に行われました。当時のGoはまだSubversion (SVN) をバージョン管理システムとして使用しており、doc/go_lang.txtというファイルは、Go言語の初期の言語仕様書のような役割を担っていたと考えられます。この時期にこのような文法的な調整が行われたことは、Go言語が最初から開発者の使いやすさとコードの簡潔さを重視していたことを示しています。

前提知識の解説

  • Go言語の文法とセミコロンの自動挿入 (ASI): Go言語は、C言語に似た文法を持ちますが、セミコロンの扱いには大きな違いがあります。Goの字句解析器(lexer)は、特定のルールに基づいて自動的にセミコロンを挿入します。これにより、開発者は通常、行の終わりにセミコロンを明示的に記述する必要がありません。例えば、x = 1 の後に改行があれば、自動的にセミコロンが挿入され、x = 1; と解釈されます。このルールは、if文やfor文の開き括弧{が前の行と同じ行になければならない理由でもあります。もし{が次の行にあると、その前にセミコロンが自動挿入され、文法エラーとなるためです。
  • 構造体 (Struct): 構造体は、異なる型のフィールド(変数)をまとめて一つの新しい型として定義するためのものです。C言語の構造体や、オブジェクト指向言語におけるクラスのデータ部分に似ています。Goでは、構造体は値型であり、メソッドを持つことができます。
  • インターフェース (Interface): インターフェースは、メソッドのシグネチャ(名前、引数、戻り値)の集合を定義する型です。Goのインターフェースは、型がそのインターフェースのすべてのメソッドを実装していれば、そのインターフェースを満たすと見なされます(暗黙的な実装)。これにより、柔軟なポリモーフィズムを実現し、疎結合な設計を促進します。

技術的詳細

このコミットの技術的な核心は、Go言語の形式文法(BNF記法に似たもの)の変更にあります。変更されたのは、doc/go_lang.txtファイル内のStructTypeInterfaceTypeの定義です。

変更前:

  StructType = 'struct' '{' { FieldDecl } '}' .
  FieldDecl = IdentifierList Type ';' .

  InterfaceType = 'interface' '{' { MethodDecl } '}' .
  MethodDecl = identifier Parameters [ Result ] ';' .

この定義では、FieldDeclMethodDeclの末尾に明示的にセミコロン(;)が必須とされていました。また、StructTypeInterfaceTypeの定義内で{ FieldDecl }{ MethodDecl }と記述されている部分は、「0個以上のFieldDecl(またはMethodDecl)が続く」ことを意味します。これは、各宣言の後にセミコロンが必須であることを示唆しています。

変更後:

  StructType = 'struct' '{' [ FieldDecl { ';' FieldDecl } [ ';' ] ] '}' .
  FieldDecl = IdentifierList Type .

  InterfaceType = 'interface' '{' [ MethodDecl { ';' MethodDecl } [ ';' ] ] '}' .
  MethodDecl = identifier Parameters [ Result ] .

この変更により、以下の点が実現されました。

  1. FieldDeclMethodDeclからのセミコロンの削除: FieldDeclMethodDecl自体の定義から末尾のセミコロンが削除されました。これは、これらの宣言の後にセミコロンが必須ではなくなったことを意味します。
  2. StructTypeInterfaceTypeの定義の変更:
    • [ FieldDecl { ';' FieldDecl } [ ';' ] ]という新しい記法が導入されました。
    • [...]は「オプション」を意味します。つまり、FieldDecl(またはMethodDecl)のリスト全体がオプションであることを示します。これにより、空の構造体やインターフェース(例: struct {}interface {})が有効になります。
    • FieldDecl { ';' FieldDecl }は、「FieldDeclの後にセミコロンと別のFieldDeclが続く」というパターンが0回以上繰り返されることを意味します。これにより、複数のフィールドやメソッドがセミコロンで区切られて記述されることを許容します。
    • 最後の[ ';' ]は、「末尾にオプションのセミコロンが存在してもよい」ことを意味します。これにより、最後のフィールドやメソッドの後にセミコロンがあってもなくても、どちらも有効な文法となります。

この文法変更は、Go言語のセミコロン自動挿入の原則と完全に一致し、開発者がより自然な形で構造体やインターフェースを定義できるようになりました。例えば、以下のような記述が可能になります。

type MyStruct struct {
    Field1 int
    Field2 string // セミコロンなし
}

type MyInterface interface {
    Method1()
    Method2() error // セミコロンなし
}

コアとなるコードの変更箇所

変更はdoc/go_lang.txtファイルに集中しており、Go言語の形式文法定義が修正されています。

--- a/doc/go_lang.txt
+++ b/doc/go_lang.txt
@@ -601,8 +601,8 @@ Struct types are similar to C structs.
 Each field of a struct represents a variable within the data
 structure.
 
-  StructType = 'struct' '{' { FieldDecl } '}' .
-  FieldDecl = IdentifierList Type ';' .
+  StructType = 'struct' '{' [ FieldDecl { ';' FieldDecl } [ ';' ] ] '}' .
+  FieldDecl = IdentifierList Type .
 
      // An empty struct.
      struct {}
@@ -768,8 +768,8 @@ Interface types
 
 An interface type denotes a set of methods.
 
-  InterfaceType = 'interface' '{' { MethodDecl } '}' .
-  MethodDecl = identifier Parameters [ Result ] ';' .
+  InterfaceType = 'interface' '{' [ MethodDecl { ';' MethodDecl } [ ';' ] ] '}' .
+  MethodDecl = identifier Parameters [ Result ] .
 
   // A basic file interface.
   type File interface {

コアとなるコードの解説

この変更は、Go言語の構文解析器が構造体とインターフェースの定義をどのように解釈するかを直接変更するものです。

  • FieldDecl = IdentifierList Type .: 構造体のフィールド宣言において、型名の後にセミコロンが不要になりました。これは、Goの自動セミコロン挿入ルールと整合性が取れています。
  • MethodDecl = identifier Parameters [ Result ] .: インターフェースのメソッド宣言においても、同様にセミコロンが不要になりました。
  • StructType = 'struct' '{' [ FieldDecl { ';' FieldDecl } [ ';' ] ] '}' .:
    • [ FieldDecl { ';' FieldDecl } [ ';' ] ]: この部分が最も重要です。
      • 外側の[]は、構造体内にフィールドが全くない場合(空の構造体 struct {})を許容します。
      • FieldDecl { ';' FieldDecl }: 複数のフィールドがセミコロンで区切られて記述されることを許可します。例えば、Field1 int; Field2 string のような形式です。
      • 内側の[ ';' ]: 最後のフィールド宣言の後にセミコロンがあってもなくても良いことを示します。これにより、Field1 int; Field2 string; のように末尾にセミコロンがあっても、Field1 int; Field2 string のようにセミコロンがなくても、どちらも有効な文法となります。

この変更により、Go言語の構造体やインターフェースの定義は、より自然で、C言語のような厳密なセミコロンの強制から解放され、Goらしい簡潔な記述スタイルに近づきました。

関連リンク

参考にした情報源リンク

  • Go言語のセミコロン自動挿入に関する公式ドキュメント: https://go.dev/blog/semicolon
  • Go言語の構造体に関するドキュメント: https://go.dev/tour/basics/18
  • Go言語のインターフェースに関するドキュメント: https://go.dev/tour/methods/10
  • Go言語の初期のバージョン管理システムに関する情報 (Brad Fitzpatrickのブログ): https://www.aosabook.org/en/go.html (SVNからPerforceへの移行に関する言及がある可能性があります)
  • Web検索結果 (Google Search):
    • "Go language history struct interface semicolon optional"
    • "Go language specification struct type grammar early versions"
    • "Go language specification interface type grammar early versions"
    • "SVN=111810 Go commit Rob Pike"