HowtoGo
Standard Library

bytes

The bytes package works directly on []byte, covering most of what strings does for byte slices instead of strings, plus a growable Buffer type for building output without repeated allocations.

A byte is an alias for uint8, so a []byte is a slice of raw 8-bit values. Converting a string to []byte counts bytes, not characters, and a multi-byte UTF-8 rune like é takes two of them.

s := "héllo"
b := []byte(s)
fmt.Println(len(s), len(b), len([]rune(s)))

The conversion copies the data, so writing to b never touches the original string s. Strings stay immutable no matter what happens to a byte slice built from one.

Terminal
$ go run main.go
6 6 5
Héllo
héllo

Try it

Examples

Contains and Index work on []byte the same way their strings counterparts work on string.

b := []byte("gopher")
fmt.Println(bytes.Contains(b, []byte("phe")))
fmt.Println(bytes.Index(b, []byte("her")))
fmt.Println(bytes.Equal(b, []byte("gopher")))
Output
true
3
true

Search and comparison

FunctionDescription
Equal(a, b []byte) bool
Reports whether a and b have the same length and content.
Compare(a, b []byte) int
Returns -1, 0, or 1, ordering a before, equal to, or after b lexically.
Contains(b, subslice []byte) bool
bytes.Contains([]byte("seafood"), []byte("foo")) // true
Reports whether subslice appears anywhere within b.
ContainsAny(b []byte, chars string) bool
Reports whether any UTF-8 code point in chars appears in b.
ContainsRune(b []byte, r rune) bool
Reports whether the rune r appears in b.
Index(b, subslice []byte) int
bytes.Index([]byte("chicken"), []byte("ken")) // 4
Returns the index of the first instance of subslice in b, or -1 if absent.
IndexByte(b []byte, c byte) int
Returns the index of the first instance of byte c in b, or -1 if absent.
IndexRune(b []byte, r rune) int
Returns the index of the first instance of rune r in b, or -1 if absent.
LastIndex(b, subslice []byte) int
Returns the index of the last instance of subslice in b, or -1 if absent.
Count(b, subslice []byte) int
Returns the number of non-overlapping instances of subslice in b.
HasPrefix(b, prefix []byte) bool
Reports whether b starts with prefix.
HasSuffix(b, suffix []byte) bool
Reports whether b ends with suffix.

Transforming and splitting

FunctionDescription
ToUpper(b []byte) []byte
Returns a copy of b with every letter mapped to upper case.
ToLower(b []byte) []byte
Returns a copy of b with every letter mapped to lower case.
TrimSpace(b []byte) []byte
Returns a subslice of b with leading and trailing whitespace removed.
Trim(b []byte, cutset string) []byte
Returns a subslice of b with leading and trailing characters in cutset removed.
TrimLeft(b []byte, cutset string) []byte
Like Trim, but only removes from the left side.
TrimRight(b []byte, cutset string) []byte
Like Trim, but only removes from the right side.
TrimPrefix(b, prefix []byte) []byte
Removes prefix from b if present, otherwise returns b unchanged.
TrimSuffix(b, suffix []byte) []byte
Removes suffix from b if present, otherwise returns b unchanged.
Replace(s, old, new []byte, n int) []byte
bytes.Replace([]byte("oink oink"), []byte("oink"), []byte("moo"), 1) // "moo oink"
Replaces the first n instances of old with new; n = -1 replaces all.
ReplaceAll(s, old, new []byte) []byte
Like Replace with n = -1: every instance of old is replaced.
Split(s, sep []byte) [][]byte
Splits s into subslices around every instance of sep.
SplitN(s, sep []byte, n int) [][]byte
Like Split, but stops after n subslices; n = -1 behaves like Split.
Fields(s []byte) [][]byte
Splits s around runs of whitespace, discarding empty results.
Join(s [][]byte, sep []byte) []byte
bytes.Join([][]byte{[]byte("go"), []byte("dev")}, []byte(".")) // "go.dev"
Concatenates the elements of s, placing sep between each one.
Repeat(b []byte, count int) []byte
Returns a new slice of b repeated count times.
Map(mapping func(rune) rune, s []byte) []byte
Returns a copy of s with each rune passed through mapping; a mapping that returns a negative value drops the rune.

bytes.Buffer

bytes.Buffer is a growable buffer for building output piece by piece instead of repeatedly concatenating strings. Its zero value is ready to write to, with no constructor required.

var buf bytes.Buffer
buf.WriteString("go")
buf.WriteByte(' ')
buf.WriteString("gopher")
fmt.Println(buf.String())

Buffer implements both io.Writer and io.Reader, so it drops into any function that expects one, including fmt.Fprintf.

var buf bytes.Buffer
fmt.Fprintf(&buf, "%s scored %d", "Ada", 97)
fmt.Println(buf.String())
FunctionDescription
NewBufferString(s string) *Buffer
Creates a Buffer pre-loaded with s, ready to be read.
(*Buffer) Write(p []byte) (n int, err error)
Appends p to the buffer, growing it as needed; err is always nil.
(*Buffer) WriteString(s string) (n int, err error)
Like Write, but takes a string directly, skipping a []byte conversion.
(*Buffer) WriteByte(c byte) error
Appends a single byte to the buffer.
(*Buffer) WriteRune(r rune) (n int, err error)
Appends the UTF-8 encoding of r to the buffer.
(*Buffer) String() string
Returns the unread portion of the buffer as a string, without consuming it.
(*Buffer) Bytes() []byte
Returns a slice of the unread portion of the buffer; valid only until the next write.
(*Buffer) Len() int
Returns the number of unread bytes in the buffer.
(*Buffer) Reset()
Empties the buffer while keeping its underlying storage for reuse.
(*Buffer) Read(p []byte) (n int, err error)
Reads up to len(p) bytes into p and consumes them; returns io.EOF once drained.

Putting it together

A short pipeline: trim the whitespace around each comma-separated field, then rebuild the line with a Buffer instead of repeated string concatenation.

Terminal
$ go run main.go
go|rust|python
14