ZetCode

Golang byte type

last modified May 8, 2025

This tutorial provides a comprehensive guide on using the byte built-in type in Go. Bytes are essential for handling binary data and text, making them a fundamental component of various programming tasks. Through practical examples, we will explore how bytes function and how they can be utilized effectively in Go applications.

The byte type in Go is an alias for uint8, meaning it can store integer values ranging from 0 to 255. Since bytes are often used to represent ASCII characters, they play a crucial role in text processing and encoding. Byte operations allow developers to manipulate individual characters efficiently, making them indispensable in systems that require precise data handling.

In Go, the byte type is widely used in I/O operations, network communication, and string manipulation. Whether reading data from a file, processing network packets, or performing low-level operations on strings, understanding how bytes work is essential for optimizing performance and memory usage. Mastering byte manipulation helps developers build efficient, high-speed applications while maintaining control over data processing.

Basic byte declaration and usage

The simplest way to work with bytes is declaring byte variables and performing basic operations. This example shows byte fundamentals.
Note: Byte literals can be written as decimal or hex values.

basic_byte.go
package main

import "fmt"

func main() {

    var b1 byte = 65      // ASCII 'A'
    b2 := byte('B')       // byte from rune
    b3 := byte(0x43)      // hex value 'C'
    
    fmt.Printf("b1: %c, b2: %c, b3: %c\n", b1, b2, b3)
    fmt.Printf("Sum: %d\n", b1+b2+b3) // Sum as numbers
    
    // Byte to string conversion
    byteSlice := []byte{b1, b2, b3}
    fmt.Println("String:", string(byteSlice))
}

The example shows three ways to create byte values. Bytes can be printed as characters or numbers. The byte slice converts cleanly to a string.

Working with Byte Slices

Byte slices are a fundamental part of handling data in Go, especially for I/O operations, string manipulation, and data processing. Unlike strings, which are immutable, byte slices allow direct modification and efficient manipulation. The following example demonstrates essential byte slice operations, including conversion, modification, extraction, and appending.

byte_slice.go
package main

import "fmt"

func main() {
    // Convert a string to a byte slice
    str := "Hello there!"
    bytes := []byte(str)
    fmt.Printf("Bytes: %v\n", bytes)

    // Modify specific bytes within the slice
    bytes[6] = 'G'
    bytes[7] = 'o'
    fmt.Println("Modified:", string(bytes))

    // Extract a portion (subslice) of the byte slice
    subslice := bytes[0:5]
    fmt.Println("Subslice:", string(subslice))

    // Append a new character to the byte slice
    bytes = append(bytes, '!')
    fmt.Println("Appended:", string(bytes))
}

The example begins by converting a string into a byte slice using []byte(str), allowing direct manipulation of its contents. Unlike strings, which are immutable, byte slices provide flexibility in modifying data dynamically. After conversion, the program replaces specific characters, demonstrating how individual bytes can be modified in a slice.

To further illustrate slice manipulation, the code extracts a portion of the byte slice using bytes[0:5]. This operation is useful when working with structured binary data or segmenting text. Lastly, the program appends a new character using append(), showcasing how byte slices can be expanded dynamically without requiring additional memory allocation.

Byte slices are powerful tools for handling binary data, encoding operations, and custom text processing in Go. Their mutability and efficiency make them essential for performance optimization and dynamic content manipulation in applications.

Byte manipulation and bit operations

Bytes are often used for bit-level operations. This example shows common bit manipulation techniques with bytes.

bit_operations.go
package main

import "fmt"

func main() {

    var b byte = 0b10101010 // Binary literal
    
    fmt.Printf("Original: %08b\n", b)
    
    // Set bit 3 (0-based)
    b |= 1 << 3
    fmt.Printf("Set bit 3: %08b\n", b)
    
    // Clear bit 5
    b &^= 1 << 5
    fmt.Printf("Clear bit 5: %08b\n", b)
    
    // Toggle bit 7
    b ^= 1 << 7
    fmt.Printf("Toggle bit 7: %08b\n", b)
    
    // Check bit 2
    if b&(1<<2) != 0 {
        fmt.Println("Bit 2 is set")
    }
}

The example demonstrates setting, clearing, toggling, and checking bits in a byte. Bit operations are essential for low-level programming.

Reading bytes from input

Bytes are commonly used for reading input data. This example shows how to read bytes from standard input.

read_bytes.go
package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {

    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Enter text: ")
    
    // Read up to 10 bytes
    input, _ := reader.ReadBytes('\n')
    
    fmt.Printf("You entered %d bytes: %v\n", len(input), input)
    fmt.Printf("As string: %s", input)
    
    // Alternative: Read single byte
    fmt.Print("\nPress any key: ")
    char, _ := reader.ReadByte()
    fmt.Printf("\nYou pressed: %c (%d)\n", char, char)
}

The ReadBytes method reads until the delimiter. ReadByte reads a single byte. Both are useful for different input scenarios.

Hexadecimal encoding/decoding

Bytes are fundamental for encoding operations. This example demonstrates hexadecimal encoding and decoding of byte data.

hex_encoding.go
package main

import (
    "encoding/hex"
    "fmt"
)

func main() {

    // Original data
    data := []byte("Hello, Go!")
    fmt.Printf("Original: %s\n", data)
    
    // Encode to hex
    encoded := hex.EncodeToString(data)
    fmt.Println("Encoded:", encoded)
    
    // Decode from hex
    decoded, err := hex.DecodeString(encoded)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Decoded: %s\n", decoded)
    
    // Working with hex literals
    hexBytes := []byte{0x48, 0x65, 0x6c, 0x6c, 0x6f}
    fmt.Println("Hex literals:", string(hexBytes))
}

The example shows hex encoding/decoding using the hex package. Hex is commonly used for binary data representation in text formats.

Converting files to byte slices

A common use case for byte slices is reading and writing files, such as images or binary data. The following example demonstrates how to read an image file into a byte slice and write it back to disk. This is useful for processing, transmitting, or storing binary data in Go.

file_to_bytes.go
package main

import (
    "fmt"
    "io/ioutil"
    "os"
)

func main() {
    // Read the entire file into a byte slice
    data, err := ioutil.ReadFile("input.png")
    if err != nil {
        fmt.Println("Error reading file:", err)
        return
    }
    fmt.Printf("Read %d bytes from input.png\n", len(data))

    // Write the byte slice to a new file
    err = ioutil.WriteFile("output.png", data, 0644)
    if err != nil {
        fmt.Println("Error writing file:", err)
        return
    }
    fmt.Println("Wrote data to output.png")
}

This example uses ioutil.ReadFile to read an entire file into a byte slice, and ioutil.WriteFile to write the byte slice back to a new file. This technique is widely used for file manipulation, uploading, and downloading binary data in Go applications.

Source

Go language specification

This tutorial covered the byte type in Go with practical examples of byte manipulation, I/O, and encoding operations.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Golang tutorials.