string trong Go là bất biến, []byte thì không — nên []byte(s) và string(b) thường phải cấp phát bộ nhớ mới và copy toàn bộ dữ liệu.
Trên đường xử lý request nóng, việc này tạo áp lực GC rõ rệt.
b := []byte(s) // cấp phát + copy
s2 := string(b) // cấp phát + copy lần nữaCác trường hợp compiler tối ưu, không cấp phát:
- m[string(b)] — tra map bằng byte slice.
- for i, r := range string(b) — duyệt rune.
- So sánh string(b) == "literal".
Cách giảm chuyển đổi trong service:
- Nối chuỗi trong vòng lặp bằng strings.Builder (hoặc bytes.Buffer) thay vì s += part, vì mỗi phép += tạo chuỗi mới.
- Dùng API nhận []byte xuyên suốt khi dữ liệu vốn là byte (đọc body, encode JSON) thay vì đổi qua lại.
- Cấp phát trước dung lượng: b := make([]byte, 0, n), hoặc sb.Grow(n).
Lưu ý về ngữ nghĩa, không chỉ hiệu năng: len(s) trả số byte, không phải số ký tự; s[i] trả một byte. Với chuỗi tiếng Việt hay emoji, phải duyệt bằng range (ra rune) hoặc dùng utf8.RuneCountInString.