本記事では、Golangのデータ型の1つであるバイトとその配列(バイト配列)、bytesパッケージについて詳しく解説していきます。
Golangにおけるバイト変数とは
Golangのバイトは、符号なし8ビットの整数値です。そのため、数値の範囲は0〜255です。
また、Golangではバイトは文字列の中の文字も表すことができます。
バイト変数の作成方法
バイトを宣言する構文は実にシンプルで、以下のようにバイト型、もしくはバイト配列型として宣言するだけです。
var a byte // 単一のバイト
var abc []byte // バイト配列
バイト変数のゼロ値
バイト変数のゼロ値は、単純にゼロ「0」となります。
package main
import (
"fmt"
)
func main() {
var sampleByte byte
fmt.Println(sampleByte)
}
// 出力結果
// 0
文字列でバイトを使用する
Golangでは、バイトを文字列に変換したり、文字列からバイトを変換したりすることができます。
以下は、文字列と一緒にバイトを使用するコード例です。
package main
import (
"fmt"
)
func main() {
var sampleString string = "Hello World"
byteString := []byte(sampleString)
fmt.Println(byteString)
fmt.Println(string(byteString))
}
// 出力結果
// [72 101 108 108 111 32 87 111 114 108 100]
// Hello World
Golangのbytesパッケージの使い方を解説!
Golangのbytesパッケージは、バイト配列を操作するために、多くの便利な関数を用意しています。
また、Bufferという重要な構造体も存在します。(後述で解説してます)
ここでは、バイトスライスで使用できる便利な関数をいくつか紹介します。
Compare関数(バイトスライスの比較)
Compare()関数は以下のルールに基づいて、バイトスライスを辞書順に比較し、比較結果を数値として返します。
bytes.Compare(バイトスライス1, バイトスライス2)
// バイトスライス1 > バイトスライス2 => 戻り値は1
// バイトスライス1 < バイトスライス2 => 戻り値は-1
// バイトスライス1 == バイトスライス2 => 戻り値は0
以下は、bytesパッケージのCompare()関数を使用したコード例です。
package main
import (
"bytes"
"fmt"
)
func main() {
slice1 := []byte("ABCDE")
slice2 := []byte("EABCD")
fmt.Println(bytes.Compare(slice1, slice2)) // -1
}
Contains関数(バイトスライスが他のバイトスライスを含むか確認)
あるバイトスライスが他のバイトスライスに含まれるかどうかを調べるにはContains()関数を使用します。
以下はContains()関数を使用したコード例です。
package main
import (
"bytes"
"fmt"
)
func main() {
slice1 := []byte("ABC")
slice2 := []byte("A")
slice3 := []byte("D")
fmt.Println(bytes.Contains(slice1, slice2)) // true
fmt.Println(bytes.Contains(slice1, slice3)) // false
}
ContainsRune関数(バイトスライスがルーンを含むかを確認する)
ContainsRune()関数は、バイトスライスがルーンを含むかどうかをチェックするために使用されます。
package main
import (
"bytes"
"fmt"
)
func main() {
slice1 := []byte("ABC")
fmt.Println(bytes.ContainsRune(slice1, 'A')) // true
fmt.Println(bytes.ContainsRune(slice1, 'D')) // false
}
Equal関数(バイトスライスが等しいかをチェックする)
Equal()関数は、2つのバイトスライスを受け取り、それらが等しい場合にtrue、異なっていればfalseを返します。
package main
import (
"bytes"
"fmt"
)
func main() {
slice1 := []byte("ABC")
slice2 := []byte("XYZ")
slice3 := []byte("ABC")
fmt.Println(bytes.Equal(slice1, slice3)) // true
fmt.Println(bytes.Equal(slice1, slice2)) // false
}
またbytesパッケージのEqualFold関数は、2つのバイトスライスが大文字・小文字が異なっていても、同じ文字が使用されていたらtrueを返します。
package main
import (
"bytes"
"fmt"
)
func main() {
slice1 := []byte("ABC")
slice2 := []byte("abc")
fmt.Println(bytes.EqualFold(slice1, slice2)) // true
}
Fields関数(バイトスライスを空白文字で区切る)
bytesパッケージのFields関数を使用すると、バイトスライスに含まれる空白文字で区切ることができます。
package main
import (
"bytes"
"fmt"
)
func main() {
fmt.Println(bytes.Fields([]byte("aa bb cc"))) // [[97 97 97] [98 98 98] [99 99 99]]
fmt.Printf("%q\n", bytes.Fields([]byte("aa bb cc"))) // ["aaa" "bbb" "ccc"]
}
Index関数(バイトスライス内のインデックス番号を取得)
Index関数は、バイトスライス内にある特定文字列の始まりのインデックス番号を取得します。
また、インデックス番号が見つからない場合は、-1を返します。
package main
import (
"bytes"
"fmt"
)
func main() {
fmt.Println(bytes.Index([]byte("ABCDEFG"), []byte("EF"))) // 4
fmt.Println(bytes.Index([]byte("ABCDEFG"), []byte("GH"))) // -1
}
Join関数(バイトスライスの結合)
bytesパッケージのJoin関数は、バイトスライスが格納された配列を受け取り、第2引数として受け取った文字列で結合します。
package main
import (
"bytes"
"fmt"
)
func main() {
sample := [][]byte{[]byte("ABCD"), []byte("EFGHI")}
fmt.Printf("%s\n", bytes.Join(sample, []byte(":"))) // ABCD:EFGHI
}
Repeat関数(バイトスライスを繰り返す)
Repeat関数は、第1引数で受け取ったバイトスライスを、第2引数で受け取った数値分繰り返します。
package main
import (
"bytes"
"fmt"
)
func main() {
slice1 := []byte("XYZ")
fmt.Println(string(bytes.Repeat(slice1, 5))) // XYZXYZXYZXYZXYZ
}
Split関数(バイト文字列を分割)
bytesパッケージのSplit関数を使用すると、セパレータを使用して、文字列を文字列の配列に分割することができます。
package main
import (
"bytes"
"fmt"
)
func main() {
slice1 := []byte("xyxyxy")
fmt.Printf("%q\n", bytes.Split(slice1, []byte("x"))) // ["" "y" "y" "y"]
}
Trim関数(バイトスライスのトリミング)
Trim関数を使うだけで、バイトスライスの一部を切り取ることができるのです。
package main
import (
"bytes"
"fmt"
)
func main() {
slice1 := []byte("abc def ")
fmt.Printf("%q\n", bytes.Trim(slice1, " ")) // "abc def"
}
bytes.Buffer型について
Bufferとは、bytes パッケージに付属している効率的で便利な構造体です。
以下は、空のBufferを宣言する構文です。
var 変数名 bytes.Buffer
Bufferに書き込むには、次のような書き込み関数を使用します。
bytes.Buffer型の値.Write([]byte(文字列"))
Bufferに書き込むサンプルコードは以下の通りです。
package main
import (
"bytes"
"fmt"
)
func main() {
var sampleBuffer bytes.Buffer
sampleBuffer.Write([]byte("Hello, World"))
fmt.Println(sampleBuffer.String()) // Hello, World
}
また、Fprintf関数を使用してバッファに書き込むことも可能です。
package main
import (
"bytes"
"fmt"
)
func main() {
var sampleBuffer bytes.Buffer
fmt.Fprintf(&sampleBuffer, "Hello, World") // Bufferに書き込み
fmt.Println(sampleBuffer.String())
}
Buffer型で使用できる関数はいくつかあり、様々な場面で役に立ちます。
以下では、そのいくつかの例を紹介します。
// バッファのlengthを取得する
fmt.Println(sampleBuffer.Len()) // => 12
// バッファの容量を取得する
fmt.Println(sampleBuffer.Cap()) // => 64
// バッファの未読部分を、バッファの長さのバイトスライスとして取得する
fmt.Println(sampleBuffer.Bytes()) // => [72 101 108 108 111 44 32 87 111 114 108 100]
Buffer型には、文字列やルーンなど、データの種類に応じた複数の書き込み関数が用意されています。
sampleBuffer.Write([]byte("Hello, World")) // バイトスライスに変換する
sampleBuffer.WriteString("Hello, Japan") // 文字列を書き込む
sampleBuffer.WriteByte(101) // 数値(0〜255)を書き込む
sampleBuffer.WriteRune('%') // Rune文字列を書き込む