Chuyển đến nội dung chính
Mô-đun 4 · Bài học 4 trong tổng số 519/50 trong khóa học~12 min
Bài học theo mô-đun (4/5)

Chuỗi, byte và rune

Trong Go, string là một chuỗi byte không thể thay đổi. Chuỗi ký tự được mã hóa bằng UTF-8. rune là bí danh của int32 và đại diện cho một **điểm mã ** Unicode duy nhất.

Hiểu sự khác biệt giữa byte và rune là điều cần thiết để tránh lỗi khi một chuỗi chứa dấu trọng âm, biểu tượng cảm xúc, chữ tượng hình hoặc bất kỳ ký tự không phải ASCII.

string = byte, không phải ký tự

Go
s := "ciaò"
fmt.Println(len(s))   // 5 — not 4!
fmt.Println(s[0])     // 99 ('c' as a byte)
fmt.Println(s[3])     // 195 (first byte of 'ò' in UTF-8)

len(s) trả về số byte, không hiển thị ký tự. Lập chỉ mục s[i] trả về byte thứ i (uint8), không phải ký tự.

for range lặp lại ngọc

for i, r := range s giải mã nhanh UTF-8: i là phần bù byte khi bắt đầu chữ rune, r là chữ rune (int32):

Go
s := "ciaò"
for i, r := range s {
    fmt.Printf("%d %c (U+%04X)\n", i, r, r)
}
// 0 c (U+0063)
// 1 i (U+0069)
// 2 a (U+0061)
// 3 ò (U+00F2)   <- starts at byte 3, takes 2 bytes

[]rune(s): lập chỉ mục theo từng ký tự

Chuyển đổi rõ ràng: phân bổ một lát rune mới. Tốn kém nhưng đôi khi cần thiết:

Go
runes := []rune("ciaò")
fmt.Println(len(runes))    // 4
fmt.Println(string(runes[3])) // ò

string(runes) là chuyển đổi nghịch đảo: nhận []rune và tạo ra một chuỗi UTF-8.

Chuỗi là bất biến

Go
s := "ciao"
// s[0] = 'C'   // ERROR: cannot assign to s[0]

Để biến đổi, hãy chuyển đổi thành []byte hoặc []rune, thao tác, chuyển đổi ngược lại:

Go
b := []byte(s)
b[0] = 'C'
s = string(b)   // "Ciao"

Nối

Toán tử + hoạt động nhưng đối với nhiều phép nối trong vòng lặp, hãy sử dụng strings.Builder (hiệu quả hơn, tránh phân bổ trung gian):

Go
var sb strings.Builder
for i := 0; i < 5; i++ {
    sb.WriteString("ab")
}
fmt.Println(sb.String())   // "ababababab"

Gói hữu ích

  • strings: Contains, HasPrefix, Split, Join, ToUpper, Replace...
  • strconv: Atoi, Itoa, ParseFloat, FormatInt...
  • unicode: IsLetter, IsDigit, ToUpper...
  • unicode/utf8: RuneCountInString (thay thế cho len([]rune(s))).

Hãy thử nó

tập thể dục#go.m4.l4.e1
Nỗ lực: 0Đang tải…

Lặp lại chuỗi s với phạm vi và in chỉ mục và rune bằng cách sử dụng %d %c.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

phạm vi trên một chuỗi trả về byte-offset + rune.

Giải pháp khả dụng sau 3 lần thử

tập thể dục#go.m4.l4.e2
Nỗ lực: 0Đang tải…

Chuyển đổi s thành []rune và in độ dài của nó bằng ký tự.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Chuyển đổi rõ ràng: `[]rune(s)`.

Giải pháp khả dụng sau 3 lần thử

Quiz#go.m4.l4.e3
Sẵn sàng

len("ciaò") là gì?

Go
s := "ciaò"
fmt.Println(len(s))
Tùy chọn trả lời

Tóm tắt lại

  • string = chuỗi byte bất biến, được mã hóa UTF-8.
  • len(s) = byte; s[i] = byte thứ i (uint8).
  • for i, r := range s giải mã rune; i là phần bù byte.
  • []rune(s) để lập chỉ mục theo ký tự (tốn kém, phân bổ).
  • Để thay đổi: đi qua []byte hoặc []rune.
  • Để nối trong một vòng lặp: strings.Builder.
  • Các gói key: strings, strconv, unicode, unicode/utf8.