L32 — unsafe & CGo: thoát khỏi Go safety
Hai cánh cửa hậu của Go: unsafe (đo & bẻ memory layout) và cgo (gọi C).
Ba module tương tác bên dưới giúp bạn thấy những thứ thường vô hình:
padding trong struct, cùng địa chỉ memory đọc dưới nhiều kiểu, và overhead khi vượt biên Go↔C.
Module 1 — Struct memory layout (Sizeof / Offsetof / padding)
Chọn một struct ở dropdown để xem byte-by-byte memory layout: màu là field thật, cam (pad) là padding compiler chèn để giữ alignment. So sánh với phiên bản "sắp xếp lại" để thấy bớt được bao nhiêu byte.
Module 2 — Pointer conversion: cùng memory, kiểu khác
Cùng 8 byte trong RAM, ba cách diễn giải. Nhập một int64, xem nó "biến" thành
float64 và [8]byte khi cast qua unsafe.Pointer.
8 byte trong RAM (hex, little-endian):
Cast về *int64
Cast về *float64
Cast về *[8]byte
⚠ Lưu ý: đây là 6 pattern hợp lệ #1. Nếu cast giữa hai kiểu khác size
(vd *int32 → *int64) thì đọc/ghi sẽ vượt bộ nhớ hợp lệ — undefined behavior.
Module 3 — Go ↔ C boundary: cgo call overhead
Animation mô phỏng các bước khi Go gọi C qua C.strlen(...):
pin goroutine vào OS thread, switch register ABI, copy string, gọi C, copy ngược, unpin.
Mỗi bước thêm vài ns; tổng cộng ~100–200 ns mỗi lần — gấp 100× một Go function call thường.
C.strlen(C.CString("hello"))
strlen — duyệt đến byte zero
cs vẫn ở C heap — phải C.free tay (chưa làm = leak!)
💡 Hệ quả thực tế: hot loop gọi C.something() 1 triệu lần/giây →
150 ms CPU/giây = 15% một core, chỉ riêng overhead vượt biên. Đó là lý do Go std lib viết MD5,
SHA, JSON, regex bằng pure Go — không wrap OpenSSL/PCRE qua CGo.