String w Go to niezmienny ciąg bajtów, zwykle tekst w UTF-8. Operatory działają na samym stringu (+, ==, <, indeksowanie, wycinanie), a cała reszta znajduje się w standardowym pakiecie strings.
Dzielenie stringów
| Funkcja | Dzieli w miejscu | Uwagi |
|---|---|---|
Split(s, sep) | każdego sep | zachowuje puste części; Split("", ",") zwraca [""], jeden pusty string |
SplitN(s, sep, n) | co najwyżej na n części | ostatnia część zawiera resztę |
SplitAfter(s, sep) | każdego sep | zostawia separator przy każdej części |
Fields(s) | ciągów białych znaków | nigdy nie zwraca pustych części |
FieldsFunc(s, f) | znaków, dla których f zwraca true | własne separatory |
Cut(s, sep) | tylko pierwszego sep | zwraca część przed, po i czy znaleziono (Go 1.18) |
Przypadek Split("", ",") łapie wiele osób: puste wejście daje slice o długości 1, a nie 0. Przy dzieleniu danych od użytkownika Fields albo wcześniejsze sprawdzenie s == "" pozwala uniknąć fantomowego pustego elementu.
strings.Cut to najczystszy sposób na podzielenie key=value, user@host i podobnych par. Go 1.24 dodało też wersje z iteratorami, strings.SplitSeq i strings.FieldsSeq, które zwracają części po jednej, bez budowania slice'a.
Wyszukiwanie
| Funkcja | Zwraca |
|---|---|
Contains(s, sub) | true, jeśli sub występuje w s |
ContainsAny(s, chars) | true, jeśli występuje dowolny znak z chars |
HasPrefix(s, p) / HasSuffix(s, p) | true, jeśli s zaczyna się lub kończy na p |
Index(s, sub) | pozycję w bajtach pierwszego dopasowania albo -1 |
LastIndex(s, sub) | pozycję w bajtach ostatniego dopasowania albo -1 |
Count(s, sub) | liczbę nienakładających się dopasowań |
EqualFold(a, b) | równość bez rozróżniania wielkości liter |
Każde wyszukiwanie rozróżnia wielkość liter, z wyjątkiem EqualFold. Aby szukać bez rozróżniania wielkości liter, zamień obie strony na małe litery albo użyj EqualFold do porównania całych stringów.
Przekształcanie
Jedna pułapka: Trim, TrimLeft i TrimRight przyjmują zestaw znaków, a nie prefiks. strings.TrimLeft("abcab", "ab") usuwa każde początkowe a i b i zwraca "cab". Aby usunąć dokładny prefiks lub sufiks, użyj TrimPrefix i TrimSuffix.
Łączenie i strings.Builder
+ łączy stringi, a fmt.Sprintf formatuje wartości w jeden string. Oba za każdym razem alokują nowy string, bo stringi są niezmienne. Przy kilku operacjach to nie problem, ale w pętli jest wolne, bo każde += kopiuje wszystko, co zbudowano do tej pory. Użyj zamiast tego strings.Builder:
Zerowy strings.Builder jest gotowy do użycia. Implementuje io.Writer, więc fmt.Fprintf zapisuje do niego bezpośrednio. Najpierw wywołaj b.Grow(n), jeśli z grubsza wiesz, jak duży będzie wynik. Nie kopiuj Builder po zapisaniu do niego danych; przekazuj wskaźnik.
Wieloliniowe i surowe stringi
Go ma dwa rodzaje literałów stringów:
Stringi w podwójnych cudzysłowach przetwarzają sekwencje ucieczki (\n, \t, \", \\, \u00e9) i muszą mieścić się w jednej linii. Surowe stringi w backtickach biorą wszystko dosłownie, łącznie ze znakami nowej linii, więc tak zapisuje się wieloliniowe stringi, wyrażenia regularne, JSON i ścieżki Windows. Surowy string nie może zawierać backticka, a znaki powrotu karetki są z niego usuwane. Zauważ, że powyższe zapytanie zaczyna się od znaku nowej linii, bo literał zaczyna się zaraz po otwierającym backticku.
Długość, indeksowanie i podciągi
len(s) to liczba bajtów. s[i] to bajt, a s[i:j] to podciąg według pozycji w bajtach:
ï i é zajmują po dwa bajty, więc string ma 12 bajtów i 10 znaków. Wycinanie po bajtach jest bezpieczne, o ile pozycje pochodzą z strings.Index lub podobnych funkcji, które zwracają przesunięcia w bajtach na granicach znaków. Aby wziąć „pierwsze n znaków”, najpierw zamień string na []rune. Strona o runach i bajtach szczegółowo wyjaśnia UTF-8.
Stringi są niezmienne
Nie możesz zmienić bajtu w miejscu: s[0] = 'H' to błąd kompilacji (cannot assign to s[0] (neither addressable nor a map index expression)). Każda funkcja z strings zwraca nowy string. Aby edytować, zamień na []byte lub []rune, zmień slice i zamień z powrotem:
b := []byte("hello")
b[0] = 'H'
s := string(b) // "Hello"
Niezmienność sprawia też, że podciągi są tanie: s[2:5] współdzieli pamięć z s zamiast ją kopiować. Druga strona medalu: mały podciąg ogromnego stringa utrzymuje przy życiu cały ogromny string. Użyj strings.Clone (Go 1.20), gdy zachowujesz krótki fragment dużego wejścia.
Porównywanie stringów
== i != porównują zawartość, a <, > porównują bajt po bajcie, co dla ASCII oznacza kolejność alfabetyczną. strings.Compare istnieje, ale rzadko jest potrzebne; slices.Sort na []string używa <. Do sortowania tekstu w innych językach z uwzględnieniem reguł lokalnych użyj golang.org/x/text/collate.
Konwersja innych typów
Liczby zamieniasz na stringi przez strconv.Itoa, strconv.FormatFloat lub fmt.Sprintf, a stringi na liczby przez strconv.Atoi i strconv.ParseFloat. Nie pisz string(42): daje to znak o punkcie kodowym 42, czyli "*". Pełną tabelę znajdziesz na stronie o konwersji typów.
Najczęściej zadawane pytania
Jak podzielić string w Go?
Użyj strings.Split(s, sep): strings.Split("a,b,c", ",") zwraca ["a" "b" "c"]. Aby dzielić po dowolnym ciągu białych znaków i pomijać puste części, użyj strings.Fields(s). strings.SplitN ogranicza liczbę części, a strings.Cut dzieli raz, wokół pierwszego separatora.
Jak zapisać wieloliniowy string w Go?
Użyj surowego literału stringa w backtickach:
query := `SELECT id, name
FROM users
WHERE active = true`
Wszystko między backtickami jest brane dosłownie, łącznie ze znakami nowej linii i ukośnikami wstecznymi. Surowy string nie może zawierać backticka.
Jak sprawdzić, czy string zawiera podciąg w Go?
strings.Contains(s, substr) zwraca bool. Powiązane funkcje: strings.HasPrefix, strings.HasSuffix, strings.Index (pozycja albo -1), strings.ContainsAny (dowolny znak z zestawu) oraz strings.EqualFold do porównania bez rozróżniania wielkości liter.
Jaki jest najszybszy sposób łączenia stringów w Go?
Dla kilku stringów wystarczy +. Gdy budujesz string w pętli, użyj strings.Builder: wywołuj wielokrotnie WriteString, a na końcu raz String(). Powtarzane += w pętli za każdym razem kopiuje cały string, więc spowalnia w miarę jego wzrostu. Aby połączyć slice separatorem, użyj strings.Join.
Dlaczego len zwraca złą długość mojego stringa?
len(s) zwraca liczbę bajtów, a nie znaków. Stringi w Go są w UTF-8, gdzie znaki spoza ASCII zajmują od 2 do 4 bajtów, więc len("héllo") to 6. Użyj utf8.RuneCountInString(s), aby poznać liczbę punktów kodowych Unicode.