Przejdź do głównej treści
eLearner.app
Moduł 4 · Lekcja 4 z 519/50 w kursie~12 min
Lekcje modułu (4/5)

Ciągi znaków, bajty i runy

W Go string jest niezmienną sekwencją bajtów. Literały łańcuchowe są zakodowane w UTF-8. rune jest aliasem dla int32 i reprezentuje pojedynczy punkt kodowy Unicode.

Zrozumienie różnicy pomiędzy bajtami i runami jest niezbędne unikaj błędów, gdy ciąg znaków zawiera akcenty, emoji, ideogramy lub dowolne inne znak inny niż ASCII.

string = bajty, nie znaki

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) zwraca liczbę bajtów, niewidocznych znaków. Indeksowanie s[i] zwraca i-ty bajt (uint8), a nie znak.

for range iteruje runy

for i, r := range s dekoduje UTF-8 na bieżąco: i to przesunięcie bajtu początku runy, r jest runą (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): indeksowanie według znaków

Jawna konwersja: przydziela nowy kawałek run. Kosztowne, ale czasami konieczne:

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

string(runes) to konwersja odwrotna: pobiera []rune i generuje ciąg UTF-8.

Ciągi znaków są niezmienne

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

Aby mutować, przekonwertuj na []byte lub []rune, wykonaj operację, przekonwertuj z powrotem:

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

Łączenie

Operator + działa, ale w przypadku wielu konkatenacji w pętli należy go używać strings.Builder (bardziej wydajny, pozwala uniknąć alokacji pośrednich):

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

Przydatne pakiety

  • KOD 0: KOD 1, KOD PH 2, KOD 3, KOD 4, KOD 5, KOD 6...
  • KOD 7: KOD 8, KOD 9, KOD 10, KOD 11...
  • KODEKF12: KODEF13, KODEF14, KODEF15...
  • Contains6: Contains7 (alternatywa dla Contains8).

Spróbuj

Ćwiczenie#go.m4.l4.e1
Próby: 0Ładowanie...

Wykonaj iterację ciągu s z zakresem i wydrukuj indeks oraz runę, używając %d %c.

Ładowanie edytora...
Pokaż wskazówkę

zakres ciągu zwraca przesunięcie bajtu + runę.

Rozwiązanie dostępne po 3 próbach

Ćwiczenie#go.m4.l4.e2
Próby: 0Ładowanie...

Konwertuj s na []rune i wydrukuj jego długość w znakach.

Ładowanie edytora...
Pokaż wskazówkę

Jawna konwersja: `[]rune(s)`.

Rozwiązanie dostępne po 3 próbach

Quiz#go.m4.l4.e3
Gotowe

Co to jest len("ciaò")?

Go
s := "ciaò"
fmt.Println(len(s))
Opcje odpowiedzi

Podsumowanie

  • string = niezmienna sekwencja bajtów, zakodowana w formacie UTF-8.
  • len(s) = bajty; s[i] = i-ty bajt (uint8).
  • for i, r := range s dekoduje runy; i to przesunięcie bajtu.
  • []rune(s) do indeksowania według znaku (kosztowne, przydziela).
  • Aby mutować: przejdź przez []byte lub []rune.
  • Aby połączyć w pętli: strings.Builder.
  • Kluczowe pakiety: strings, len(s)0, len(s)1, len(s)2.