Q

Quản trị viên

Là một lập trình viên yêu công nghệ, thích viết blog để chia sẻ kiến thức, kinh nghiệm lập trình và những điều thú vị trong thế giới tech.

2324 bài viết · Website
Lập trình Go 22/09/2026 8 phút

String internals trong Go: header 16 byte, bất biến, và chi phí ẩn của []byte(s)

String là header 16 byte trỏ vào dữ liệu bất biến, không có cap. Đo thật: substring s[7:13] miễn phí (chia sẻ backing, 0 cấp phát) nhưng chuyển string sang []byte phải copy toàn bộ (21 ns, 1 cấp phát) vì string bất biến còn byte sửa được. Vì sao và khi nào tốn kém. Go 1.23.

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

Integration test với testcontainers trong Go: dựng dịch vụ thật trong Docker

Mock chỉ giả lập hành vi bạn nghĩ dịch vụ có; bug thật nằm ở khác biệt với dịch vụ thật. testcontainers-go dựng database/Redis thật trong Docker ngay trong test rồi tự dọn. Đo thật: code testcontainers biên dịch sạch, và một integration test thật chống Redis (không mock) pass — kèm báo cáo trung thực về yêu cầu Docker socket.

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

Hash join đo thật: DuckDB ghép 10 triệu đơn với 100 nghìn khách theo khoá bằng chỉ mất 33 ms vì dựng bảng băm trên bên nhỏ rồi dò bằng bên lớn theo O(N cộng M), còn join theo khoảng rơi về nested loop O(N nhân M), chậm hơn 1142 lần

DuckDB ghép hai bảng lớn nhanh nhờ hash join: dựng bảng băm trên bên nhỏ rồi dò bằng bên lớn, độ phức tạp O(N cộng M) thay vì O(N nhân M) của nested loop. Đo thật: join 10 triệu đơn với 100 nghìn khách theo khoá bằng mất 33 ms, và thời gian tăng gần tuyến tính theo kích thước bảng fact (1 triệu 7,7 ms, 5 triệu 20,2 ms). Hash join chỉ dùng được cho điều kiện bằng; join theo khoảng nhỏ hơn rơi về nested loop và trên 20 nghìn nhân 20 nghìn mất 776 ms, chậm hơn equi-join 1142 lần vì bùng nổ tổ hợp.

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

Mạng không đáng tin: đo thật bằng tc netem giữa hai container — mất gói 30% vẫn 137/200 thành công nhưng p99 lên 420 ms, và 10 đơn hàng được tạo mà client tưởng là lỗi

Mở đầu sê-ri hệ thống phân tán bằng cách làm hỏng mạng có chủ đích: tc netem trên một container Go gọi sang container khác. Trễ 50 ms thành 107 ms mỗi request vì bắt tay TCP; mất gói 5% làm p99 nhảy từ 0,3 lên 209 ms vì TCP truyền lại theo bậc 200/400/800 ms; mất 30% vẫn 137/200 thành công nhưng tối đa 829 ms. Phép đo quan trọng nhất: dưới mất gói 30%, client thấy 125 thành công và 75 lỗi, server đếm 135 đơn đã tạo — 10 request client tưởng lỗi nhưng server đã làm. Tải 1 MB ở mất gói 15% không lỗi lần nào, chỉ chậm gấp 160 lần. Phân vùng 3 giây được phát hiện sau đúng một timeout.

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

Đọc panic trace và runtime.Stack trong Go: mổ xẻ từng dòng để chẩn đoán crash

Panic trace không phải chữ đỏ đáng sợ mà là bản đồ đầy đủ để tìm bug. Bài này mổ xẻ từng phần: số hiệu goroutine, trạng thái [running]/[chan receive]/[sync.Mutex.Lock], ngăn xếp đọc từ đâu, tham số hex, tín hiệu SIGSEGV — và dùng runtime.Stack chụp mọi goroutine. Đo thật trong Go 1.23.