
Golang Bytes
What is a byte?
A byte is an unsigned integer that represents a single byte of data it is represented by the uint8
type. By convention a byte is represented by the byte
keyword.
Just like strings byte manipulation can be done using the bytes
package found in the standard library.
How to define a byte in Go.
A byte is defined using the byte
keyword. It must be declared implicity since the compiler can’t infer the type.
...
var b byte
...
When declared without a value, the default value is 0
.
A byte can also be declared with a value.
...
var b byte = 1
...
Bytes array or slice
Just like any other data type in Go, a byte can be declared as an array or a slice.
...
var b []byte
// or
var b [1]byte
...
Bytes and strings
Bytes can be converted to strings and vice versa.
...
a := "Is this a string?"
b := []byte(a)
c := string(b)
fmt.Println(b) // [73 115 32 116 104 105 115 32 97 32 115 116 114 105 110 103 63]
fmt.Println(c) // Is this a string?
...
[]byte() vs []byte{}
[]byte() is a type conversion while []byte{} is a slice literal.
Bytes and runes
A rune is a Go type that represents a Unicode code point while a byte is a Go type that represents a single byte of data. A rune is 4 bytes long while a byte is 1 byte long.
Convert a byte to a rune
...
var b byte = 65
var r rune = rune(b)
fmt.Println(r) // 65
fmt.Printf("%T", r) // int32
var c rune = 65
fmt.Println(c) // 65
fmt.Printf("%T", c) // int32
Convert a rune to a byte
...
var r rune = 65
var b byte = byte(r)
fmt.Println(b) // 65
fmt.Printf("%T", b) // uint8
Byte manipulation with the bytes
package
The bytes
package provides functions for manipulating byte slices and arrays.
...
import "bytes"
...
bytes.Compare
The bytes.Compare
function compares two byte slices and returns an integer that represents the result of the comparison.
...
a := []byte("a")
b := []byte("b")
fmt.Println(bytes.Compare(a, b)) // -1
fmt.Println(bytes.Compare(b, a)) // 1
fmt.Println(bytes.Compare(a, a)) // 0
...
The bytes.Compare
function returns 0
if the two byte slices are equal, -1
if the first byte slice is less than the second byte slice and 1
if the first byte slice is greater than the second byte slice.
bytes.Contains
The bytes.Contains
function is used to check if a byte slice contains a byte slice. It returns a boolean value.
...
a := []byte("a")
b := []byte("b")
fmt.Println(bytes.Contains(a, b)) // false
fmt.Println(bytes.Contains(a, a)) // true
...
bytes.ContainsAny
The bytes.ContainsAny
function is used to check if a byte slice contains any of the bytes in a byte slice. It returns a boolean value.
...
a := []byte{0x61}
b := []byte{0x62}
fmt.Println(bytes.ContainsAny(a, string(b))) // false
fmt.Println(bytes.ContainsAny(a, string(a))) // true
...
The bytes.ContainsAny
function takes a byte slice as the first argument and a string as the second argument. The string is converted to a byte slice before the comparison.
bytes.ContainsRune
The bytes.ContainsRune
function is used to check if a byte slice contains a rune. It returns a boolean value.
...
a := []byte("hello")
fmt.Println(bytes.ContainsRune(a, 98)) // true
fmt.Println(bytes.ContainsRune(a, 'h')) // true
fmt.Println(bytes.ContainsRune(a, 99)) // false
...
Double quotes vs single quotes
In Go, double quotes are used to represent strings while single quotes are used to represent runes
bytes.Count
The bytes.Count
function is used to count the number of non-overlapping instances of a byte slice in another byte slice. It returns an integer value.
...
a := []byte("hello")
fmt.Println(bytes.Count(a, []byte("l"))) // 2
fmt.Println(bytes.Count(a, []byte("ll"))) // 1
fmt.Println(bytes.Count(a, []byte("z"))) // 0
...
bytes.Equal
The bytes.Equal
function is used to check if two byte slices are eqaual. It returns a boolean value.
...
a := []byte("hello")
b := []byte("hello")
c := []byte("world")
fmt.Println(bytes.Equal(a, b)) // true
fmt.Println(bytes.Equal(a, c)) // false
...
bytes.EqualFold
The bytes.EqualFold
function is used to check if two byte slice are equal without case sensitivity. It returns a boolean value.
...
a := []byte("hello")
b := []byte("HELLO")
c := []byte("world")
fmt.Println(bytes.EqualFold(a, b)) // true
fmt.Println(bytes.EqualFold(a, c)) // false
fmt.Println(bytes.EqualFold([]byte("a"), []byte("A"))) // true
...
bytes.Fields
The bytes.Fields
function is used to split a byte slice into a slice of byte slices. It returns a slice of byte slices.
...
a := []byte("hello world")
fmt.Println(bytes.Fields(a)) // [[104 101 108 108 111] [119 111 114 108 100]]
...
bytes.FieldsFunc
The bytes.FieldsFunc
function is used to split a byte slice into a slice of byte slices using a function. It retuns a slice of byte slices.
...
a := []byte("hello world")
fmt.Println(bytes.FieldsFunc(a, func(r rune) bool {
return r == ' '
})) // [[104 101 108 108 111] [119 111 114 108 100]]
...
bytes.HasPrefix
The bytes.HasPrefix
function is used to check if a byte slice has a prefix. It returns a boolean value.
...
a := []byte("hello world")
fmt.Println(bytes.HasPrefix(a, []byte("hello"))) // true
fmt.Println(bytes.HasPrefix(a, []byte("world"))) // false
...
bytes.HasSuffix
The bytes.HasSuffix
function is used to check if a byte slice has a suffix. It returns a boolean value.
...
a := []byte("hello world")
fmt.Println(bytes.HasSuffix(a, []byte("world"))) // true
fmt.Println(bytes.HasSuffix(a, []byte("hello"))) // false
...
bytes.Index
The bytes.Index
function is used to find the index of a byte slice in another byte slice. It returns an integer value.
...
a := []byte("hello world")
fmt.Println(bytes.Index(a, []byte("world"))) // 6
fmt.Println(bytes.Index(a, []byte("hello"))) // 0
fmt.Println(bytes.Index(a, []byte("foo"))) // -1
...
In the case that the byte slice is not found, the function returns -1
.
Some other functions that are similar to bytes.Index
are bytes.IndexAny
, bytes.IndexByte
and bytes.IndexRune
.
bytes.Join
The bytes.Join
function is used to join a slice of byte slice into a single byte slice. It returns a byte slice.
...
a: = [][]byte{
[]byte("hello"),
[]byte("world"),
}
fmt.Println(bytes.Join(a, []byte(" "))) // hello world
...
bytes.LastIndex
The bytes.LastIndex
function is used to find the last index of a byte slice in another byte slice. It returns an integer value.
a := []byte("hello world")
fmt.Println(bytes.LastIndex(a, []byte("world"))) // 6
fmt.Println(bytes.LastIndex(a, []byte("hello"))) // 0
fmt.Println(bytes.LastIndex(a, []byte("foo"))) // -1
...
bytes.Map
The bytes.Map
function is used to apply a function to each byte in a byte slice. It returns a byte slice.
...
a := []byte("hello world")
fmt.Println(bytes.Map(func(r rune) rune {
return r + 1
}, a))
...
bytes.Repeat
The bytes.Repeat
function is used to repeat a byte slice a number of times. It returns a byte slice.
...
a := []byte("hello")
fmt.Println(bytes.Repeat(a, 2)) // [104 101 108 108 111 104 101 108 108 111]
fmt.Println(string(bytes.Repeat(a, 2))) // hellohello
...
bytes.Replace
The bytes.Replace
function is used to replace a byte slice with another byte slice. It returns a byte slice.
...
a := []byte("hello world")
b := bytes.Replace(a, []byte("world"), []byte("foo"), 1)
fmt.Println(b) // [104 101 108 108 111 32 102 111 111]
fmt.Println(string(b)) // hello foo
c := bytes.Replace(a, []byte("l"), []byte("z"), 2)
fmt.Println(c) // [104 101 122 122 111 32 119 111 114 100]
fmt.Println(string(c)) // hezzo world
...
bytes.ReplaceAll
The bytes.ReplaceAll
function is used to replace all occurences of a byte slice with another byte slice. It returns a byte slice.
...
a := []byte("data is data is data")
b := bytes.ReplaceAll(a, []byte("data"), []byte("foo"))
fmt.Println(b) // [102 111 111 32 105 115 32 102 111 111 32 105 115 32 102 111 111]
fmt.Println(string(b)) // foo is foo is foo
...
bytes.Runes
The bytes.Runes
function is used to convert a byte slice into a slice of runes. It returns a slice of runes.
...
a := []byte("hello world")
fmt.Println(bytes.Runes(a)) // [104 101 108 108 111 32 119 111 114 108 100]
...
bytes.Split
The bytes.Split
function is used to split a byte slice into a slice of byte slices. It returns a slice of byte slices.
...
a := []byte("hello world")
fmt.Println(bytes.Split(a, []byte(" "))) // [[104 101 108 108 111] [119 111 114 108 100]]
...
bytes.SplitAfter
The bytes.SplitAfter
function is used to split a byte slice into a slice of byte slices after a byte slice. It returns a slice of byte slices.
...
a := []byte("hello world")
fmt.Println(bytes.SplitAfter(a, []byte(" "))) // [[104 101 108 108 111 32] [119 111 114 108 100]]
...
Some other functions that are similar to bytes.SplitAfter
are bytes.SplitAfterN
and bytes.SplitN
.
bytes.Title
The bytes.Title
function is used to convert the first letter of each word in a byte slice to uppercase. This function was deprecated in Go 1.18.
a := []byte("hello world")
fmt.Println(bytes.Title(a)) // [72 101 108 108 111 32 87 111 114 108 100]
fmt.Println(string(bytes.Title(a))) // Hello World
...
To convert the first letter of a byte slice to uppercase, it is recommended to use the cases
package instead.
...
import (
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
func main () {
a := []byte("hello world")
fmt.Println(cases.Title(language.English).Bytes(a)) // [72 101 108 108 111 32 87 111 114 108 100]
fmt.Println(string(cases.Title(language.English).Bytes(a))) // Hello World
}
Other functions
Check out the bytes package for more functions.
Conclusion
Bytes are an important data type in Go. They are used to represent a single byte of data and can be manipulated using the bytes
package found in the standard library. The bytes
package provides functions for comparing, searching, and manipulating byte slices and arrays. By understanding how to work with bytes in Go, you can write more efficient and effective code.