Fundamentals 5 min read

Understanding Go Byte Order and Pointer Arithmetic in One Guide

This article demonstrates how to determine Go's endianness using unsafe.Pointer and uintptr, explains the memory layout of multi‑byte variables, and details the roles of *T, unsafe.Pointer, and uintptr for pointer arithmetic with concrete code examples.

Nullbody Notes
Nullbody Notes
Nullbody Notes
Understanding Go Byte Order and Pointer Arithmetic in One Guide

Go stores multi-byte values in either big‑endian or little‑endian order; the article shows how to detect the endianness at runtime using the unsafe package.

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    var i int32 = 0x01020304
    size := unsafe.Sizeof(i)
    for j := 0; j < int(size); j++ {
        fmt.Println(*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&i)) + uintptr(j))))
    }

    if *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&i)))) == 0x04 {
        fmt.Println("小端存储")
    } else {
        fmt.Println("大端存储")
    }
}

The program prints the four bytes 4 3 2 1 and then “小端存储”, indicating little‑endian storage on the current machine.

Memory is laid out from the lowest address (0x00) to the highest (0xFF); the starting address of a variable is always the low‑address byte, and higher‑address bytes are reached by simple addition.

In the example, the high‑order byte is 0x01 and the low‑order byte is 0x04; storing 0x04 first corresponds to little‑endian, while storing 0x01 first corresponds to big‑endian.

Golang pointers

*T: ordinary pointer type that can hold an object address but cannot be used for pointer arithmetic.

unsafe.Pointer: generic pointer used for converting between different pointer types; it must be cast to a concrete pointer type before dereferencing.

uintptr: integer type used for pointer arithmetic; the garbage collector does not treat it as a pointer, so values of this type do not keep the referenced object alive.

unsafe.Pointer acts as a bridge that allows conversion between any pointer types, and together with uintptr it enables pointer arithmetic.

Code analysis of the expression used in the loop:

*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&i)) + uintptr(j)))

unsafe.Pointer(&i) converts the *int32 pointer to an unsafe.Pointer, similar to C's void*.

uintptr(unsafe.Pointer(&i)) turns the pointer into an integer value because Go does not allow arithmetic directly on pointers.

Adding uintptr(j) to that integer yields the address of the j‑th byte.

unsafe.Pointer(uintptr(unsafe.Pointer(&i)) + uintptr(j)) converts the resulting integer back to a pointer.

*(*byte)(…) casts the pointer to *byte and dereferences it to obtain the byte value.

The for loop iterates over each byte, moving the pointer one byte at a time and printing the corresponding value.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Gounsafeendiannessbyte orderpointer arithmeticuintptr
Nullbody Notes
Written by

Nullbody Notes

Go backend development, learning open-source project source code together, focusing on simplicity and practicality.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.