The difference between bytes and runes in Go
What is a byte?
A byte takes 8 bits of storage. In Go, it is equivalent to the data type uint8. It is used to represent an ASCII character.
package mainimport "fmt"func main() {// Declaration and assignmentvar a1 byte = 97var a2 byte = 'b'// Printing without character formattingfmt.Println(a1)fmt.Println(a2)// Printing with character formattingfmt.Printf("%c\n", a1)fmt.Printf("%c\n", a2)}
Explanation
- Line 1: We declare the package name.
- Line 2: We import the standard package
fmt. - Line 6: We assign
97toa1which is the ASCII equivalent of 'a'. - Line 7: We assign a character
btoa2. - Lines 10–11: We print the two variables
a1anda2without character formatting. The output without character formatting is the ASCII equivalent code of the characters. - Lines 14–15: We print the two variables with character formatting.
What is a rune?
A rune takes 4 bytes or 32 bits for storage. It is an int32 equivalent. Runes are used to represent the Unicode characters, which is a broader set than ASCII characters. These Unicode characters are encoded in the UTF-8 format.
package mainimport ("fmt""reflect")func main() {// Shorthand declaration and assignmenta1 := 97a2 := 'b'a3 := '♬'// Printing the value, unicode equivalent and type of the variablefmt.Printf("Value: %c, Unicode: %U, Type: %s\n", a1, a1, reflect.TypeOf(a1))fmt.Printf("Value: %c, Unicode: %U, Type: %s\n", a2, a2, reflect.TypeOf(a2))fmt.Printf("Value: %c, Unicode: %U, Type: %s\n", a3, a3, reflect.TypeOf(a3))}
Explanation
- Line 1: We declare the package name.
- Lines 2–5: We import the standard packages
fmtandreflect. - Line 9: We assign
97toa1which is the ASCII equivalent of 'a'. - Line 10: We assign character
btoa2. - Line 11: We assign the Unicode character
♬toa3. - Lines 14–16: We print the values, the Unicode equivalent, and the type of the three variables
a1,a2anda3.
Output
The type of a1 is int. This is because we had assigned an integer 97 to it. The type of both a2 and a3 is int32. This is because the default type of character value is a rune.
Comparison of byte and rune
Byte | Rune |
It takes 8 bits to store a value. | It takes 32 bits to store a value. |
Byte is equivalent to uint8. | Rune is equivalent to int32. |
Declaration: var a2 byte = 'b' | Declaration: var a2 rune = 'b' |
It has to be declared explicitly. | It is the default type of a character. |
Is a string a byte or a rune?
A string is a read-only slice of bytes effectively. When we iterate over a string using a for loop, we iterate over a slice of bytes. However, each value is decoded as a rune when we use a for range loop.
package mainimport ("fmt""reflect")func main() {s := "hello"// for loopfor i := 0; i < len(s); i++ {fmt.Printf("Value: %c, Unicode: %U, Type: %s\n", s[i], s[i], reflect.TypeOf(s[i]))}fmt.Println()// for rangefor _, value := range s {fmt.Printf("Value: %c, Unicode: %U, Type: %s\n", value, value, reflect.TypeOf(value))}}
Explanation
- Line 1: We declare the package name.
- Lines 3–6: We import the standard packages
fmtandreflect. - Line 9: We declare a string
sand assign"hello"to it. - Lines 12–13: We iterate over the string
susing aforloop. Since it is printing one character at a time, the type of each element printed is uint8. - Lines 19–20: We iterate over the string
susing afor rangeloop. Here the value is by default of type rune.
The difference in the representation can be seen from the output of the execution of the above code.
Conclusion
A byte and a rune are both used to represent a character in Go. The default type for character value is a rune.