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

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

このコミットは、Go言語の標準ライブラリである strings パッケージに、文字列内に特定の文字(群)が含まれているかを効率的に判定するための新しい関数 ContainsAnyContainsRune を追加するものです。既存の IndexAny および IndexRune 関数に対応する形で、より直感的な真偽値判定を提供します。

コミット

commit 0f0c25dcccee52c4fae3b54ca8b185984ceff1f9
Author: Scott Lawrence <bytbox@gmail.com>
Date:   Wed Nov 23 20:20:14 2011 -0800

    strings: Add ContainsAny and ContainsRune to correspond to IndexAny etc.
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/5430046

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

https://github.com/golang/go/commit/0f0c25dcccee52c4fae3b54ca8b185984ceff1f9

元コミット内容

strings: Add ContainsAny and ContainsRune to correspond to IndexAny etc.

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

変更の背景

Go言語の strings パッケージには、特定のサブストリングや文字が文字列内に存在するかどうかを判定するための Contains 関数や、その位置を返す Index 関数群が既に存在していました。しかし、IndexAny(文字列内の任意のUnicodeコードポイントのいずれかが含まれる最初のインデックスを返す)や IndexRune(文字列内の特定のUnicodeコードポイントの最初のインデックスを返す)に対応する、真偽値を直接返す Contains 系の関数が欠けていました。

このコミットは、このギャップを埋めることを目的としています。IndexAnyIndexRune が返すインデックス値が -1 でないことを確認する代わりに、よりセマンティックで読みやすい ContainsAny および ContainsRune 関数を提供することで、コードの可読性と利便性を向上させます。これは、Goの標準ライブラリにおけるAPIの一貫性を保つための一般的なパターンであり、ユーザーが特定の機能を探す際に予測しやすいインターフェースを提供します。

前提知識の解説

Go言語の strings パッケージ

strings パッケージは、Go言語におけるUTF-8でエンコードされた文字列を操作するための基本的な関数群を提供します。文字列の検索、置換、分割、結合、大文字小文字変換など、多岐にわたる機能が含まれています。

UnicodeとRune

Go言語の文字列はUTF-8でエンコードされています。これは、1つの文字が1バイト以上で表現される可能性があることを意味します。Goでは、このようなUnicodeコードポイントを表現するために rune 型が導入されています。runeint32 のエイリアスであり、単一のUnicodeコードポイントを表します。文字列を range でイテレートすると、各要素は rune 型として取得されます。

Index 系関数と Contains 系関数

  • Index(s, substr string) int: 文字列 s 内で substr が最初に出現するインデックスを返します。見つからない場合は -1 を返します。
  • IndexAny(s, chars string) int: 文字列 s 内で chars に含まれる任意のUnicodeコードポイントが最初に出現するインデックスを返します。見つからない場合は -1 を返します。
  • IndexRune(s string, r rune) int: 文字列 s 内で r が最初に出現するインデックスを返します。見つからない場合は -1 を返します。
  • Contains(s, substr string) bool: 文字列 ssubstr を含む場合に true を返します。これは内部的に Index(s, substr) != -1 と同等です。

このコミットで追加される ContainsAnyContainsRune は、それぞれ IndexAnyIndexRune の結果を真偽値に変換するラッパー関数として機能します。

技術的詳細

追加された ContainsAnyContainsRune 関数は、非常にシンプルに実装されています。それぞれ対応する IndexAny および IndexRune 関数を呼び出し、その結果が -1 (見つからなかったことを示す) でない場合に true を返します。

  • ContainsAny(s, chars string) bool:

    • 引数:
      • s: 検索対象の文字列。
      • chars: 検索するUnicodeコードポイントを含む文字列。この文字列内の任意の文字が s に含まれているかを判定します。
    • 戻り値: s 内に chars のいずれかの文字が含まれていれば true、そうでなければ false
    • 実装: return IndexAny(s, chars) >= 0
  • ContainsRune(s string, r rune) bool:

    • 引数:
      • s: 検索対象の文字列。
      • r: 検索する単一のUnicodeコードポイント(rune型)。
    • 戻り値: s 内に r が含まれていれば true、そうでなければ false
    • 実装: return IndexRune(s, r) >= 0

また、既存の Contains 関数も Index(s, substr) != -1 から Index(s, substr) >= 0 に変更されています。これは機能的には同じですが、-1 が「見つからない」ことを意味するインデックスの慣習的な表現であるため、>= 0 は「見つかった」(つまり、インデックスが0以上)という意図をより明確に示します。同様に、FieldsFuncmakeCutsetFunc 内の条件式も != -1 から >= 0 に変更され、一貫性が保たれています。

テストコードでは、これらの新しい関数が期待通りに動作するかを確認するために、様々なケース(空文字列、単一文字、複数文字、Unicode文字、特殊文字など)を網羅したテストケースが追加されています。

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

src/pkg/strings/strings.go

--- a/src/pkg/strings/strings.go
+++ b/src/pkg/strings/strings.go
@@ -64,7 +64,17 @@ func Count(s, sep string) int {

 // Contains returns true if substr is within s.
 func Contains(s, substr string) bool {
-	return Index(s, substr) != -1
+	return Index(s, substr) >= 0
+}
+
+// ContainsAny returns true if any Unicode code points in chars are within s.
+func ContainsAny(s, chars string) bool {
+	return IndexAny(s, chars) >= 0
+}
+
+// ContainsRune returns true if the Unicode code point r is within s.
+func ContainsRune(s string, r rune) bool {
+	return IndexRune(s, r) >= 0
 }

 // Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
@@ -269,7 +279,7 @@ func FieldsFunc(s string, f func(rune) bool) []string {
 			fieldStart = i
 		}
 	}
-	if fieldStart != -1 { // Last field might end at EOF.
+	if fieldStart >= 0 { // Last field might end at EOF.
 		a[na] = s[fieldStart:]
 	}
 	return a
@@ -512,7 +522,7 @@ func lastIndexFunc(s string, f func(rune) bool, truth bool) int {
 }

 func makeCutsetFunc(cutset string) func(rune) bool {
-	return func(r rune) bool { return IndexRune(cutset, r) != -1 }
+	return func(r rune) bool { return IndexRune(cutset, r) >= 0 }
 }

 // Trim returns a slice of the string s with all leading and

src/pkg/strings/strings_test.go

--- a/src/pkg/strings/strings_test.go
+++ b/src/pkg/strings/strings_test.go
@@ -908,6 +908,56 @@ func TestContains(t *testing.T) {
 	}
 }

+var ContainsAnyTests = []struct {
+	str, substr string
+	expected    bool
+}{
+	{"", "", false},
+	{"", "a", false},
+	{"", "abc", false},
+	{"a", "", false},
+	{"a", "a", true},
+	{"aaa", "a", true},
+	{"abc", "xyz", false},
+	{"abc", "xcz", true},
+	{"a☺b☻c☹d", "uvw☻xyz", true},
+	{"aRegExp*", ".(|)*+?^$[]", true},
+	{dots + dots + dots, " ", false},
+}
+
+func TestContainsAny(t *testing.T) {
+	for _, ct := range ContainsAnyTests {
+		if ContainsAny(ct.str, ct.substr) != ct.expected {
+			t.Errorf("ContainsAny(%s, %s) = %v, want %v",
+				ct.str, ct.substr, !ct.expected, ct.expected)
+		}
+	}
+}
+
+var ContainsRuneTests = []struct {
+	str      string
+	r        rune
+	expected bool
+}{
+	{"", 'a', false},
+	{"a", 'a', true},
+	{"aaa", 'a', true},
+	{"abc", 'y', false},
+	{"abc", 'c', true},
+	{"a☺b☻c☹d", 'x', false},
+	{"a☺b☻c☹d", '☻', true},
+	{"aRegExp*", '*', true},
+}
+
+func TestContainsRune(t *testing.T) {
+	for _, ct := range ContainsRuneTests {
+		if ContainsRune(ct.str, ct.r) != ct.expected {
+			t.Errorf("ContainsRune(%s, %s) = %v, want %v",
+				ct.str, ct.r, !ct.expected, ct.expected)
+		}
+	}
+}
+
 var EqualFoldTests = []struct {
 	s, t string
 	out  bool

コアとなるコードの解説

strings.go の変更点

  1. Contains 関数の修正:

    • return Index(s, substr) != -1 から return Index(s, substr) >= 0 へ変更。
    • これは機能的な変更ではなく、インデックスが「見つかった」ことを示す条件をより明確にするための表現の変更です。Index 関数は、部分文字列が見つからない場合に -1 を返すため、!= -1>= 0 は同じ論理結果をもたらします。
  2. ContainsAny 関数の追加:

    • IndexAny(s, chars) の結果が >= 0 であるかを返します。
    • これにより、chars 内の任意の文字が s に含まれているかを簡潔に判定できます。
  3. ContainsRune 関数の追加:

    • IndexRune(s, r) の結果が >= 0 であるかを返します。
    • これにより、特定の runes に含まれているかを簡潔に判定できます。
  4. FieldsFunc および makeCutsetFunc 内の条件式の修正:

    • これらの関数内の fieldStart != -1IndexRune(cutset, r) != -1 といった条件式も、>= 0 を使用するように変更されています。これは、Contains 関数の変更と同様に、コード全体でのインデックスチェックの慣習を統一するためのものです。

strings_test.go の変更点

  1. ContainsAnyTestsTestContainsAny の追加:

    • ContainsAny 関数の動作を検証するためのテストケースとテスト関数が追加されています。
    • 様々な文字列と文字セットの組み合わせに対して、期待される真偽値が正しく返されるかを確認します。Unicode文字や正規表現の特殊文字を含むケースも含まれています。
  2. ContainsRuneTestsTestContainsRune の追加:

    • ContainsRune 関数の動作を検証するためのテストケースとテスト関数が追加されています。
    • 空文字列、単一文字、複数文字、Unicode文字、特殊文字など、多様な rune と文字列の組み合わせでテストが行われます。

これらの変更により、strings パッケージはより完全で使いやすくなり、開発者は文字列内の文字の存在をより直感的にチェックできるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント (pkg.go.dev/strings)
  • Go言語のブログ記事 (go.dev/blog/strings)
  • GitHub上のGo言語リポジトリのコミット履歴
  • 一般的なGo言語の文字列操作に関する知識The user wants a detailed explanation of a Git commit. I have already read the commit data. Now I need to perform a web search to gather more context and technical details, especially regarding Go's strings package, rune type, and the IndexAny/IndexRune functions.

I will use google_web_search to find relevant information.

Here's a refined plan:

  1. Parse the commit data: (Already done in the previous turn, I have the content of 10499.txt).
  2. Understand the changes: Analyze strings.go and strings_test.go to understand the new functions ContainsAny and ContainsRune and the modifications to existing Contains, FieldsFunc, and makeCutsetFunc. (This is an internal analysis step).
  3. Research Go's strings package: Understand its purpose and common functions.
  4. Research IndexAny and IndexRune: Understand how these functions work, as the new ContainsAny and ContainsRune are based on them.
  5. Explain the background: Why were these functions added? The commit message says "to correspond to IndexAny etc." which implies a consistency reason.
  6. Explain prerequisite knowledge: What are runes, Unicode, and string manipulation in Go?
  7. Detail the technical aspects: How do ContainsAny and ContainsRune work internally? What are their signatures and return values?
  8. Describe core code changes: Point out the specific lines added/modified in strings.go and strings_test.go.
  9. Explain core code: Elaborate on the implementation of the new functions and the minor changes to existing ones.
  10. Find related links: Search for Go documentation on the strings package, especially for Contains, IndexAny, IndexRune.
  11. Identify sources: List the sources used for the explanation.

I will now perform the web searches.# [インデックス 10499] ファイルの概要

このコミットは、Go言語の標準ライブラリである strings パッケージに、文字列内に特定の文字(群)が含まれているかを効率的に判定するための新しい関数 ContainsAnyContainsRune を追加するものです。既存の IndexAny および IndexRune 関数に対応する形で、より直感的な真偽値判定を提供します。

コミット

commit 0f0c25dcccee52c4fae3b54ca8b185984ceff1f9
Author: Scott Lawrence <bytbox@gmail.com>
Date:   Wed Nov 23 20:20:14 2011 -0800

    strings: Add ContainsAny and ContainsRune to correspond to IndexAny etc.
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/5430046

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

https://github.com/golang/go/commit/0f0c25dcccee52c4fae3b54ca8b185984ceff1f9

元コミット内容

strings: Add ContainsAny and ContainsRune to correspond to IndexAny etc.

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

変更の背景

Go言語の strings パッケージには、特定のサブストリングや文字が文字列内に存在するかどうかを判定するための Contains 関数や、その位置を返す Index 関数群が既に存在していました。しかし、IndexAny(文字列内の任意のUnicodeコードポイントのいずれかが含まれる最初のインデックスを返す)や IndexRune(文字列内の特定のUnicodeコードポイントの最初のインデックスを返す)に対応する、真偽値を直接返す Contains 系の関数が欠けていました。

このコミットは、このギャップを埋めることを目的としています。IndexAnyIndexRune が返すインデックス値が -1 でないことを確認する代わりに、よりセマンティックで読みやすい ContainsAny および ContainsRune 関数を提供することで、コードの可読性と利便性を向上させます。これは、Goの標準ライブラリにおけるAPIの一貫性を保つための一般的なパターンであり、ユーザーが特定の機能を探す際に予測しやすいインターフェースを提供します。

前提知識の解説

Go言語の strings パッケージ

strings パッケージは、Go言語におけるUTF-8でエンコードされた文字列を操作するための基本的な関数群を提供します。文字列の検索、置換、分割、結合、大文字小文字変換など、多岐にわたる機能が含まれています。

UnicodeとRune

Go言語の文字列はUTF-8でエンコードされています。これは、1つの文字が1バイト以上で表現される可能性があることを意味します。Goでは、このようなUnicodeコードポイントを表現するために rune 型が導入されています。runeint32 のエイリアスであり、単一のUnicodeコードポイントを表します。文字列を range でイテレートすると、各要素は rune 型として取得されます。

Index 系関数と Contains 系関数

  • Index(s, substr string) int: 文字列 s 内で substr が最初に出現するインデックスを返します。見つからない場合は -1 を返します。
  • IndexAny(s, chars string) int: 文字列 s 内で chars に含まれる任意のUnicodeコードポイントが最初に出現するインデックスを返します。見つからない場合は -1 を返します。
  • IndexRune(s string, r rune) int: 文字列 s 内で r が最初に出現するインデックスを返します。見つからない場合は -1 を返します。
  • Contains(s, substr string) bool: 文字列 ssubstr を含む場合に true を返します。これは内部的に Index(s, substr) != -1 と同等です。

このコミットで追加される ContainsAnyContainsRune は、それぞれ IndexAnyIndexRune の結果を真偽値に変換するラッパー関数として機能します。

技術的詳細

追加された ContainsAnyContainsRune 関数は、非常にシンプルに実装されています。それぞれ対応する IndexAny および IndexRune 関数を呼び出し、その結果が -1 (見つからなかったことを示す) でない場合に true を返します。

  • ContainsAny(s, chars string) bool:

    • 引数:
      • s: 検索対象の文字列。
      • chars: 検索するUnicodeコードポイントを含む文字列。この文字列内の任意の文字が s に含まれているかを判定します。
    • 戻り値: s 内に chars のいずれかの文字が含まれていれば true、そうでなければ false
    • 実装: return IndexAny(s, chars) >= 0
  • ContainsRune(s string, r rune) bool:

    • 引数:
      • s: 検索対象の文字列。
      • r: 検索する単一のUnicodeコードポイント(rune型)。
    • 戻り値: s 内に r が含まれていれば true、そうでなければ false
    • 実装: return IndexRune(s, r) >= 0

また、既存の Contains 関数も Index(s, substr) != -1 から Index(s, substr) >= 0 に変更されています。これは機能的には同じですが、-1 が「見つからない」ことを意味するインデックスの慣習的な表現であるため、>= 0 は「見つかった」(つまり、インデックスが0以上)という意図をより明確に示します。同様に、FieldsFuncmakeCutsetFunc 内の条件式も != -1 から >= 0 に変更され、一貫性が保たれています。

テストコードでは、これらの新しい関数が期待通りに動作するかを確認するために、様々なケース(空文字列、単一文字、複数文字、Unicode文字、特殊文字など)を網羅したテストケースが追加されています。

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

src/pkg/strings/strings.go

--- a/src/pkg/strings/strings.go
+++ b/src/pkg/strings/strings.go
@@ -64,7 +64,17 @@ func Count(s, sep string) int {

 // Contains returns true if substr is within s.
 func Contains(s, substr string) bool {
-	return Index(s, substr) != -1
+	return Index(s, substr) >= 0
+}
+
+// ContainsAny returns true if any Unicode code points in chars are within s.
+func ContainsAny(s, chars string) bool {
+	return IndexAny(s, chars) >= 0
+}
+
+// ContainsRune returns true if the Unicode code point r is within s.
+func ContainsRune(s string, r rune) bool {
+	return IndexRune(s, r) >= 0
 }

 // Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
@@ -269,7 +279,7 @@ func FieldsFunc(s string, f func(rune) bool) []string {
 			fieldStart = i
 		}
 	}
-	if fieldStart != -1 { // Last field might end at EOF.
+	if fieldStart >= 0 { // Last field might end at EOF.
 		a[na] = s[fieldStart:]
 	}
 	return a
@@ -512,7 +522,7 @@ func lastIndexFunc(s string, f func(rune) bool, truth bool) int {
 }

 func makeCutsetFunc(cutset string) func(rune) bool {
-	return func(r rune) bool { return IndexRune(cutset, r) != -1 }\n+\treturn func(r rune) bool { return IndexRune(cutset, r) >= 0 }
 }

 // Trim returns a slice of the string s with all leading and

src/pkg/strings/strings_test.go

--- a/src/pkg/strings/strings_test.go
+++ b/src/pkg/strings/strings_test.go
@@ -908,6 +908,56 @@ func TestContains(t *testing.T) {
 	}
 }

+var ContainsAnyTests = []struct {
+	str, substr string
+	expected    bool
+}{
+	{"", "", false},
+	{"", "a", false},
+	{"", "abc", false},
+	{"a", "", false},
+	{"a", "a", true},
+	{"aaa", "a", true},
+	{"abc", "xyz", false},
+	{"abc", "xcz", true},
+	{"a☺b☻c☹d", "uvw☻xyz", true},
+	{"aRegExp*", ".(|)*+?^$[]", true},
+	{dots + dots + dots, " ", false},
+}
+
+func TestContainsAny(t *testing.T) {
+	for _, ct := range ContainsAnyTests {
+		if ContainsAny(ct.str, ct.substr) != ct.expected {
+			t.Errorf("ContainsAny(%s, %s) = %v, want %v",
+				ct.str, ct.substr, !ct.expected, ct.expected)
+		}
+	}
+}
+
+var ContainsRuneTests = []struct {
+	str      string
+	r        rune
+	expected bool
+}{
+	{"", 'a', false},
+	{"a", 'a', true},
+	{"aaa", 'a', true},
+	{"abc", 'y', false},
+	{"abc", 'c', true},
+	{"a☺b☻c☹d", 'x', false},
+	{"a☺b☻c☹d", '☻', true},
+	{"aRegExp*", '*', true},
+}
+
+func TestContainsRune(t *testing.T) {
+	for _, ct := range ContainsRuneTests {
+		if ContainsRune(ct.str, ct.r) != ct.expected {
+			t.Errorf("ContainsRune(%s, %s) = %v, want %v",
+				ct.str, ct.r, !ct.expected, ct.expected)
+		}
+	}
+}
+
 var EqualFoldTests = []struct {
 	s, t string
 	out  bool

コアとなるコードの解説

strings.go の変更点

  1. Contains 関数の修正:

    • return Index(s, substr) != -1 から return Index(s, substr) >= 0 へ変更。
    • これは機能的な変更ではなく、インデックスが「見つかった」ことを示す条件をより明確にするための表現の変更です。Index 関数は、部分文字列が見つからない場合に -1 を返すため、!= -1>= 0 は同じ論理結果をもたらします。
  2. ContainsAny 関数の追加:

    • IndexAny(s, chars) の結果が >= 0 であるかを返します。
    • これにより、chars 内の任意の文字が s に含まれているかを簡潔に判定できます。
  3. ContainsRune 関数の追加:

    • IndexRune(s, r) の結果が >= 0 であるかを返します。
    • これにより、特定の runes に含まれているかを簡潔に判定できます。
  4. FieldsFunc および makeCutsetFunc 内の条件式の修正:

    • これらの関数内の fieldStart != -1IndexRune(cutset, r) != -1 といった条件式も、>= 0 を使用するように変更されています。これは、Contains 関数の変更と同様に、コード全体でのインデックスチェックの慣習を統一するためのものです。

strings_test.go の変更点

  1. ContainsAnyTestsTestContainsAny の追加:

    • ContainsAny 関数の動作を検証するためのテストケースとテスト関数が追加されています。
    • 様々な文字列と文字セットの組み合わせに対して、期待される真偽値が正しく返されるかを確認します。Unicode文字や正規表現の特殊文字を含むケースも含まれています。
  2. ContainsRuneTestsTestContainsRune の追加:

    • ContainsRune 関数の動作を検証するためのテストケースとテスト関数が追加されています。
    • 空文字列、単一文字、複数文字、Unicode文字、特殊文字など、多様な rune と文字列の組み合わせでテストが行われます。

これらの変更により、strings パッケージはより完全で使いやすくなり、開発者は文字列内の文字の存在をより直感的にチェックできるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント (pkg.go.dev/strings)
  • Go言語のブログ記事 (go.dev/blog/strings)
  • GitHub上のGo言語リポジトリのコミット履歴
  • 一般的なGo言語の文字列操作に関する知識