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

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

このコミットは、Go言語の標準ライブラリ sort パッケージ内の example_interface_test.go ファイルに対する変更です。具体的には、sort.Interface の使用例をより簡潔にし、パッケージレベルに移動させることを目的としています。

コミット

commit 49eeef5927b37a96d1bb733197cff7ea974aad2c
Author: Andrew Gerrand <adg@golang.org>
Date:   Mon Sep 16 13:02:01 2013 +1000

    sort: move example to package level and simplify further

    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/13634044

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

https://github.com/golang/go/commit/49eeef5927b37a96d1bb733197cff7ea974aad2c

元コミット内容

sort: move example to package level and simplify further

このコミットメッセージは、sort パッケージの例をパッケージレベルに移動させ、さらに簡素化することを示しています。

変更の背景

Go言語の標準ライブラリの例は、その機能の利用方法を示す上で非常に重要です。このコミットの背景には、sort パッケージの Interface の使用例をより分かりやすく、かつGoのイディオムに沿った形に改善するという意図があります。

元のコードでは、ExampleInterface() という関数名が使われていましたが、Goの Example 関数は、パッケージレベルで Example という名前で定義することで、go doc コマンドや godoc ツールによって自動的にドキュメントとして抽出され、実行可能なテストとしても機能します。これにより、ユーザーはコードの動作を簡単に確認できるようになります。

また、[]*Person のようにポインタのスライスを使用していた部分を []Person のように値のスライスに変更することで、コードの記述がより簡潔になり、不要なポインタのデリファレンスを避けることができます。これは、Goにおいて構造体を値として扱うことが一般的であるという設計思想にも合致しています。

前提知識の解説

このコミットを理解するためには、以下のGo言語の概念と sort パッケージの知識が必要です。

  1. Go言語の sort パッケージ:

    • sort パッケージは、Goのスライスをソートするための機能を提供します。
    • ソートの対象となる型は、sort.Interface インターフェースを実装する必要があります。
    • sort.Interface は以下の3つのメソッドを定義しています。
      • Len() int: ソート対象の要素数を返します。
      • Swap(i, j int): インデックス ij の要素を入れ替えます。
      • Less(i, j int) bool: インデックス i の要素がインデックス j の要素よりも小さい(ソート順で前になる)場合に true を返します。
    • sort.Sort(data Interface) 関数に sort.Interface を実装した型を渡すことで、ソートが実行されます。
  2. Go言語の Example 関数:

    • Goのテストファイル(_test.go で終わるファイル)内に Example というプレフィックスを持つ関数を定義すると、それは特別な意味を持ちます。
    • func Example(): パッケージ全体の例として扱われます。
    • func ExampleF(): 関数 F の例として扱われます。
    • func ExampleT_M(): 型 T のメソッド M の例として扱われます。
    • これらの Example 関数は、go doc コマンドでドキュメントとして表示されるだけでなく、go test コマンドで実行可能なテストとしても機能します。// Output: コメントに記述された出力と実際の出力が一致するかどうかを検証します。これにより、ドキュメントとコードの整合性が保たれます。
  3. ポインタと値:

    • Goでは、変数を値として渡すか、ポインタとして渡すかを選択できます。
    • 値として渡すと、元のデータのコピーが渡されます。
    • ポインタとして渡すと、元のデータのメモリアドレスが渡され、関数内で元のデータを変更できます。
    • スライスの場合、[]T は型 T の値のスライスを意味し、[]*T は型 T へのポインタのスライスを意味します。
    • 一般的に、Goでは小さな構造体や、変更が頻繁に発生しない構造体は値として扱うことが推奨されます。これにより、ガベージコレクションの負荷を軽減し、コードを簡潔に保つことができます。

技術的詳細

このコミットは、sort パッケージの example_interface_test.go ファイルにおける ExampleInterface 関数の変更に焦点を当てています。

変更の核心は以下の2点です。

  1. ExampleInterface() から Example() への関数名変更:

    • Goの Example 関数の命名規則に従い、ExampleInterface() という特定のインターフェースの例を示す関数名を、パッケージ全体の例を示す Example() に変更しました。これにより、go doc sort を実行した際に、この例が sort パッケージの主要な使用例として表示されるようになります。
    • また、go test 実行時にこの例が自動的にテストされ、出力が期待通りであることを検証します。
  2. ByAge []*Person から ByAge []Person への変更、および people スライスの初期化の簡素化:

    • 元のコードでは、ByAge 型が []*Person (Person構造体へのポインタのスライス) として定義されており、people スライスも []*Person として初期化されていました。
    • 変更後、ByAge 型は []Person (Person構造体の値のスライス) となり、people スライスも []Person として初期化されます。
    • これに伴い、people スライスの初期化も &Person{Name: "Bob", Age: 31} のようなポインタの取得ではなく、{"Bob", 31} のような構造体リテラルによる値の直接初期化に簡素化されています。これは、Person 構造体がエクスポートされていないフィールド(NameAge)を持つため、フィールド名を省略した順序での初期化が可能です。
    • この変更により、sort.Interface を実装する ByAge 型がポインタではなく値のスライスを扱うようになり、コードがより直接的で読みやすくなります。Goでは、構造体を値として扱うことが一般的であり、特にソートのような操作では、要素のコピーが発生してもパフォーマンス上の大きな問題がない限り、値のスライスを使用する方が簡潔です。

これらの変更は、Goのイディオムに沿ったコードの記述を促進し、ドキュメンテーションとテストの自動化を最大限に活用するためのものです。

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

--- a/src/pkg/sort/example_interface_test.go
+++ b/src/pkg/sort/example_interface_test.go
@@ -20,18 +20,18 @@ func (p Person) String() string {
 
 // ByAge implements sort.Interface for []Person based on
 // the Age field.
-type ByAge []*Person
+type ByAge []Person
 
 func (a ByAge) Len() int           { return len(a) }
 func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
 func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
 
-func ExampleInterface() {
-	people := []*Person{
-		&Person{Name: "Bob", Age: 31},\
-		&Person{Name: "John", Age: 42},\
-		&Person{Name: "Michael", Age: 17},\
-		&Person{Name: "Jenny", Age: 26},\
+func Example() {
+	people := []Person{
+		{"Bob", 31},\
+		{"John", 42},\
+		{"Michael", 17},\
+		{"Jenny", 26},\
 	}
 
 	fmt.Println(people)

コアとなるコードの解説

上記の差分から、以下の変更点とその意図が読み取れます。

  1. type ByAge []*Person から type ByAge []Person への変更:

    • これは ByAge 型がソートする対象を、Person 構造体へのポインタのスライスから、Person 構造体の値のスライスへと変更したことを意味します。
    • これにより、Less メソッド内で a[i].Age のように直接フィールドにアクセスできるようになり、ポインタのデリファレンス((*a[i]).Age のような記述)が不要になります。コードがより簡潔になります。
  2. func ExampleInterface() から func Example() への変更:

    • Goの Example 関数の命名規則に従い、関数名を Example に変更しました。
    • この変更により、この関数は sort パッケージ全体の例として認識され、go doc sort コマンドで表示されるドキュメントに自動的に含まれるようになります。
    • また、go test 実行時にこの例がテストとして実行され、その出力が // Output: コメントに記述された内容と一致するかどうかが検証されます。
  3. people := []*Person{...} から people := []Person{...} への変更:

    • people スライスの型が Person 構造体のポインタのスライスから、Person 構造体の値のスライスに変更されました。これは ByAge 型の変更と整合性を保つためのものです。
  4. &Person{Name: "Bob", Age: 31} から {"Bob", 31} への初期化の簡素化:

    • Person 構造体の初期化において、ポインタを取得する & 演算子とフィールド名を省略し、{"Bob", 31} のように直接値を指定する形式に変更されました。
    • これは、Person 構造体のフィールドがエクスポートされていない(小文字で始まる)ため、構造体リテラルでフィールド名を省略して順序通りに値を指定できるGoの機能を利用したものです。これにより、コードがさらに簡潔になります。

これらの変更は、Goのイディオムに沿ったコードの記述を促進し、sort パッケージの例をより分かりやすく、かつGoのツールチェーン(go doc, go test)と連携して機能するように改善することを目的としています。

関連リンク

参考にした情報源リンク

  • https://golang.org/cl/13634044 (Goのコードレビューシステムにおけるこのコミットの変更リスト)
  • Go言語の公式ドキュメントおよびGoコミュニティの慣習に関する一般的な知識。
  • Go言語におけるポインタと値の扱いに関する一般的なプログラミング知識。
  • Go言語の構造体リテラルに関する知識。# [インデックス 17607] ファイルの概要

このコミットは、Go言語の標準ライブラリ sort パッケージ内の example_interface_test.go ファイルに対する変更です。具体的には、sort.Interface の使用例をより簡潔にし、パッケージレベルに移動させることを目的としています。

コミット

commit 49eeef5927b37a96d1bb733197cff7ea974aad2c
Author: Andrew Gerrand <adg@golang.org>
Date:   Mon Sep 16 13:02:01 2013 +1000

    sort: move example to package level and simplify further

    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/13634044

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

https://github.com/golang/go/commit/49eeef5927b37a96d1bb733197cff7ea974aad2c

元コミット内容

sort: move example to package level and simplify further

このコミットメッセージは、sort パッケージの例をパッケージレベルに移動させ、さらに簡素化することを示しています。

変更の背景

Go言語の標準ライブラリの例は、その機能の利用方法を示す上で非常に重要です。このコミットの背景には、sort パッケージの Interface の使用例をより分かりやすく、かつGoのイディオムに沿った形に改善するという意図があります。

元のコードでは、ExampleInterface() という関数名が使われていましたが、Goの Example 関数は、パッケージレベルで Example という名前で定義することで、go doc コマンドや godoc ツールによって自動的にドキュメントとして抽出され、実行可能なテストとしても機能します。これにより、ユーザーはコードの動作を簡単に確認できるようになります。

また、[]*Person のようにポインタのスライスを使用していた部分を []Person のように値のスライスに変更することで、コードの記述がより簡潔になり、不要なポインタのデリファレンスを避けることができます。これは、Goにおいて構造体を値として扱うことが一般的であるという設計思想にも合致しています。

前提知識の解説

このコミットを理解するためには、以下のGo言語の概念と sort パッケージの知識が必要です。

  1. Go言語の sort パッケージ:

    • sort パッケージは、Goのスライスをソートするための機能を提供します。
    • ソートの対象となる型は、sort.Interface インターフェースを実装する必要があります。
    • sort.Interface は以下の3つのメソッドを定義しています。
      • Len() int: ソート対象の要素数を返します。
      • Swap(i, j int): インデックス ij の要素を入れ替えます。
      • Less(i, j int) bool: インデックス i の要素がインデックス j の要素よりも小さい(ソート順で前になる)場合に true を返します。
    • sort.Sort(data Interface) 関数に sort.Interface を実装した型を渡すことで、ソートが実行されます。
  2. Go言語の Example 関数:

    • Goのテストファイル(_test.go で終わるファイル)内に Example というプレフィックスを持つ関数を定義すると、それは特別な意味を持ちます。
    • func Example(): パッケージ全体の例として扱われます。
    • func ExampleF(): 関数 F の例として扱われます。
    • func ExampleT_M(): 型 T のメソッド M の例として扱われます。
    • これらの Example 関数は、go doc コマンドでドキュメントとして表示されるだけでなく、go test コマンドで実行可能なテストとしても機能します。// Output: コメントに記述された出力と実際の出力が一致するかどうかを検証します。これにより、ドキュメントとコードの整合性が保たれます。
  3. ポインタと値:

    • Goでは、変数を値として渡すか、ポインタとして渡すかを選択できます。
    • 値として渡すと、元のデータのコピーが渡されます。
    • ポインタとして渡すと、元のデータのメモリアドレスが渡され、関数内で元のデータを変更できます。
    • スライスの場合、[]T は型 T の値のスライスを意味し、[]*T は型 T へのポインタのスライスを意味します。
    • 一般的に、Goでは小さな構造体や、変更が頻繁に発生しない構造体は値として扱うことが推奨されます。これにより、ガベージコレクションの負荷を軽減し、コードを簡潔に保つことができます。

技術的詳細

このコミットは、sort パッケージの example_interface_test.go ファイルにおける ExampleInterface 関数の変更に焦点を当てています。

変更の核心は以下の2点です。

  1. ExampleInterface() から Example() への関数名変更:

    • Goの Example 関数の命名規則に従い、ExampleInterface() という特定のインターフェースの例を示す関数名を、パッケージ全体の例を示す Example() に変更しました。これにより、go doc sort を実行した際に、この例が sort パッケージの主要な使用例として表示されるようになります。
    • また、go test 実行時にこの例が自動的にテストされ、出力が期待通りであることを検証します。
  2. ByAge []*Person から ByAge []Person への変更、および people スライスの初期化の簡素化:

    • 元のコードでは、ByAge 型が []*Person (Person構造体へのポインタのスライス) として定義されており、people スライスも []*Person として初期化されていました。
    • 変更後、ByAge 型は []Person (Person構造体の値のスライス) となり、people スライスも []Person として初期化されます。
    • これに伴い、people スライスの初期化も &Person{Name: "Bob", Age: 31} のようなポインタの取得ではなく、{"Bob", 31} のような構造体リテラルによる値の直接初期化に簡素化されています。これは、Person 構造体がエクスポートされていないフィールド(NameAge)を持つため、フィールド名を省略した順序での初期化が可能です。
    • この変更により、sort.Interface を実装する ByAge 型がポインタではなく値のスライスを扱うようになり、コードがより直接的で読みやすくなります。Goでは、構造体を値として扱うことが一般的であり、特にソートのような操作では、要素のコピーが発生してもパフォーマンス上の大きな問題がない限り、値のスライスを使用する方が簡潔です。

これらの変更は、Goのイディオムに沿ったコードの記述を促進し、ドキュメンテーションとテストの自動化を最大限に活用するためのものです。

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

--- a/src/pkg/sort/example_interface_test.go
+++ b/src/pkg/sort/example_interface_test.go
@@ -20,18 +20,18 @@ func (p Person) String() string {
 
 // ByAge implements sort.Interface for []Person based on
 // the Age field.
-type ByAge []*Person
+type ByAge []Person
 
 func (a ByAge) Len() int           { return len(a) }
 func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
 func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
 
-func ExampleInterface() {\
-	people := []*Person{\
-		&Person{Name: "Bob", Age: 31},\
-		&Person{Name: "John", Age: 42},\
-		&Person{Name: "Michael", Age: 17},\
-		&Person{Name: "Jenny", Age: 26},\
+func Example() {\
+	people := []Person{\
+		{"Bob", 31},\
+		{"John", 42},\
+		{"Michael", 17},\
+		{"Jenny", 26},\
 	}
 
 	fmt.Println(people)

コアとなるコードの解説

上記の差分から、以下の変更点とその意図が読み取れます。

  1. type ByAge []*Person から type ByAge []Person への変更:

    • これは ByAge 型がソートする対象を、Person 構造体へのポインタのスライスから、Person 構造体の値のスライスへと変更したことを意味します。
    • これにより、Less メソッド内で a[i].Age のように直接フィールドにアクセスできるようになり、ポインタのデリファレンス((*a[i]).Age のような記述)が不要になります。コードがより簡潔になります。
  2. func ExampleInterface() から func Example() への変更:

    • Goの Example 関数の命名規則に従い、関数名を Example に変更しました。
    • この変更により、この関数は sort パッケージ全体の例として認識され、go doc sort コマンドで表示されるドキュメントに自動的に含まれるようになります。
    • また、go test 実行時にこの例がテストとして実行され、その出力が // Output: コメントに記述された内容と一致するかどうかが検証されます。
  3. people := []*Person{...} から people := []Person{...} への変更:

    • people スライスの型が Person 構造体のポインタのスライスから、Person 構造体の値のスライスに変更されました。これは ByAge 型の変更と整合性を保つためのものです。
  4. &Person{Name: "Bob", Age: 31} から {"Bob", 31} への初期化の簡素化:

    • Person 構造体の初期化において、ポインタを取得する & 演算子とフィールド名を省略し、{"Bob", 31} のように直接値を指定する形式に変更されました。
    • これは、Person 構造体のフィールドがエクスポートされていない(小文字で始まる)ため、構造体リテラルでフィールド名を省略して順序通りに値を指定できるGoの機能を利用したものです。これにより、コードがさらに簡潔になります。

これらの変更は、Goのイディオムに沿ったコードの記述を促進し、sort パッケージの例をより分かりやすく、かつGoのツールチェーン(go doc, go test)と連携して機能するように改善することを目的としています。

関連リンク

参考にした情報源リンク

  • https://golang.org/cl/13634044 (Goのコードレビューシステムにおけるこのコミットの変更リスト)
  • Go言語の公式ドキュメントおよびGoコミュニティの慣習に関する一般的な知識。
  • Go言語におけるポインタと値の扱いに関する一般的なプログラミング知識。
  • Go言語の構造体リテラルに関する知識。