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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Nullbody Notes
Go backend development, learning open-source project source code together, focusing on simplicity and practicality.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
