Question
I need to read a [100]byte value that stores string data.
Not all strings are exactly 100 characters long, so the unused part of the byte array is padded with 0 bytes.
If I convert [100]byte to a string like this:
s := string(byteArray[:])
the trailing 0 bytes appear in the result as null characters.
In C, a string typically ends at the first 0 byte. What is the best way to convert this kind of zero-terminated byte array to a string in Go?
Short Answer
By the end of this page, you will understand why Go strings do not automatically stop at a null byte, how zero-terminated byte arrays differ from C strings, and how to safely convert fixed-size byte arrays like [100]byte into clean Go strings.
Concept
In Go, a string is a sequence of bytes. It can contain any byte value, including 0 (the null byte). That means Go does not treat 0 as a special end-of-string marker.
This is different from C, where strings are commonly stored as null-terminated character arrays. In C, the first \0 marks the end of the string.
So when you do this in Go:
s := string(byteArray[:])
Go converts all 100 bytes into the string, including any trailing 0 bytes.
If your data format uses a fixed-size byte array with zero padding, you need to manually find where the meaningful content ends.
A common approach is:
- Find the first
0byte - Slice up to that position
- Convert that slice to a string
This matters in real programs because many binary formats, network protocols, and C interop APIs store text in fixed-length buffers rather than true Go strings.
Mental Model
Think of the [100]byte array as a 100-slot storage tray.
- The real text is placed in the first few slots
- The remaining unused slots are filled with
0 - Go reads the entire tray unless you tell it where to stop
C behaves more like: "stop reading when you hit the first empty marker."
Go behaves more like: "read exactly what you gave me."
So in Go, you must decide where the useful data ends before converting it to a string.
Syntax and Examples
The core idea is to cut the byte slice at the first null byte.
Option 1: Use bytes.IndexByte
package main
import (
"bytes"
"fmt"
)
func main() {
data := [100]byte{'H', 'e', 'l', 'l', 'o', 0, 0, 0}
n := bytes.IndexByte(data[:], 0)
if n == -1 {
n = len(data)
}
s := string(data[:n])
fmt.Println(s)
}
This finds the first 0 byte and converts only the bytes before it.
Option 2: Use bytes.TrimRight
If your array is padded with trailing zeros and you want to remove only zeros at the end:
package main
import (
"bytes"
"fmt"
)
func main {
data := []{, , , , , , , }
s := (bytes.TrimRight(data[:], ))
fmt.Println(s)
}
Step by Step Execution
Consider this example:
package main
import (
"bytes"
"fmt"
)
func main() {
data := [10]byte{'G', 'o', 0, 0, 0, 0, 0, 0, 0, 0}
n := bytes.IndexByte(data[:], 0)
if n == -1 {
n = len(data)
}
s := string(data[:n])
fmt.Println(s)
}
Step by step
datais a fixed-size array of 10 bytes.- The first two bytes are
'G'and'o'. - The third byte is
0, which marks the end of meaningful text. data[:]converts the array into a slice so functions likebytes.IndexBytecan inspect it.bytes.IndexByte(data[:], 0)returns because the first null byte is at index .
Real World Use Cases
This pattern appears often when Go works with older or lower-level systems.
Common situations
- Binary file formats: fixed-size name fields padded with zeros
- Network protocols: packet headers containing fixed-width text fields
- C library interop: reading
char[100]values from C structs - Database drivers or legacy systems: fixed-length text records
- Embedded systems: device messages stored in byte buffers
Example scenarios
- Reading a username from a binary record
- Extracting a device label from firmware data
- Parsing a file header that stores a 32-byte application name
- Converting a C struct field into a normal Go string
Real Codebase Usage
In real projects, developers usually wrap this logic in a helper function so they do not repeat it everywhere.
Helper function pattern
func cString(b []byte) string {
n := bytes.IndexByte(b, 0)
if n == -1 {
n = len(b)
}
return string(b[:n])
}
This is common when parsing many fields from structs or binary data.
Guard clause pattern
Developers often handle the -1 case early:
func cString(b []byte) string {
n := bytes.IndexByte(b, 0)
if n < 0 {
return string(b)
}
return string(b[:n])
}
Validation pattern
If the data must be valid UTF-8, some codebases validate after conversion:
import "unicode/utf8"
{
n := bytes.IndexByte(b, )
n == {
n = (b)
}
s := (b[:n])
!utf8.ValidString(s) {
}
s
}
Common Mistakes
1. Converting the full array directly
Broken example:
s := string(data[:])
This includes all bytes, including 0 padding.
Fix: stop at the first null byte.
n := bytes.IndexByte(data[:], 0)
if n == -1 {
n = len(data)
}
s := string(data[:n])
2. Forgetting to handle -1
Broken example:
n := bytes.IndexByte(data[:], 0)
s := string(data[:n])
If no 0 exists, n is -1, and the slice will panic.
Fix: always check for -1.
3. Using TrimRight when the string may contain internal null bytes
s := string(bytes.TrimRight(data[:], ))
Comparisons
| Approach | What it does | Best for | Limitation |
|---|---|---|---|
string(data[:]) | Converts all bytes to a string | Raw byte-to-string conversion | Keeps null bytes |
bytes.IndexByte(data[:], 0) | Finds the first null byte | C-style null-terminated strings | Needs -1 handling |
bytes.TrimRight(data[:], "\x00") | Removes trailing null bytes | Zero-padded fixed-length fields | Does not stop at internal nulls |
| Manual loop | Scans until 0 byte | Full control or learning purposes | More verbose |
IndexByte vs
Cheat Sheet
// Convert a null-terminated byte slice to string
n := bytes.IndexByte(b, 0)
if n == -1 {
n = len(b)
}
s := string(b[:n])
Quick rules
- Go strings can contain
0bytes string(b)converts every byte inb- Go does not automatically stop at
0 - Use
bytes.IndexByte(b, 0)for C-style strings - Use
bytes.TrimRight(b, "\x00")for trailing zero padding only - Convert arrays to slices with
array[:]
Common helper
func cString(b []byte) string {
n := bytes.IndexByte(b, 0)
if n == -1 {
n = len(b)
}
return string(b[:n])
}
Edge cases
FAQ
Why does Go not stop at \x00 like C?
Go strings are length-based, not null-terminated. A Go string can contain any bytes, including 0.
What is the best function for C-style strings in Go?
bytes.IndexByte(b, 0) is a clear and common choice because it finds the first null byte.
Can I use bytes.TrimRight instead?
Yes, if the data is zero-padded at the end. But it is not the same as stopping at the first null byte.
What happens if there is no 0 byte in the array?
Then the whole array is meaningful data, so you should convert the full slice.
Do I need to convert [100]byte to []byte first?
You do not need a copy, but you usually need a slice view: data[:].
Can a Go string contain null bytes safely?
Yes. Go strings can store null bytes without any problem.
Is there a standard library helper exactly for C strings?
For general byte handling, bytes.IndexByte is the usual tool. In some C interop cases, other packages may be relevant, but for plain byte arrays this is the standard approach.
Mini Project
Description
Build a small Go program that reads fixed-size byte arrays representing names from a legacy data source. Each name is stored in a [16]byte buffer and padded with 0 bytes. Your task is to convert each buffer into a clean Go string and print the results.
Goal
Create a helper that converts zero-terminated byte arrays into readable Go strings and use it to process multiple records.
Requirements
- Create a helper function that converts a null-terminated byte slice to a Go string.
- Read at least three fixed-size byte arrays containing zero-padded names.
- Correctly handle both padded and fully filled arrays.
- Print the cleaned names without null characters.
Keep learning
Related questions
Check if a Value Exists in a Slice in Go
Learn how to check whether a value exists in a slice in Go, and why Go has no Python-style `in` operator for arrays or slices.
Concatenating Slices in Go with append
Learn how to concatenate two slices in Go using append and the ... operator, with examples, pitfalls, and practical usage.
Convert String to Integer in Go: Idiomatic Parsing with strconv.Atoi
Learn the idiomatic way to convert a string to an int in Go using strconv.Atoi, with examples, errors, and common mistakes.