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

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

このコミットは、Go言語の標準ライブラリであるstringsパッケージのexample_test.goファイルに、より多くの使用例を追加するものです。これにより、stringsパッケージの各関数の使い方をより明確に示し、開発者がこれらの関数を理解し、適切に利用する手助けをすることを目的としています。

コミット

commit 71c8b82dd1e59f1864dd347ea76726406f871365
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date:   Mon Feb 13 14:05:57 2012 +1100

    strings: more examples
    
    R=golang-dev, adg
    CC=golang-dev
    https://golang.org/cl/5645092

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

https://github.com/golang/go/commit/71c8b82dd1e59f1864dd347ea76726406f871365

元コミット内容

strings: more examples

このコミットは、Go言語のstringsパッケージに、より多くの使用例を追加します。

変更の背景

Go言語の標準ライブラリは、その使いやすさと豊富な機能で知られています。stringsパッケージは、文字列操作のための基本的な機能を提供し、Goプログラムの多くの部分で利用されます。しかし、ライブラリの機能が豊富であるほど、各関数の具体的な使用方法や、どのような結果が期待されるのかを理解するための明確な例が重要になります。

このコミットが行われた2012年2月時点では、Go言語はまだ比較的新しい言語であり、ドキュメンテーションや使用例の充実は、言語の普及と開発者の学習体験向上に不可欠でした。特に、stringsパッケージのような頻繁に使用されるパッケージでは、直感的で分かりやすい例を提供することで、開発者がコードをより迅速に書き、一般的な文字列操作タスクを効率的に解決できるようになります。

このコミットの目的は、stringsパッケージの既存の関数に対して、より多くのExample関数を追加することです。Goのテストフレームワークでは、Example関数はドキュメンテーションの一部として扱われ、go docコマンドで表示されるだけでなく、自動的にテストとして実行され、出力が期待通りであるか検証されます。これにより、ドキュメンテーションの正確性が保証され、常に最新の動作を反映するようになります。

したがって、この変更は、stringsパッケージのドキュメンテーションを強化し、開発者がGo言語で文字列操作を行う際の生産性を向上させることを目的としています。

前提知識の解説

Go言語のstringsパッケージ

Go言語のstringsパッケージは、UTF-8でエンコードされた文字列を操作するための基本的な関数を提供します。これには、文字列の検索、置換、分割、結合、大文字・小文字変換、トリミングなど、多岐にわたる機能が含まれます。stringsパッケージの関数は、Goの標準ライブラリの一部として、Goプログラムで文字列を扱う際の基盤となります。

Go言語のExample関数

Go言語のテストパッケージ(testing)には、Example関数という特別な種類の関数があります。これは、通常のテスト関数(TestXxx)やベンチマーク関数(BenchmarkXxx)とは異なり、コードの動作例を示すために使用されます。

Example関数の特徴は以下の通りです。

  1. ドキュメンテーションとしての機能: Example関数は、go docコマンドを実行した際に、対応する関数やパッケージのドキュメンテーションの一部として表示されます。これにより、開発者は関数の使い方をコード例で直接確認できます。
  2. 自動テストとしての機能: Example関数は、go testコマンドを実行した際に、通常のテストと同様に実行されます。Example関数のコメント行にOutput:というプレフィックスで期待される出力が記述されている場合、GoのテストランナーはそのExample関数を実行し、標準出力に書き込まれた内容がOutput:に続く内容と一致するかどうかを検証します。これにより、ドキュメンテーションのコード例が常に正しく動作することが保証されます。
  3. 命名規則: Example関数は、ExampleExampleFExampleTExamplePExample_suffixExampleF_suffixExampleT_suffixExampleP_suffixといった命名規則に従います。ここでFは関数名、Tは型名、Pはパッケージ名を表します。例えば、strings.Contains関数の例であればExampleContainsという名前になります。

このコミットは、このExample関数の仕組みを利用して、stringsパッケージの各関数の使用例を豊富に追加しています。

技術的詳細

このコミットは、src/pkg/strings/example_test.goファイルに、stringsパッケージの様々な関数に対するExample関数を追加しています。追加されたExample関数は、それぞれの関数の典型的な使用方法と、その実行結果をfmt.Printlnfmt.Printfで出力し、その出力がOutput:コメントで期待される結果と一致するかをgo test時に検証します。

具体的に追加されたExample関数は以下の通りです。

  • ExampleContains(): strings.Contains関数の使用例。文字列が特定のサブストリングを含むかどうかをチェックします。
  • ExampleContainsAny(): strings.ContainsAny関数の使用例。文字列が指定された文字セットのいずれかの文字を含むかどうかをチェックします。
  • ExampleCount(): strings.Count関数の使用例。文字列内で特定のサブストリングが何回出現するかを数えます。
  • ExampleEqualFold(): strings.EqualFold関数の使用例。UTF-8文字列を大文字・小文字を区別せずに比較します。
  • ExampleIndex(): strings.Index関数の使用例。文字列内でサブストリングが最初に出現するインデックスを返します。
  • ExampleRune(): strings.IndexRune関数の使用例。文字列内で特定のルーン(Unicodeコードポイント)が最初に出現するインデックスを返します。
  • ExampleLastIndex(): strings.LastIndex関数の使用例。文字列内でサブストリングが最後に出現するインデックスを返します。
  • ExampleJoin(): strings.Join関数の使用例。文字列スライスを区切り文字で結合します。
  • ExampleRepeat(): strings.Repeat関数の使用例。文字列を指定された回数繰り返します。
  • ExampleReplace(): strings.Replace関数の使用例。文字列内のサブストリングを別のサブストリングで置換します。
  • ExampleSplit(): strings.Split関数の使用例。文字列を区切り文字で分割します。
  • ExampleSplitN(): strings.SplitN関数の使用例。文字列を区切り文字で最大N回分割します。
  • ExampleSplitAfter(): strings.SplitAfter関数の使用例。文字列を区切り文字の後に分割します。
  • ExampleSplitAfterN(): strings.SplitAfterN関数の使用例。文字列を区切り文字の後に最大N回分割します。
  • ExampleTitle(): strings.Title関数の使用例。文字列をタイトルケースに変換します。
  • ExampleToTitle(): strings.ToTitle関数の使用例。文字列をUnicodeのタイトルケースに変換します。
  • ExampleTrim(): strings.Trim関数の使用例。文字列の先頭と末尾から指定された文字セットの文字を削除します。
  • ExampleMap(): strings.Map関数の使用例。文字列の各ルーンに関数を適用して新しい文字列を生成します。例としてROT13エンコーディングが示されています。
  • ExampleTrimSpace(): strings.TrimSpace関数の使用例。文字列の先頭と末尾から空白文字を削除します。
  • ExampleNewReplacer(): strings.NewReplacer関数の使用例。複数の置換ペアを効率的に処理するためのReplacerオブジェクトを作成します。
  • ExampleToUpper(): strings.ToUpper関数の使用例。文字列を大文字に変換します。
  • ExampleToLower(): strings.ToLower関数の使用例。文字列を小文字に変換します。

これらの例は、各関数の基本的な使い方だけでなく、エッジケース(例: 空文字列の扱い)や、特定の引数(例: strings.Replacen引数、strings.SplitNn引数)が結果にどのように影響するかを示しています。

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

変更はすべてsrc/pkg/strings/example_test.goファイルに対して行われています。

--- a/src/pkg/strings/example_test.go
+++ b/src/pkg/strings/example_test.go
@@ -13,3 +13,158 @@ import (
 func ExampleFields() {
 	fmt.Printf("Fields are: %q", strings.Fields("  foo bar  baz   "))
 }
+
+// true
+// false
+// true
+// true
+func ExampleContains() {
+	fmt.Println(strings.Contains("seafood", "foo"))
+	fmt.Println(strings.Contains("seafood", "bar"))
+	fmt.Println(strings.Contains("seafood", ""))
+	fmt.Println(strings.Contains("", ""))
+}
+
+// false
+// true
+// false
+// false
+func ExampleContainsAny() {
+	fmt.Println(strings.ContainsAny("team", "i"))
+	fmt.Println(strings.ContainsAny("failure", "u & i"))
+	fmt.Println(strings.ContainsAny("foo", ""))
+	fmt.Println(strings.ContainsAny("", ""))
+
+}
+
+// 3
+// 5
+func ExampleCount() {
+	fmt.Println(strings.Count("cheese", "e"))
+	fmt.Println(strings.Count("five", "")) // before & after each rune
+}
+
+// true
+func ExampleEqualFold() {
+	fmt.Println(strings.EqualFold("Go", "go"))
+}
+
+// 4
+// -1
+func ExampleIndex() {
+	fmt.Println(strings.Index("chicken", "ken"))
+	fmt.Println(strings.Index("chicken", "dmr"))
+}
+
+// 4
+// -1
+func ExampleRune() {
+	fmt.Println(strings.IndexRune("chicken", 'k'))
+	fmt.Println(strings.IndexRune("chicken", 'd'))
+}
+
+// 0
+// 3
+// -1
+func ExampleLastIndex() {
+	fmt.Println(strings.Index("go gopher", "go"))
+	fmt.Println(strings.LastIndex("go gopher", "go"))
+	fmt.Println(strings.LastIndex("go gopher", "rodent"))
+}
+
+// foo, bar, baz
+func ExampleJoin() {
+	s := []string{"foo", "bar", "baz"}
+	fmt.Println(strings.Join(s, ", "))
+}
+
+// banana
+func ExampleRepeat() {
+	fmt.Println("ba" + strings.Repeat("na", 2))
+}
+
+// oinky oinky oink
+// moo moo moo
+func ExampleReplace() {
+	fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2))
+	fmt.Println(strings.Replace("oink oink oink", "oink", "moo", -1))
+}
+
+// ["a" "b" "c"]
+// ["" "man " "plan " "canal panama"]
+// [" " "x" "y" "z" " "]
+func ExampleSplit() {
+	fmt.Printf("%q\n", strings.Split("a,b,c", ","))
+	fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a "))
+	fmt.Printf("%q\n", strings.Split(" xyz ", ""))
+}
+
+// ["a" "b,c"]
+// [] (nil = true)
+func ExampleSplitN() {
+	fmt.Printf("%q\n", strings.SplitN("a,b,c", ",", 2))
+	z := strings.SplitN("a,b,c", ",", 0)
+	fmt.Printf("%q (nil = %v)\n", z, z == nil)
+}
+
+// ["a," "b," "c"]
+func ExampleSplitAfter() {
+	fmt.Printf("%q\n", strings.SplitAfter("a,b,c", ","))
+}
+
+// ["a," "b,c"]
+func ExampleSplitAfterN() {
+	fmt.Printf("%q\n", strings.SplitAfterN("a,b,c", ",", 2))
+}
+
+// Her Royal Highness
+func ExampleTitle() {
+	fmt.Println(strings.Title("her royal highness"))
+}
+
+// LOUD NOISES
+// ХЛЕБ
+func ExampleToTitle() {
+	fmt.Println(strings.ToTitle("loud noises"))
+	fmt.Println(strings.ToTitle("хлеб"))
+}
+
+// [Achtung]
+func ExampleTrim() {
+	fmt.Printf("[%s]", strings.Trim(" !!! Achtung !!! ", "! "))
+}
+
+// 'Gjnf oevyyvt naq gur fyvgul tbcure...
+func ExampleMap() {
+	rot13 := func(r rune) rune {
+		switch {
+		case r >= 'A' && r <= 'Z':
+			return 'A' + (r-'A'+13)%26
+		case r >= 'a' && r <= 'z':
+			return 'a' + (r-'a'+13)%26
+		}
+		return r
+	}
+	fmt.Println(strings.Map(rot13, "'Twas brillig and the slithy gopher..."))
+}
+
+// a lone gopher
+func ExampleTrimSpace() {
+	fmt.Println(strings.TrimSpace(" \t\n a lone gopher \n\t\r\n"))
+}
+
+// This is &lt;b&gt;HTML&lt;/b&gt;!
+func ExampleNewReplacer() {
+	r := strings.NewReplacer("<", "&lt;", ">", "&gt;")
+	fmt.Println(r.Replace("This is <b>HTML</b>!"))
+}
+
+// GOPHER
+func ExampleToUpper() {
+	fmt.Println(strings.ToUpper("Gopher"))
+}
+
+// gopher
+func ExampleToLower() {
+	fmt.Println(strings.ToLower("Gopher"))
+}

コアとなるコードの解説

このコミットは、src/pkg/strings/example_test.goファイルに、stringsパッケージの様々な関数に対するExample関数を大量に追加しています。

Example関数は、以下の構造に従っています。

  1. 関数定義: func ExampleFunctionName() { ... } の形式で定義されます。
  2. 関数呼び出しと出力: stringsパッケージの対象関数を呼び出し、その結果をfmt.Printlnfmt.Printfで標準出力に出力します。
  3. 期待される出力: // Output: で始まるコメント行の後に、上記の関数呼び出しによって標準出力に出力されると期待される内容が記述されています。go testコマンドが実行されると、このコメントと実際の出力が比較され、一致しない場合はテストが失敗します。

例えば、ExampleContains()関数では、strings.Contains関数の様々なケース(部分文字列が見つかる場合、見つからない場合、空文字列を検索する場合など)が示され、それぞれの結果がtrueまたはfalseとして出力されることが期待されています。

特筆すべきは、ExampleMap()関数で、strings.Map関数の使用例としてROT13エンコーディングのロジックが示されています。これは、strings.Mapがルーン単位で文字列を変換する強力な機能を持つことを具体的に示しています。

また、ExampleSplit()ExampleSplitN()ExampleSplitAfter()ExampleSplitAfterN()のように、文字列の分割に関する複数の関数に対して、それぞれの挙動の違いが明確に分かるような例が提供されています。

これらの追加されたExample関数は、stringsパッケージのドキュメンテーションを大幅に充実させ、開発者が各関数の機能と使い方を迅速に理解するための貴重なリソースとなります。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメンテーション
  • Go言語のtestingパッケージにおけるExample関数の概念に関する一般的な情報源
  • コミットメッセージと差分情報