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

Работа со строками в Go: пакет strings

4 min read Go Обновлено 03 Jan 2026
Обработка строк в Go: пакет strings и практики
Обработка строк в Go: пакет strings и практики

Маскот Go — синий гофер с большими глазами на фоне колонок зелёных символов.

TL;DR

Пакет strings из стандартной библиотеки Go предоставляет набор функций для поиска, замены, разбиения, объединения, изменения регистра, обрезки и эффективной сборки строк. Для большой части задач достаточно этих функций, но для высокопроизводительных сценариев стоит учитывать кодировки, аллокции и альтернативы вроде буферов и rune-ориентированных функций.

Краткое описание

String — последовательность символов (байтов в Go-строке). Пакет strings работает в байтовой семантике для многих операций, но одновременно поддерживает Unicode через специфичные функции и работу с rune. Ниже — практическое руководство и советы по использованию основных возможностей пакета.

Варианты поисковых операций

Пакет предоставляет несколько полезных функций для поиска подстрок и символов: Contains, ContainsAny, ContainsRune, Index, IndexAny, IndexByte, IndexFunc, IndexRune.

Примеры кода (оригинальная форма сохраняется):

import "fmt"
import "strings"

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

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

Объяснения:

  • strings.Contains возвращает true, если подстрока присутствует.
  • strings.ContainsAny проверяет наличие любого из символов в наборе.
  • strings.ContainsRune ищет конкретный rune (Unicode кодовую точку).

Index и похожие функции возвращают позицию первого вхождения или -1.

import (
    "fmt"
    "strings"
)

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

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

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

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

Важно: IndexByte оперирует байтами, а IndexRune и IndexFunc ориентированы на rune/Unicode.

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

Для замены используйте Replace и ReplaceAll.

import (
    "fmt"
    "strings"
)

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

Примечание: Replace с третьим параметром n контролирует количество замен; -1 означает «все вхождения». ReplaceAll эквивалентен Replace с -1.

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

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

Split, SplitAfter, SplitAfterN и SplitN возвращают срез строк, разделяя исходную строку.

  • strings.Split(s, sep) — стандартное разделение по сепаратору.
  • strings.SplitAfter(s, sep) — похожа, но включает сепаратор в результирующие элементы.
  • SplitN и SplitAfterN ограничивают число кусков.
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:

import (
    "fmt"
    "strings"
)

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

Изменение регистра

Простейшие функции:

  • ToLower
  • ToUpper
  • ToTitle
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.
}

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

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

Для частых конкатенаций используйте strings.Builder (или bytes.Buffer в старых примерах). Builder уменьшает число аллокаций по сравнению с частым использованием оператора +.

import (
    "fmt"
    "strings"
)

func main() {
    var b strings.Builder

    // Write some strings to the builder
    b.WriteString("This ")
    b.WriteString("is ")
    b.WriteString("a ")
    b.WriteString("test ")
    b.WriteString("string.")

    // Get the length of the builder
    fmt.Println(b.Len())

    // Convert the builder to a string
    str := b.String()
    fmt.Println(str)

    // Reset the builder
    b.Reset()

    // Write some more strings to the builder
    b.WriteString("This ")
    b.WriteString("is ")
    b.WriteString("another ")
    b.WriteString("test ")
    b.WriteString("string.")

    // Get the capacity of the builder
    fmt.Println(b.Cap())

    // Convert the builder to a string again
    str = b.String()
    fmt.Println(str)
}

Результат сборки строки в Go

Советы по производительности:

  • Предпочитайте strings.Builder при множественных конкатенациях в цикле.
  • Если нужно собирать большие объёмы данных или работать с бинарными данными, bytes.Buffer может быть более уместен.
  • Для форматирования с переменными используйте fmt.Sprintf экономно — он аллоцирует строку.

Обрезка строк

Функции: Trim, TrimLeft, TrimRight, TrimPrefix, TrimSuffix, TrimSpace.

import (
    "strings"
    "fmt"
)

func main() {
    // the full string
    s := "Hello, World!"

    // the element for the trim
    prefix := "Hello"
    suffix := "World!"

    // trims a string by specified trim set
    fmt.Println(strings.Trim(s, "!"))

    // trims out by spaces in the beginning and end of the string
    fmt.Println(strings.TrimSpace(s))

    // trims from the left  string by specified trim set
    fmt.Println(strings.TrimLeft(s, "Hello"))

    // trims out from the right string by specified trim set
    fmt.Println(strings.TrimRight(s, "World!"))

    // trims out a prefix
    fmt.Println(strings.TrimPrefix(s, prefix))

    // trims out a specific suffix
    fmt.Println(strings.TrimSuffix(s, suffix))
}

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

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

Для форматирования используйте пакет fmt с C-подобными спецификаторами (%%s, %%d и т.д.). fmt.Sprintf возвращает отформатированную строку.

Пример:

import (
    "fmt"
)

func main() {
    name := "Gopher"
    version := 1
    s := fmt.Sprintf("%s v%d", name, version)
    fmt.Println(s)
}

Когда стандартные функции не подойдут

  • При работе с очень большими потоками текста в tight loop может потребоваться профилирование и оптимизация аллокаций.
  • Для сложной нормализации Unicode (например, NFC/NFD) стандартный пакет strings не предоставляет средств; используйте golang.org/x/text/unicode/norm.
  • Если нужна потоковая обработка без удержания всей строки в памяти, рассматривайте io.Reader и буферные операции.

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

  • bytes.Buffer — удобен, когда вы работаете с байтами.
  • fmt.Fprintf на bytes.Buffer — удобно для комбинирования форматирования и сборки.
  • regexp — для сложных шаблонных замен (но дорог по производительности).
  • golang.org/x/text — для работы с локализацией и расширенной поддержкой Unicode.

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

  • Строка в Go — неизменяемый срез байтов (internal: последовательность байтов). Для частых модификаций используйте Builder.
  • Всегда учитывайте, работаете ли вы с байтами или rune: индекс в байтах != индекс в символах для UTF-8.
  • Предпочитайте специализированные функции (Trim, ReplaceAll, SplitN) — они компактны и оптимизированы.

Чек-лист для практики

  • Проверить, используются ли функциональные возможности пакета strings перед написанием собственной реализации.
  • Выбрать strings.Builder для множественных конкатенаций.
  • Использовать IndexFunc/ContainsRune при работе с Unicode.
  • Не применять regexp без необходимости (профайлить сначала).
  • Для нормализации Unicode использовать x/text.

Тестовые случаи и критерии приёмки

  • Поиск: проверка Index/Contains для ASCII и UTF-8 строк.
  • Замена: Replace с n=1, n=-1 и ReplaceAll дают ожидаемый результат.
  • Split/Join: split+join возвращает исходную строку (с учётом сепараторов).
  • Builder: многократные WriteString и проверка результата и Len/Cap.

Частые ошибки и как их избежать

  • Ошибка: использование IndexByte для Unicode-символов. Правильно: IndexRune или IndexFunc.
  • Ошибка: ожидание, что len(s) возвращает число «символов»; он возвращает байты. Для символов используйте utf8.RuneCountInString.
  • Ошибка: преждевременная оптимизация без профайлинга — сначала убедитесь, что это узкое место.

Мини‑глоссарий (1 строка)

  • Rune: кодовая точка Unicode; Byte: один байт в UTF-8 представлении; Builder: оптимизированный для сборки строк тип.

Итог

Пакет strings покрывает большинство повседневных задач по работе со строками в Go: поиск, замена, разбиение, объединение, изменение регистра, обрезка и эффективная сборка. Для сложной работы с Unicode или требовательной к производительности логики стоит сочетать strings с bytes, fmt, regexp и пакетами из golang.org/x.

Важно: всегда профилируйте реальные кейсы, прежде чем оптимизировать.

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

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

Загрузить Raspberry Pi с SSD — полное руководство
Raspberry Pi

Загрузить Raspberry Pi с SSD — полное руководство

Синхронизация звука в VLC на Android TV
Руководство

Синхронизация звука в VLC на Android TV

Фото в картину: эффект текстуры в Photoshop
Photoshop

Фото в картину: эффект текстуры в Photoshop

Воспроизвести MKV на iPhone и iPad — VLC и способы
Инструкции

Воспроизвести MKV на iPhone и iPad — VLC и способы

Как очистить кэш на смарт‑телевизоре
Руководство

Как очистить кэш на смарт‑телевизоре

Как убрать нежелательный контент на Reddit
Социальные сети

Как убрать нежелательный контент на Reddit