author
Kevin Kelche

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.

main.go
...
var b byte
...

Copied!

When declared without a value, the default value is 0.

A byte can also be declared with a value.

main.go
...
var b byte = 1
...

Copied!

Bytes array or slice

Just like any other data type in Go, a byte can be declared as an array or a slice.

main.go
...
var b []byte
// or
var b [1]byte
...

Copied!

Bytes and strings

Bytes can be converted to strings and vice versa.

main.go
...
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?
...

Copied!

[]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

main.go
...
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

Copied!

Convert a rune to a byte

main.go
...
var r rune = 65
var b byte = byte(r)

fmt.Println(b) // 65
fmt.Printf("%T", b) // uint8

Copied!

Byte manipulation with the bytes package

The bytes package provides functions for manipulating byte slices and arrays.

main.go
...
import "bytes"
...

Copied!

bytes.Compare

The bytes.Compare function compares two byte slices and returns an integer that represents the result of the comparison.

main.go
...
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
...

Copied!

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.

main.go
...
a := []byte("a")
b := []byte("b")

fmt.Println(bytes.Contains(a, b)) // false
fmt.Println(bytes.Contains(a, a)) // true
...

Copied!

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.

main.go
...
a := []byte{0x61}
b := []byte{0x62}

fmt.Println(bytes.ContainsAny(a, string(b))) // false
fmt.Println(bytes.ContainsAny(a, string(a))) // true
...

Copied!

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.

main.go
...
a := []byte("hello")

fmt.Println(bytes.ContainsRune(a, 98)) // true
fmt.Println(bytes.ContainsRune(a, 'h')) // true
fmt.Println(bytes.ContainsRune(a, 99)) // false
...

Copied!

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.

main.go
...
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
...

Copied!

bytes.Equal

The bytes.Equal function is used to check if two byte slices are eqaual. It returns a boolean value.

main.go
...
a := []byte("hello")
b := []byte("hello")
c := []byte("world")

fmt.Println(bytes.Equal(a, b)) // true
fmt.Println(bytes.Equal(a, c)) // false
...

Copied!

bytes.EqualFold

The bytes.EqualFold function is used to check if two byte slice are equal without case sensitivity. It returns a boolean value.

main.go
...
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
...

Copied!

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.

main.go
...
a := []byte("hello world")

fmt.Println(bytes.Fields(a)) // [[104 101 108 108 111] [119 111 114 108 100]]
...

Copied!

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.

main.go
...
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]]
...

Copied!

bytes.HasPrefix

The bytes.HasPrefix function is used to check if a byte slice has a prefix. It returns a boolean value.

main.go
...
a := []byte("hello world")

fmt.Println(bytes.HasPrefix(a, []byte("hello"))) // true
fmt.Println(bytes.HasPrefix(a, []byte("world"))) // false
...

Copied!

bytes.HasSuffix

The bytes.HasSuffix function is used to check if a byte slice has a suffix. It returns a boolean value.

main.go
...
a := []byte("hello world")

fmt.Println(bytes.HasSuffix(a, []byte("world"))) // true
fmt.Println(bytes.HasSuffix(a, []byte("hello"))) // false
...

Copied!

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.

main.go
...
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
...

Copied!

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.

main.go
...
a: = [][]byte{
  []byte("hello"),
  []byte("world"),
}

fmt.Println(bytes.Join(a, []byte(" "))) // hello world
...

Copied!

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.

main.go
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
...

Copied!

bytes.Map

The bytes.Map function is used to apply a function to each byte in a byte slice. It returns a byte slice.

main.go
...
a := []byte("hello world")

fmt.Println(bytes.Map(func(r rune) rune {
  return r + 1
}, a))
...

Copied!

bytes.Repeat

The bytes.Repeat function is used to repeat a byte slice a number of times. It returns a byte slice.

main.go
...
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
...

Copied!

bytes.Replace

The bytes.Replace function is used to replace a byte slice with another byte slice. It returns a byte slice.

main.go
...
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
...

Copied!

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.

main.go
...
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
...

Copied!

bytes.Runes

The bytes.Runes function is used to convert a byte slice into a slice of runes. It returns a slice of runes.

main.go
...
a := []byte("hello world")

fmt.Println(bytes.Runes(a)) // [104 101 108 108 111 32 119 111 114 108 100]
...

Copied!

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.

main.go
...
a := []byte("hello world")

fmt.Println(bytes.Split(a, []byte(" "))) // [[104 101 108 108 111] [119 111 114 108 100]]
...

Copied!

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.

main.go
...
a := []byte("hello world")

fmt.Println(bytes.SplitAfter(a, []byte(" "))) // [[104 101 108 108 111 32] [119 111 114 108 100]]
...

Copied!

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.

main.go
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
...

Copied!

To convert the first letter of a byte slice to uppercase, it is recommended to use the cases package instead.

main.go
...
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
}

Copied!

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.

Subscribe to my newsletter

Get the latest posts delivered right to your inbox.