Question
var arr [20]byte
str := "abc"
for k, v := range []byte(str) {
arr[k] = byte(v)
}
How can I assign a string to a fixed-size byte array in Go? Is there a simpler or more idiomatic way than looping over the bytes manually?
Short Answer
By the end of this page, you will understand how strings and byte arrays relate in Go, how to copy string data into a fixed-size [N]byte array, when a loop is fine, and when the built-in copy function is the better choice.
Concept
In Go, a string and a fixed-size byte array like [20]byte are different types with different purposes.
- A
stringis an immutable sequence of bytes. - A
[20]byteis a fixed-size array that stores exactly 20 bytes.
Because they are different types, you cannot directly assign a string to a byte array.
var arr [20]byte
str := "abc"
// Not allowed
// arr = str
Instead, you need to copy the string's bytes into the array.
A common and idiomatic way is to use Go's built-in copy function:
var arr [20]byte
str := "abc"
copy(arr[:], str)
This works because:
arr[:]creates a slice view over the whole array.copycan copy from a string into a byte slice.
This concept matters because fixed-size byte arrays are often used in:
- binary protocols
- file headers
- network packets
- C interop
- low-level storage formats
In these cases, you often need to place text into a fixed-size field safely and efficiently.
Mental Model
Think of a string as a label containing text, and a [20]byte array as a row of 20 storage boxes.
- The string
"abc"contains 3 bytes. - The array has 20 slots.
- Copying means putting
a,b, andcinto the first 3 boxes. - The remaining 17 boxes stay as zero values.
So this:
copy(arr[:], str)
is like saying: take the bytes from the string and place them into the available boxes until you run out of text or space.
Syntax and Examples
Basic syntax
var arr [20]byte
str := "abc"
copy(arr[:], str)
What this does
arr[:]turns the array into a slice.copycopies bytes fromstrinto that slice.- Since
stris shorter than 20 bytes, only the first 3 positions are filled. - The rest remain
0.
Example: print the array
package main
import "fmt"
func main() {
var arr [20]byte
str := "abc"
copy(arr[:], str)
fmt.Println(arr)
}
Output:
[97 98 99 0 0 ]
Step by Step Execution
Consider this code:
package main
import "fmt"
func main() {
var arr [5]byte
str := "hey"
n := copy(arr[:], str)
fmt.Println("copied:", n)
fmt.Println("array:", arr)
fmt.Println("first 3 bytes as string:", string(arr[:3]))
}
Step-by-step
-
var arr [5]byte- Creates a fixed-size array with 5 bytes.
- Initial value is:
[0 0 0 0 0]
-
str := "hey"- Creates a string containing 3 bytes:
h,e,y.
- Creates a string containing 3 bytes:
Real World Use Cases
Fixed-width file formats
Some binary or legacy file formats store text in fields of a fixed size, such as 16 or 32 bytes.
var name [16]byte
copy(name[:], "alice")
Network protocol headers
Protocols may define fixed-size byte fields for IDs, names, or command codes.
var header [8]byte
copy(header[:], "PING")
Interfacing with C libraries
When working with C-style structs or memory layouts, you may need fixed byte arrays instead of Go strings.
Embedded or low-level programming
Hardware protocols and packed structures often use fixed-length byte storage.
Database or serialization formats
Some systems represent short text fields as fixed-length byte blocks for predictable layout.
Real Codebase Usage
In real Go codebases, developers commonly use copy for this task because it is simple and safe.
Common pattern: copy into fixed buffer
var buf [32]byte
copy(buf[:], value)
Common pattern: validate length first
If truncation is not acceptable, check first:
if len(str) > len(arr) {
return fmt.Errorf("string too long")
}
copy(arr[:], str)
This is a good example of a guard clause.
Common pattern: zero-padded fields
A fixed array is automatically zero-filled, so copying a shorter string leaves trailing zero bytes.
var field [10]byte
copy(field[:], "id")
This is useful when formats expect null-padded or zero-padded fields.
Common pattern: helper function
In larger projects, developers often wrap this logic in a helper:
{
(dst, s)
}
Common Mistakes
Mistake 1: trying direct assignment
var arr [20]byte
str := "abc"
// arr = str // invalid
Why it fails
A string is not the same type as a byte array.
Fix
copy(arr[:], str)
Mistake 2: forgetting that arrays and slices are different
copy needs a slice as the destination, not the array value directly.
var arr [20]byte
str := "abc"
// copy(arr, str) // invalid
Fix
copy(arr[:], str)
Mistake 3: ignoring truncation
var arr [3]byte
copy(arr[:], "hello")
fmt.Println(string(arr[:]))
Output:
Comparisons
| Approach | Example | Best for | Notes |
|---|---|---|---|
| Manual loop | for i, b := range []byte(str) { arr[i] = b } | Learning or custom logic | More verbose |
copy | copy(arr[:], str) | Simple byte copying | Idiomatic and concise |
| Conversion to slice first | copy(arr[:], []byte(str)) | When you already need a byte slice | Usually unnecessary for plain copying |
copy(arr[:], str) vs looping
copyis shorter.copyclearly expresses intent.- A loop is better only if you need custom behavior, such as:
Cheat Sheet
// Copy string into fixed byte array
var arr [20]byte
copy(arr[:], "abc")
// Get number of bytes copied
n := copy(arr[:], "abc")
// Prevent truncation
if len(str) > len(arr) {
return
}
copy(arr[:], str)
// Convert back using only meaningful bytes
s := string(arr[:n])
Rules
- You cannot assign a
stringdirectly to a[N]bytearray. - Use
arr[:]to make a slice from the array. - Use
copy(arr[:], str)for idiomatic copying. copytruncates if the source is too long.- Unused array elements remain
0. len(str)returns bytes, not necessarily characters.
Good default pattern
var arr [20]byte
(str) > (arr) {
}
(arr[:], str)
FAQ
Can I assign a Go string directly to a byte array?
No. A string and a fixed-size array like [20]byte are different types.
What is the simplest way to copy a string into [N]byte in Go?
Use:
copy(arr[:], str)
Does copy work directly from a string?
Yes. In Go, copy can copy from a string into a byte slice.
What happens if the string is longer than the array?
Only the bytes that fit are copied. The rest are ignored.
Why use arr[:] instead of arr?
Because copy needs a slice destination, and arr[:] creates a slice over the array.
Is a manual loop wrong?
No. It works fine, but copy is usually cleaner and more idiomatic.
Are strings always one byte per character in Go?
No. Go strings are UTF-8 encoded, so some characters use multiple bytes.
When should I use instead of ?
Mini Project
Description
Build a small Go program that stores short command names in fixed-size byte arrays. This mirrors real situations like binary file formats, packet headers, or fixed-width records where a text field must fit into a specific number of bytes.
Goal
Create a program that copies strings into fixed-size byte arrays, detects overly long input, and prints the stored result safely.
Requirements
- Create a helper function that copies a string into a
[8]bytefield. - Reject strings that are longer than 8 bytes.
- Return how many bytes were copied.
- Print both the raw byte array and the reconstructed string.
- Test the program with one valid string and one too-long string.
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.