strings packageのFields(s string)[]string関数の実装が興味深い
https://golang.org/src/strings/strings.go?s=7967:7997#L310
var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1}
ascii codeは8bitあれば表現することができる。
つまり長さが256のuint8のフラグを使えば表現できる。
全てのascii文字のうちスペースとして定義される文字について予めフラグを立てている処理である。
322を読む前に以下の実装だとどういう出力が得られるだろうか
var str = "ほげ"
fmt.Println(len(str))
答えは6である
go言語においてstring型のlenを取った時の長さの見え方は[]byte型にcastした時のものが見える
つまり次のように考えるとわかりやすい
var str = "ほげ"
fmt.Println(len([]byte(str)))
UTF-8において平仮名一文字は今のところ3オクテットで表現されるので2文字あると6オクテットになりlenを取った時6が帰ってくる
つまり322~328行目のforループはとある文字列を[]byteとみなしてsliceの0番目から順番に処理していくことになる
ちなみに次のようにも書けそうであるが意味が変わるので注意
for i, r := range s {
setBits |= r
isSpace := int(asciiSpace[r])
n += wasSpace & ^isSpace
wasSpace = isSpace
}
rangeを使った場合rはruneになる
ascii文字列は8bitとして表現した時必ず0x7f未満に収まる
2進数に直すと0b01111111になるわけだが、もし文字列が全てascii codeで構成された場合全ての文字をor演算した場合必ず最上位bitは0であるということになる
それに対してutf-8の文字列においては必ずorを取った時に最上位bitが経つのでutf-8文字列かascii文字のみの文字列を判定できる
結果的に322~328行目が何をやっているかと言うとfieldの要素数とutf-8かasciiかの判定のための情報を作っている
https://play.golang.org/p/egc-EI4Vvr