Menu

Строки в Golang: Split, Join, Contains, Replace и другие

Работа со строками в Go: пакет strings (Split, Join, Contains, Replace, Fields, TrimSpace, ToUpper), эффективная сборка строк через strings.Builder, многострочные сырые строки, неизменяемость и почему len считает байты.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Строка в Go это неизменяемая последовательность байтов, обычно текст в UTF-8. Операторы работают с самой строкой (+, ==, <, индексация, срезы), а всё остальное находится в стандартном пакете strings.

Разбиение строк

ФункцияГде разбиваетПримечания
Split(s, sep)на каждом sepсохраняет пустые части; Split("", ",") возвращает [""], одну пустую строку
SplitN(s, sep, n)не больше n частейпоследняя часть содержит остаток
SplitAfter(s, sep)на каждом sepоставляет разделитель в каждой части
Fields(s)по последовательностям пробельных символовникогда не возвращает пустых частей
FieldsFunc(s, f)на символах, где f истиннасвои разделители
Cut(s, sep)только на первом sepвозвращает до, после, найдено ли (Go 1.18)

Случай Split("", ",") ловит многих: пустой ввод даёт слайс длины 1, а не 0. При разбиении пользовательского ввода Fields или предварительная проверка s == "" избавляют от фантомного пустого элемента.

strings.Cut самый чистый способ разбить пары вроде key=value или user@host. В Go 1.24 также появились версии-итераторы, strings.SplitSeq и strings.FieldsSeq, которые выдают части по одной, не создавая слайс.

Поиск

ФункцияВозвращает
Contains(s, sub)true, если sub встречается в s
ContainsAny(s, chars)true, если встречается любой символ из chars
HasPrefix(s, p) / HasSuffix(s, p)true, если s начинается или заканчивается на p
Index(s, sub)позицию первого совпадения в байтах или -1
LastIndex(s, sub)позицию последнего совпадения в байтах или -1
Count(s, sub)число непересекающихся совпадений
EqualFold(a, b)равенство без учёта регистра

Любой поиск учитывает регистр, кроме EqualFold. Чтобы искать без учёта регистра, приведите обе стороны к нижнему регистру или используйте EqualFold для сравнения строк целиком.

Преобразование

Одна ловушка: Trim, TrimLeft и TrimRight принимают набор символов, а не префикс. strings.TrimLeft("abcab", "ab") убирает все ведущие a и b и возвращает "cab". Чтобы убрать точный префикс или суффикс, используйте TrimPrefix и TrimSuffix.

Конкатенация и strings.Builder

+ склеивает строки, а fmt.Sprintf форматирует значения в одну строку. Оба каждый раз создают новую строку, потому что строки неизменяемы. Для нескольких операций это нормально, а в цикле медленно: каждый += копирует всё, что уже собрано. Вместо этого используйте strings.Builder:

Нулевой strings.Builder готов к работе. Он реализует io.Writer, поэтому fmt.Fprintf пишет в него напрямую. Если примерно знаете размер результата, сначала вызовите b.Grow(n). Не копируйте Builder после записи в него; передавайте указатель.

Многострочные и сырые строки

В Go два вида строковых литералов:

Строки в двойных кавычках обрабатывают escape-последовательности (\n, \t, \", \\, \u00e9) и должны помещаться на одной строке. Сырые строки в обратных кавычках берут всё буквально, включая переводы строк, поэтому так пишут многострочный текст, регулярные выражения, JSON и пути Windows. Сырая строка не может содержать обратную кавычку, а символы возврата каретки внутри неё отбрасываются. Обратите внимание: запрос выше начинается с перевода строки, потому что литерал начинается сразу после открывающей обратной кавычки.

Длина, индексация и подстроки

len(s) это число байтов. s[i] это байт, а s[i:j] это подстрока по позициям в байтах:

ï и é занимают по два байта, поэтому в строке 12 байтов и 10 символов. Срез по байтам безопасен, пока позиции берутся из strings.Index и подобных функций, которые возвращают смещения в байтах на границах символов. Чтобы взять «первые n символов», сначала преобразуйте строку в []rune. UTF-8 подробно объясняется на странице о рунах и байтах.

Строки неизменяемы

Изменить байт на месте нельзя: s[0] = 'H' это ошибка компиляции (cannot assign to s[0] (neither addressable nor a map index expression)). Каждая функция из strings возвращает новую строку. Чтобы редактировать, преобразуйте в []byte или []rune, измените слайс и преобразуйте обратно:

b := []byte("hello")
b[0] = 'H'
s := string(b) // "Hello"

Неизменяемость также делает подстроки дешёвыми: s[2:5] разделяет память с s, а не копирует её. Обратная сторона: маленькая подстрока огромной строки держит в памяти всю огромную строку. Используйте strings.Clone (Go 1.20), когда сохраняете короткий кусок большого ввода.

Сравнение строк

== и != сравнивают содержимое, а < и > сравнивают побайтно, что для ASCII означает алфавитный порядок. strings.Compare существует, но нужна редко; slices.Sort для []string использует <. Для сортировки текста не на английском с учётом локали используйте golang.org/x/text/collate.

Преобразование других типов

Числа превращаются в строки через strconv.Itoa, strconv.FormatFloat или fmt.Sprintf, а строки в числа через strconv.Atoi и strconv.ParseFloat. Не пишите string(42): это даёт символ с кодовой точкой 42, "*". Полная таблица на странице о преобразовании типов.

Часто задаваемые вопросы

Как разбить строку в Go?

Используйте strings.Split(s, sep): strings.Split("a,b,c", ",") возвращает ["a" "b" "c"]. Чтобы разбить по любым последовательностям пробельных символов и отбросить пустые части, используйте strings.Fields(s). strings.SplitN ограничивает число частей, а strings.Cut разбивает один раз вокруг первого разделителя.

Как написать многострочную строку в Go?

Используйте сырой строковый литерал в обратных кавычках:

query := `SELECT id, name
FROM users
WHERE active = true`

Всё между обратными кавычками берётся буквально, включая переводы строк и обратные слэши. Сырая строка не может содержать обратную кавычку.

Как проверить, содержит ли строка подстроку, в Go?

strings.Contains(s, substr) возвращает bool. Связанные функции: strings.HasPrefix, strings.HasSuffix, strings.Index (позиция или -1), strings.ContainsAny (любой символ из набора) и strings.EqualFold для сравнения без учёта регистра.

Как быстрее всего склеивать строки в Go?

Для нескольких строк подойдёт +. Когда строка собирается в цикле, используйте strings.Builder: вызывайте WriteString многократно, а String() один раз в конце. Повторный += в цикле каждый раз копирует всю строку, поэтому по мере роста строки работает всё медленнее. Чтобы соединить слайс через разделитель, используйте strings.Join.

Почему len возвращает неправильную длину строки?

len(s) возвращает число байтов, а не символов. Строки в Go хранятся в UTF-8, где символы вне ASCII занимают от 2 до 4 байтов, поэтому len("héllo") равно 6. Для числа кодовых точек Unicode используйте utf8.RuneCountInString(s).

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ