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

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

コミット

  • コミットハッシュ: ed925490710adedc36d1273cf7d01f3b8dd19946
  • Author: Andrew Gerrand adg@golang.org
  • Date: Fri Nov 4 17:55:21 2011 +1100

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

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

元コミット内容

bytes: fix typo and resolve to be less idiotic next time

R=bradfitz
CC=golang-dev
https://golang.org/cl/5340044

変更の背景

このコミットは、Go言語の標準ライブラリであるbytesパッケージ内のContains関数におけるタイプミス(typo)を修正することを目的としています。コミットメッセージにある「resolve to be less idiotic next time」という表現から、このタイプミスが開発者にとって明らかな誤りであり、将来同様のミスを避けるための自戒の念が込められていることが伺えます。

具体的には、Contains関数の引数型が誤って[]string(文字列スライス)と定義されていたため、bytesパッケージの意図する機能(バイトスライス操作)と合致していませんでした。この誤った型定義は、コンパイルエラーを引き起こすか、あるいは意図しない動作を招く可能性がありました。bytesパッケージはバイトスライスを扱うためのものであり、Contains関数もバイトスライスが別のバイトスライスに含まれるかを判定するべきです。したがって、この修正はライブラリの正確性と整合性を保つために不可欠でした。

前提知識の解説

Go言語のbytesパッケージ

bytesパッケージは、Go言語の標準ライブラリの一部であり、バイトスライス([]byte)を操作するためのユーティリティ関数を提供します。文字列(string)が不変のバイトシーケンスであるのに対し、[]byteは可変のバイトシーケンスです。bytesパッケージは、バイトスライスの比較、検索、分割、結合、変換など、様々な低レベルの操作を効率的に行うための機能を提供します。例えば、bytes.Indexbytes.Equalbytes.Joinなどの関数があります。

Go言語のスライス([]byte[]string

Go言語において、スライスは同じ型の要素のシーケンスを表すデータ構造です。配列とは異なり、スライスの長さは動的に変化させることができます。

  • []byte: バイトのシーケンスを表すスライスです。ファイルの内容の読み書き、ネットワーク通信、バイナリデータの処理など、低レベルのデータ操作によく使用されます。Go言語の文字列は内部的にはUTF-8エンコードされたバイトスライスとして表現されますが、string型は不変であり、直接変更することはできません。[]byteは可変であるため、バイトレベルでのデータの変更が可能です。
  • []string: 文字列のシーケンスを表すスライスです。複数の文字列をリストとして扱う場合に使用されます。

bytesパッケージの関数は、その性質上、通常[]byte型の引数を期待します。[]stringは文字列のリストであり、バイトのリストではありません。

Index関数とContains関数の関係

bytesパッケージにはIndex関数が存在します。Index(s, sep []byte) intは、バイトスライスs内でバイトスライスsepが最初に現れるインデックスを返します。見つからない場合は-1を返します。

Contains関数は、このIndex関数を利用して実装されるのが一般的です。つまり、Indexの結果が-1でなければ(つまり、sepが見つかれば)、Containstrueを返す、というロジックになります。

技術的詳細

このコミットの技術的詳細は、bytes.Contains関数のシグネチャ(関数の名前、引数の型、戻り値の型)の修正に集約されます。

修正前のContains関数の定義は以下の通りでした。

func Contains(b, subslice []string) bool {
	return Index(b, subslice) != -1
}

ここで問題となるのは、引数bsubsliceの型が[]stringとなっている点です。bytesパッケージの他の関数、特にIndex関数は[]byte型の引数を期待します。Index関数はfunc Index(s, sep []byte) intというシグネチャを持っています。

したがって、Contains関数内でIndex(b, subslice)を呼び出すと、[]string型の引数を[]byte型の引数として渡そうとすることになり、Goコンパイラは型ミスマッチのエラーを報告します。これは、[]string[]byteがGo言語において全く異なる型であるためです。

このコミットは、この型ミスマッチを修正し、Contains関数がbytesパッケージの他の関数と整合性を持つように、引数の型を[]byteに変更しました。

修正後のContains関数の定義は以下の通りです。

func Contains(b, subslice []byte) bool {
	return Index(b, subslice) != -1
}

この変更により、Contains関数は正しくバイトスライスを引数として受け取り、bytes.Index関数を呼び出すことができるようになります。これにより、bytesパッケージの意図する機能が正常に動作するようになります。

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

--- a/src/pkg/bytes/bytes.go
+++ b/src/pkg/bytes/bytes.go
@@ -89,7 +89,7 @@ func Count(s, sep []byte) int {
 }
 
 // Contains returns whether subslice is within b.
-func Contains(b, subslice []string) bool {
+func Contains(b, subslice []byte) bool {
 	return Index(b, subslice) != -1
 }
 

コアとなるコードの解説

変更はsrc/pkg/bytes/bytes.goファイル内のContains関数のシグネチャに限定されています。

  • - func Contains(b, subslice []string) bool {: 変更前の行です。ここでbsubsliceの型が誤って[]string(文字列スライス)と定義されていました。
  • + func Contains(b, subslice []byte) bool {: 変更後の行です。bsubsliceの型が[]byte(バイトスライス)に修正されています。

この1行の変更が、bytes.Contains関数が正しく機能するための鍵となります。bytesパッケージはバイトスライスを扱うためのものであるため、Contains関数もバイトスライスを引数として受け取るのが自然かつ正しい挙動です。この修正により、Contains関数はbytes.Index関数に適切な型の引数を渡せるようになり、コンパイルエラーが解消され、関数の意図通りの動作が保証されます。

関連リンク

  • Go Code Review (Gerrit) Change-Id: https://golang.org/cl/5340044 (これはGoプロジェクトが内部的に使用しているコードレビューシステムへのリンクです。通常、GitHubのコミットメッセージには、関連するGerritの変更セットへのリンクが含まれています。)

参考にした情報源リンク

  • Go言語の公式ドキュメント(bytesパッケージに関する情報)
  • Go言語のスライスに関する情報
    • Go Slices: usage and internals (これらのリンクは、Go言語のbytesパッケージやスライスの概念を理解するための一般的な情報源として参照しました。)