To convert a string to a byte slice in Go, use the standard []byte
conversion expression []byte(string)
. To convert a byte slice to a string, use the string([]byte)
conversion.
Convert a string to a byte slice
package main
import "fmt"
func main() {
// string to []byte
data := []byte("Hello on https://gosamples.dev")
fmt.Println(data)
}
Output:
[72 101 108 108 111 32 111 110 32 104 116 116 112 115 58 47 47 103 111 115 97 109 112 108 101 115 46 100 101 118]
Convert a byte slice to a string
package main
import "fmt"
func main() {
// []byte to string
str := string([]byte{72, 101, 108, 108, 111, 32, 111, 110, 32, 104, 116, 116, 112, 115, 58, 47, 47, 103, 111, 115, 97, 109, 112, 108, 101, 115, 46, 100, 101, 118})
fmt.Println(str)
}
Output:
Hello on https://gosamples.dev
The difference between a string and a byte slice
The conversion between a string and a byte slice is so simple because a string is technically a read-only slice of bytes. You can take a fragment of a string just like a fragment of a slice or an array:
s := "GOSAMPLES.dev is the best Golang website in the world!"
fmt.Println(s[:13])
Output:
GOSAMPLES.dev
But you can’t modify a string:
s := "🌈 GOSAMPLES.dev"
s[5] = 32 // compiler error: cannot assign to s[5] (strings are immutable)
fmt.Println(s)
A byte slice can be modified:
s := []byte("🌈 GOSAMPLES.dev")
s[5] = 32
fmt.Println(string(s))
Output
🌈 OSAMPLES.dev
You can also loop over the individual bytes of a string in the same way as with a byte slice, using the for
loop. The examples:
s := "🌈 GOSAMPLES.dev"
for i := 0; i < len(s); i++ {
fmt.Println(i, s[i])
}
and
b := []byte("🌈 GOSAMPLES.dev")
for i := 0; i < len(b); i++ {
fmt.Println(i, b[i])
}
return the same output:
0 240
1 159
2 140
3 136
4 32
5 71
6 79
7 83
8 65
9 77
10 80
11 76
12 69
13 83
14 46
15 100
16 101
17 118
You may wonder why the 13-character text is 18 bytes long. This is because the character 🌈 is encoded with 4 bytes in UTF-8 (all strings in Go are UTF-8). For texts containing characters encoded with more than 1 byte, there is another difference between using strings and byte slices, in the behavior of the for range
loop. When you use the for range
loop on a string, you iterate over runes
(Unicode code points):
s := "🌈 GOSAMPLES.dev"
for i, c := range s {
fmt.Printf("%d: %c\n", i, c)
}
Output:
0: 🌈
4:
5: G
6: O
7: S
8: A
9: M
10: P
11: L
12: E
13: S
14: .
15: d
16: e
17: v
When you use the for range
on a byte slice, you iterate over individual bytes:
b := []byte("🌈 GOSAMPLES.dev")
for i, c := range b {
fmt.Printf("%d: %c\n", i, c)
}
Output:
0: ð
1:
3:
4:
5: G
6: O
7: S
8: A
9: M
10: P
11: L
12: E
13: S
14: .
15: d
16: e
17: v