Гид по технологиям

Манипуляции со строками в Go: руководство по пакету strings

5 min read Программирование Обновлено 06 Dec 2025
Строки в Go: пакет strings — примеры и приёмы
Строки в Go: пакет strings — примеры и приёмы

Голанг-талисман — синий гофер на фоне столбцов зелёных символов.

Строки — базовый тип во всех языках программирования. В Go строка — это неизменяемая последовательность байт, обычно закодированных в UTF‑8. Манипуляции со строками пригодятся в парсинге, валидации данных, формировании HTTP‑ответов и подготовке логов.

Краткая сводка о пакете strings

Пакет strings содержит функции для:

  • поиска подстрок и символов;
  • получения индексов (по байту и по руну);
  • замены подстрок;
  • разбиения и объединения;
  • изменения регистра (верхний/нижний/заглавные);
  • обрезки пробелов и специфичных символов;
  • эффективной сборки строк через strings.Builder.

Важно: строки в Go неизменяемы. Любая «модификация» строкы возвращает новую строку. Для многократной конкатенации и снижения аллокаций применяйте strings.Builder или bytes.Buffer.

Поиск подстрок и символов

Определения:

  • rune — кодовая точка Unicode (alias int32);
  • byte — uint8, одна байтовая ячейка в строке;

Функции поиска:

  • strings.Contains(s, substr) — содержит ли s подстроку substr;
  • strings.ContainsAny(s, chars) — содержит ли s любой символ из chars;
  • strings.ContainsRune(s, r) — содержит ли s руну r.

Пример:

import (
    "fmt"
    "strings"
)

func main() {
    aString := "Hello, World!"
    substring := "World"
    characters := "aeiou"
    aRune := 'o'

    fmt.Println(strings.Contains(aString, substring))    // true
    fmt.Println(strings.ContainsAny(aString, characters)) // true
    fmt.Println(strings.ContainsRune(aString, aRune))     // true
}

Поиск индекса

Функции Index* возвращают позицию (в байтах) или -1:

  • strings.Index(s, substr)
  • strings.IndexAny(s, chars)
  • strings.IndexByte(s, b)
  • strings.IndexRune(s, r)
  • strings.IndexFunc(s, f) — индекс первой руны, для которой f возвращает true.

Пример с IndexFunc:

import (
    "fmt"
    "strings"
)

func main() {
    aString := "Hello, world!"
    substring := "world"
    chars := "wrld"
    byteCharacter := byte('o')
    aRune := rune('o')

    fmt.Println(strings.Index(aString, substring))    // 7
    fmt.Println(strings.IndexAny(aString, chars))     // 7
    fmt.Println(strings.IndexByte(aString, byteCharacter)) // 4

    f := func(r rune) bool {
        return r == 'o'
    }

    fmt.Println(strings.IndexFunc(aString, f))        // 4
    fmt.Println(strings.IndexRune(aString, aRune))    // 4
}

Важно: индексы возвращаются в байтах. Для работы с позициями в Unicode‑символах считайте руны с помощью for range или используйте package unicode/utf8.

Замена подстрок

Функции:

  • strings.Replace(s, old, new, n) — заменить n вхождений (n<0 — все);
  • strings.ReplaceAll(s, old, new) — заменить все вхождения.

Пример:

import (
    "fmt"
    "strings"
)

func main() {
    theString := "This is a test string to be modified."
    fmt.Println(strings.Replace(theString, "is", "was", 1))  // Replace first
    fmt.Println(strings.Replace(theString, "is", "was", -1)) // Replace all
    fmt.Println(strings.ReplaceAll(theString, "is", "was"))  // Replace all
}

Где стоит обратить внимание:

  • Замена работает на байтовом уровне для строк; если ваш target содержит мультибайтовые руны, результат может отличаться от ожидаемого при использовании байтовых операций.

Результат операции замены строк в Go

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

Функции для разбиения:

  • strings.Split(s, sep)
  • strings.SplitAfter(s, sep) — включает разделитель в результирующие элементы;
  • strings.SplitN(s, sep, n)
  • strings.SplitAfterN(s, sep, n)

Пример:

import (
    "fmt"
    "strings"
)

func main() {
    s := "This is a test string to be split."

    fmt.Println(strings.Split(s, " "))         // разделить по пробелу
    fmt.Println(strings.SplitAfter(s, " "))    // разделитель остаётся
    fmt.Println(strings.SplitAfterN(s, " ", 3))
    fmt.Println(strings.SplitN(s, " ", 3))
}

Объединение:

  • strings.Join(elems, sep) — принимает срез строк и разделитель.
import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(strings.Join([]string{"Hello", "World"}, ":"))
    // Output: Hello:World
}

Приведение регистра

Функции:

  • strings.ToLower(s)
  • strings.ToUpper(s)
  • strings.ToTitle(s)

Пример:

import (
    "fmt"
    "strings"
)

func main() {
    s := "This is a test string."

    fmt.Println(strings.ToLower(s)) // this is a test string.
    fmt.Println(strings.ToUpper(s)) // THIS IS A TEST STRING.
    fmt.Println(strings.ToTitle(s)) // THIS IS A TEST STRING.
}

Примечание: ToTitle делает заглавными руны; для корректной локализации (например, турецкий) используйте пакет golang.org/x/text/cases.

Эффективная сборка строк

Проблема: конкатенация с помощью + создаёт новые строки и может привести к множественным аллокациям.

Рекомендуемые решения:

  • strings.Builder — специально для эффективной сборки строк;
  • bytes.Buffer — удобен, когда работают байты и io.Writer интерфейсы.

Пример с strings.Builder:

import (
    "fmt"
    "strings"
)

func main() {
    var b strings.Builder

    b.WriteString("This ")
    b.WriteString("is ")
    b.WriteString("a ")
    b.WriteString("test ")
    b.WriteString("string.")

    fmt.Println(b.Len())
    str := b.String()
    fmt.Println(str)

    b.Reset()

    b.WriteString("This ")
    b.WriteString("is ")
    b.WriteString("another ")
    b.WriteString("test ")
    b.WriteString("string.")

    fmt.Println(b.Cap())
    fmt.Println(b.String())
}

Результат операции сборки строк

Обрезка строк (trimming)

Функции:

  • strings.Trim(s, cutset)
  • strings.TrimLeft(s, cutset)
  • strings.TrimRight(s, cutset)
  • strings.TrimPrefix(s, prefix)
  • strings.TrimSuffix(s, suffix)
  • strings.TrimSpace(s)

Пример:

import (
    "strings"
    "fmt"
)

func main() {
    s := " Hello, World! "
    prefix := "Hello"
    suffix := "World!"

    fmt.Println(strings.Trim(s, " !"))        // уберёт пробелы и восклицательные
    fmt.Println(strings.TrimSpace(s))          // уберёт пробелы по краям
    fmt.Println(strings.TrimLeft(s, " H"))   // обрезает слева
    fmt.Println(strings.TrimRight(s, "! "))  // обрезает справа
    fmt.Println(strings.TrimPrefix(s, " "))  // убирает конкретный префикс
    fmt.Println(strings.TrimSuffix(s, "! ")) // убирает конкретный суффикс
}

Результат операции обрезки строк

Форматирование строк

Для форматирования строк и вывода используйте пакет fmt и его форматные спецификаторы: fmt.Sprintf, fmt.Fprintf и т. д. Это удобнее и безопаснее, чем ручная конкатенация.

Когда стандартный подход может не подойти

  • Unicode и байты: многие функции работают в байтах; при работе с многобайтовыми рунами используйте for range, utf8 или unicode.
  • Очень большие текстовые потоки: для потоковой обработки лучше применять bufio.Reader/Writer и читать по частям вместо загрузки всего текста в память.
  • Сложные шаблоны совпадений: regexp может быть медленным; для простых требований разумнее использовать index/strings.Contains или библиотеку Aho‑Corasick для множественных шаблонов.

Важно: регулярные выражения удобны, но могут быть тяжёлыми по CPU и потреблять много памяти при неправильно составленных паттернах.

Альтернативные подходы и примеры

  • regexp — для сложных совпадений и захвата групп;
  • bytes package — работа на уровне []byte для оптимизации и совместимости с io;
  • bufio.Scanner/Reader — для построчной работы с большими потоками;
  • golang.org/x/text — расширенные операции с локализацией и преобразованием регистра.

Пример: безопасный подсчёт символов (рут) в строке:

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    s := "こんにちは"
    fmt.Println(utf8.RuneCountInString(s)) // количество рун
}

Ментальные модели и эвристики

  • Строка = неизменяемая последовательность байт в UTF‑8.
  • Для операций с символами используйте руны; для операций с байтами — byte/slice.
  • Для многократных конкатенаций используйте Builder/Buffer.
  • Для поиска простых подстрок предпочитайте strings.Index / Contains; regexp — когда простых средств недостаточно.

Чек-листы по ролям

Для разработчика:

  • Проверить, работают ли функции с Unicode корректно.
  • Использовать strings.Builder при больших объёмах конкатенаций.
  • Тестировать краевые случаи: пустые строки, строки с нулевыми байтами, только пробелы.

Для архитектора:

  • Оценить объём данных и принять решение о потоковой или пакетной обработке.
  • Выбрать между простыми строковыми операциями и индексированием/поисковыми структурами для производительности.

Для ревьювера кода:

  • Ищите лишние аллокации (массовые конкатенации с +).
  • Убедитесь, что для проверки символов используется rune, если требуется Unicode‑чувствительность.

Сниппеты — шпаргалка (cheat sheet)

  • Проверка наличия: strings.Contains(s, “x”)
  • Индекс: strings.Index(s, “x”)
  • Замена всех: strings.ReplaceAll(s, “old”, “new”)
  • Разбить: strings.Split(s, “,”)
  • Объединить: strings.Join(vals, “,”)
  • Привести к нижнему регистру: strings.ToLower(s)
  • Обрезать пробелы: strings.TrimSpace(s)
  • Собрать много строк: var b strings.Builder; b.WriteString(“x”)

Краткий глоссарий (1‑строчные определения)

  • Строка: неизменяемая последовательность байт (UTF‑8).
  • Rune: кодовая точка Unicode (int32).
  • Byte: 8‑битный элемент строки.
  • s.Builder / bytes.Buffer: структуры для эффективной сборки строк/байтов.
  • Index vs RuneIndex: Index возвращает байтовую позицию.

Риски и рекомендации по безопасности

  • Не доверяйте пользовательским данным при форматировании команд/шаблонов — избегайте прямого включения пользовательского ввода в форматные строки без экранирования.
  • Для логов, содержащих пользовательские данные, применяйте маскирование чувствительных полей.

Краткое резюме

  • Пакет strings покрывает большинство задач по работе со строками в Go.
  • Для Unicode‑безопасности учитывайте различие между байтами и рунами.
  • Для производительности при множественных конкатенациях используйте Builder или Buffer.

Важно: при миграции кода с других языков проверьте предположения о кодировке и изменяемости строк.

Спасибо за чтение — применяйте эти приёмы в повседневной работе с текстом в Go.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Отключить анимацию в Windows 10
Windows

Отключить анимацию в Windows 10

Исправить 0xC00D36FA — устройство звука не найдено
Windows

Исправить 0xC00D36FA — устройство звука не найдено

Повернуть линейку в Snip and Sketch
Windows

Повернуть линейку в Snip and Sketch

Как записать встречу в Skype быстро и правильно
Руководство

Как записать встречу в Skype быстро и правильно

Как найти песню по мелодии или словам
Музыка

Как найти песню по мелодии или словам

Генерация UUID в Rust
Разработка

Генерация UUID в Rust