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

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

このコミットは、Go言語の標準ライブラリstringsパッケージ内のFieldsFunc関数の使用例をexample_test.goファイルに追加するものです。これにより、FieldsFuncの機能と使い方をより明確に示し、開発者がこの関数を理解しやすくなります。

コミット

commit a6ebc88bace75ea1eb978ed2d1267e4ac3e9a99a
Author: Robin Eklind <r.eklind.87@gmail.com>
Date:   Mon Dec 16 09:43:03 2013 -0800

    strings: Add FieldsFunc example.
    
    R=golang-dev, dave
    CC=golang-dev
    https://golang.org/cl/42360043

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

https://github.com/golang/go/commit/a6ebc88bace75ea1eb978ed2d1267e4ac3e9a99a

元コミット内容

strings: Add FieldsFunc example.

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/42360043

変更の背景

Go言語の標準ライブラリは、その豊富な機能と使いやすさで知られています。stringsパッケージは文字列操作のための基本的な機能を提供しており、その中には文字列をフィールドに分割するFields関数とFieldsFunc関数があります。

Fields関数は、Unicodeのホワイトスペースに基づいて文字列を分割しますが、FieldsFuncはより柔軟で、ユーザーが定義した関数(f func(rune) bool)に基づいて分割の基準を決定できます。この柔軟性にもかかわらず、FieldsFuncの具体的な使用例が不足していると、開発者がその強力な機能を十分に活用できない可能性があります。

このコミットの背景には、FieldsFuncの利用を促進し、その挙動を明確にするために、具体的なコード例を公式ドキュメント(example_test.goファイルを通じて)に追加するという意図があります。これにより、開発者はFieldsFuncがどのようなシナリオで役立つのか、そしてどのように実装すればよいのかを、実際のコードを通じて学ぶことができます。

前提知識の解説

Go言語のstringsパッケージ

stringsパッケージは、Go言語の標準ライブラリの一部であり、UTF-8でエンコードされた文字列を操作するための多くの便利な関数を提供します。これには、文字列の結合、分割、検索、置換、大文字・小文字変換などが含まれます。

strings.FieldsFunc関数

strings.FieldsFunc(s string, f func(rune) bool) []stringは、文字列sを、ユーザーが提供する関数ftrueを返すUnicodeコードポイント(ルーン)で区切られたフィールドに分割します。連続する区切り文字は1つの区切りとして扱われ、結果のフィールドは空の文字列を含みません。

  • s: 分割対象の文字列。
  • f: 各ルーンがフィールドの区切り文字であるかどうかを決定する関数。この関数がtrueを返すと、そのルーンは区切り文字と見なされます。

例えば、fがスペースを区切り文字として定義する場合、FieldsFuncstrings.Fieldsと同様の動作をします。しかし、このコミットの例のように、英字や数字以外の文字を区切り文字として定義するなど、より複雑な分割ロジックを実装できます。

unicodeパッケージ

unicodeパッケージは、Unicode文字のプロパティをテストするための関数を提供します。このコミットの例では、以下の関数が使用されています。

  • unicode.IsLetter(r rune) bool: ルーンrがUnicodeの文字(Letter)である場合にtrueを返します。
  • unicode.IsNumber(r rune) bool: ルーンrがUnicodeの数字(Number)である場合にtrueを返します。

これらの関数は、特定の文字がアルファベットや数字であるかを効率的に判定するために使用されます。

Go言語の_test.goファイルとExample関数

Go言語では、テストファイルは通常、テスト対象のパッケージと同じディレクトリに_test.goというサフィックスを付けて配置されます。これらのファイルには、ユニットテスト、ベンチマークテスト、そして「Example」関数を含めることができます。

Example関数は、Example<FunctionName>()という命名規則に従い、特定の関数の使用例を示すために書かれます。これらの関数は、通常のテストと同様にgo testコマンドで実行されますが、その出力は特別なコメント// Output:と比較されます。この仕組みにより、Example関数は単なるコード例としてだけでなく、その出力が常に期待通りであることを保証するテストとしても機能します。

Example関数は、Goの公式ドキュメント生成ツール(go docgodoc)によって自動的に抽出され、生成されたドキュメントに組み込まれます。これにより、開発者は関数の使い方をコード例とともにより簡単に理解できるようになります。

技術的詳細

このコミットは、src/pkg/strings/example_test.goファイルに新しいExampleFieldsFunc関数を追加することで、strings.FieldsFuncの具体的な使用方法を示しています。

追加されたExampleFieldsFunc関数は以下の通りです。

func ExampleFieldsFunc() {
	f := func(c rune) bool {
		return !unicode.IsLetter(c) && !unicode.IsNumber(c)
	}
	fmt.Printf("Fields are: %q", strings.FieldsFunc("  foo1;bar2,baz3...", f))
	// Output: Fields are: ["foo1" "bar2" "baz3"]
}

この例では、FieldsFuncに渡される匿名関数fが、ルーンcが文字でも数字でもない場合にtrueを返すように定義されています。つまり、この関数は、アルファベットと数字以外のすべての文字を区切り文字として扱います。

入力文字列は" foo1;bar2,baz3..."です。

  1. 先頭のスペース2つは、ftrueを返すため区切り文字と見なされ、無視されます。
  2. "foo1"は、すべて文字または数字であるため、最初のフィールドとして抽出されます。
  3. ;は、文字でも数字でもないため、区切り文字と見なされます。
  4. "bar2"は、2番目のフィールドとして抽出されます。
  5. ,は、区切り文字と見なされます。
  6. "baz3"は、3番目のフィールドとして抽出されます。
  7. 末尾の...(ピリオド3つ)は、それぞれ区切り文字と見なされ、無視されます。

結果として、["foo1" "bar2" "baz3"]という文字列のスライスが出力されます。この出力は// Output:コメントに記述されており、go test実行時にこのExample関数の出力が期待通りであることを検証します。

この例は、FieldsFuncが単なるホワイトスペースだけでなく、任意のカスタムロジックに基づいて文字列を分割できるという強力な機能を示す良い例となっています。特に、unicodeパッケージの関数と組み合わせることで、多言語対応の文字列処理においても柔軟な分割が可能であることを示唆しています。

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

--- a/src/pkg/strings/example_test.go
+++ b/src/pkg/strings/example_test.go
@@ -7,6 +7,7 @@ package strings_test
 import (
 	"fmt"
 	"strings"
+	"unicode"
 )
 
 func ExampleFields() {
@@ -14,6 +15,14 @@ func ExampleFields() {
 	// Output: Fields are: ["foo" "bar" "baz"]
 }
 
+func ExampleFieldsFunc() {
+	f := func(c rune) bool {
+		return !unicode.IsLetter(c) && !unicode.IsNumber(c)
+	}
+	fmt.Printf("Fields are: %q", strings.FieldsFunc("  foo1;bar2,baz3...", f))
+	// Output: Fields are: ["foo1" "bar2" "baz3"]
+}
+
 func ExampleContains() {
 	fmt.Println(strings.Contains("seafood", "foo"))
 	fmt.Println(strings.Contains("seafood", "bar"))

コアとなるコードの解説

この変更は、src/pkg/strings/example_test.goファイルに対して行われました。

  1. import "unicode"の追加: ExampleFieldsFunc内でunicode.IsLetterunicode.IsNumber関数を使用するため、unicodeパッケージがインポートリストに追加されました。これは、Goのコードが外部パッケージの機能を利用する際の標準的な方法です。

  2. ExampleFieldsFunc関数の追加: この関数は、strings.FieldsFuncの具体的な使用例を提供します。

    • f := func(c rune) bool { return !unicode.IsLetter(c) && !unicode.IsNumber(c) }: これは匿名関数であり、strings.FieldsFuncの第2引数として渡される述語関数(predicate function)です。この関数は、入力されたルーンcがUnicodeの文字(Letter)でも数字(Number)でもない場合にtrueを返します。つまり、この関数は、アルファベットや数字以外のすべての文字を区切り文字として識別します。
    • fmt.Printf("Fields are: %q", strings.FieldsFunc(" foo1;bar2,baz3...", f))strings.FieldsFuncが呼び出され、入力文字列" foo1;bar2,baz3..."と、上で定義した匿名関数fが渡されます。%qフォーマット動詞は、文字列をGoの構文で引用符で囲んで出力するために使用されます。これにより、結果のスライスが["foo1" "bar2" "baz3"]のように表示されます。
    • // Output: Fields are: ["foo1" "bar2" "baz3"]: これはExample関数の特別なコメントで、この関数を実行した際の期待される標準出力が記述されています。go testコマンドがExample関数を実行する際、実際の出力がこのコメントの内容と一致するかどうかを検証します。これにより、コード例が常に正しく機能することが保証されます。

この変更は、strings.FieldsFuncの柔軟性と、unicodeパッケージとの連携による強力な文字列処理能力を、簡潔かつ効果的に示しています。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコードリポジトリ
  • Go言語のテストに関する一般的な知識
  • Unicodeの文字プロパティに関する一般的な知識