Lập trình Go 22/09/2026 11 phút

Encoding nhị phân tùy biến trong Go: nhỏ hơn và nhanh hơn JSON

JSON là văn bản tự mô tả — lặp tên field, số là chuỗi ASCII, phải phân tích cú pháp khi đọc. Với dữ liệu nội bộ nóng, một định dạng nhị phân tùy biến gọn và nhanh hơn nhiều. Đo thật trong Go: 100k bản ghi, binary nhỏ hơn 2.3 lần, mã hóa nhanh 4 lần, giải mã nhanh 9 lần — cùng đánh đổi và rủi ro.

Lập trình 22/09/2026 6 phút

JSON trong Go: tiện đến mức ta quên nó tốn gì — đo thật chi phí reflection

encoding/json của Go tiện kinh khủng: một cặp Marshal/Unmarshal cho mọi struct. Nhưng nó dùng reflection lúc chạy nên có chi phí ẩn. Bài này chạy thật một đơn hàng 5 mặt hàng: đo kích thước JSON (643 byte gọn, 928 byte thụt lề), và benchmark cho thấy Unmarshal chậm ~4 lần Marshal với 27 lần cấp phát bộ nhớ so với 3 — vì giải mã phải dựng lại slice, string, struct con.

Lập trình 22/09/2026 6 phút

encoding/gob: định dạng nhị phân của riêng Go, và cái bẫy khi chỉ gửi một giá trị

gob là serialization gọn của Go — tự mô tả kiểu nên không cần schema ngoài như Protobuf. Nhưng nó có một đặc tính dễ gây bất ngờ: gửi một giá trị lẻ thì gob còn LỚN hơn JSON vì gói kèm mô tả kiểu. Bài này đo thật: 1 giá trị gob 443 byte vs JSON 398, nhưng stream 1000 giá trị thì gob chỉ 215 byte/giá trị (~nửa JSON); và Encoder tái dùng mã hóa chỉ 1 lần cấp phát, nhanh hơn JSON.

Lập trình 22/09/2026 6 phút

Varint và ZigZag: vì sao số -1 tốn 10 byte, và mẹo đưa nó về 1 byte

Varint là kỹ thuật nền tảng khiến Protobuf và CBOR gọn: số nhỏ tốn ít byte. Nhưng nó có một cái bẫy đo được: mọi số ÂM trong varint thuần đều tốn 10 byte, kể cả -1. ZigZag sửa điều đó bằng cách ánh xạ đan xen âm-dương. Bài này đo thật số byte bằng Go: -1 từ 10 byte xuống 1, -1000 từ 10 xuống 2 — và giải thích công thức.

Lập trình 22/09/2026 7 phút

Protobuf wire format: giải mã từng byte để hiểu vì sao nó gọn và field number là hợp đồng

Bài trước đo được protobuf gọn hơn JSON 63% nhưng chưa nói vì sao. Bài này mổ xẻ từng byte: serialize {id:1001, name:abc, big:7} ra 11 byte rồi giải mã thủ công — 08 là tag field 1, e907 là varint 1001, a001 là tag field 20 tốn 2 byte. Đo thật varint co giãn theo giá trị (id 5 tốn 2 byte, id 10 tỷ tốn 6 byte), và vì sao wire chỉ chứa số field nên đổi tên không phá nhưng đổi field number thì phá.