Обрезаем пробелы в Go: как избавиться от лишних символов в строке

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Проблема, знакомая каждому разработчику

Представьте: вы пишете парсер логов, обрабатываете пользовательский ввод из формы или готовите данные для API. Строки приходят с лишними пробелами в начале и конце. Если их не убрать — баги, сломанные сравнения, кривые JSON и потерянные часы дебага. Это классическая задача, которая на Stack Overflow собрала тысячи просмотров. Сегодня мы разберем ее на Go — быстро, элегантно и без сюрпризов.

В этом руководстве вы узнаете:

  • Как использовать стандартную библиотеку strings для обрезки пробелов.
  • Чем отличается TrimSpace от TrimLeft и TrimRight.
  • Как написать свою кастомную функцию для нестандартных whitespace-символов.
  • Как не наступить на грабли с Unicode и табуляцией.

Поехали!

Быстрый старт: strings.TrimSpace

Самый простой и популярный способ убрать пробелы с обоих концов строки — использовать функцию strings.TrimSpace из стандартного пакета strings. Она удаляет все символы, которые Go считает "пробельными" (whitespace): обычные пробелы, табуляции, переводы строк, возвраты каретки и даже вертикальные табуляции.

Вот как это выглядит в коде:

package main

import (
    "fmt"
    "strings"
)

func main() {
    raw := "   Привет, мир!   \n\t"
    cleaned := strings.TrimSpace(raw)
    
    fmt.Printf("Исходная: %q\n", raw)
    fmt.Printf("Очищенная: %q\n", cleaned)
}

Вывод:

Исходная: "   Привет, мир!   \n\t"
Очищенная: "Привет, мир!"

Обратите внимание: %q в fmt.Printf показывает строку с escape-последовательностями — это удобно для отладки, чтобы видеть скрытые символы.

Когда использовать: в 90% случаев этого достаточно. Если вам нужно просто "почистить" строку от мусора по краям — берите TrimSpace.

Тонкая настройка: TrimLeft и TrimRight

Иногда нужно обрезать пробелы только слева или только справа. Для этого в Go есть strings.TrimLeft и strings.TrimRight. Но есть нюанс: они работают не с "пробельными символами" по умолчанию, а с переданным набором символов.

Пример:

package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "   \t\n   Hello   "
    
    // Обрезаем только слева (пробелы, табуляции, переводы строк)
    left := strings.TrimLeft(s, " \t\n")
    fmt.Printf("Слева: %q\n", left)
    
    // Обрезаем только справа (только пробелы)
    right := strings.TrimRight(s, " ")
    fmt.Printf("Справа: %q\n", right)
}

Вывод:

Слева: "Hello   "
Справа: "   \t\n   Hello"

Важно: TrimLeft и TrimRight удаляют все символы из второго аргумента, пока не встретят символ, которого там нет. Если вы укажете только пробел " ", то табуляция \t останется нетронутой.

Аналог TrimSpace для одной стороны

Если вам нужно обрезать все whitespace только слева или только справа, но лень перечислять все символы, можно написать небольшую обертку:

func trimLeftSpace(s string) string {
    return strings.TrimLeft(s, " \t\n\r\v\f")
}

func trimRightSpace(s string) string {
    return strings.TrimRight(s, " \t\n\r\v\f")
}

Или, для тех, кто любит краткость, использовать strings.TrimSpace с хитростью:

// Обрезаем только слева: сначала реверсим, потом TrimSpace, потом реверсим обратно
func trimLeftSpace(s string) string {
    runes := []rune(s)
    for i, r := range runes {
        if !unicode.IsSpace(r) {
            return string(runes[i:])
        }
    }
    return ""
}

Но второй вариант — для понимания алгоритма, на практике проще использовать strings.TrimLeft с полным набором символов.

Продвинутый уровень: TrimFunc и кастомные критерии

Go предоставляет функцию strings.TrimFunc, которая позволяет задать любое правило для удаления символов. Вы передаете функцию, которая возвращает true, если символ нужно удалить.

Пример: удаляем все пробелы и знаки пунктуации с краев строки.

package main

import (
    "fmt"
    "strings"
    "unicode"
)

func main() {
    s := "!!!   Hello, World!   ???"
    
    // Кастомная функция: удаляем пробелы и знаки препинания
    cleaned := strings.TrimFunc(s, func(r rune) bool {
        return unicode.IsSpace(r) || unicode.IsPunct(r)
    })
    
    fmt.Printf("Результат: %q\n", cleaned)
}

Вывод:

Результат: "Hello, World"

Когда это нужно: если вы работаете с нестандартными разделителями, например, с символами из других алфавитов или специфическими управляющими кодами.

Подводные камни: Unicode, rune и производительность

Go из коробки хорошо работает с UTF-8. Функции из пакета strings оперируют рунами (rune), поэтому кириллица, иероглифы и эмодзи обрабатываются корректно.

Но есть один момент: strings.TrimSpace использует определение whitespace из Unicode. Это значит, что он удаляет не только стандартный пробел U+0020, но и, например, неразрывный пробел U+00A0 (который часто встречается в HTML).

Проверим:

package main

import (
    "fmt"
    "strings"
)

func main() {
    // Неразрывный пробел (U+00A0) в начале и конце
    s := "\u00A0Привет\u00A0"
    cleaned := strings.TrimSpace(s)
    
    fmt.Printf("Исходная: %U %U\n", []rune(s)[0], []rune(s)[len([]rune(s))-1])
    fmt.Printf("Очищенная: %q\n", cleaned)
}

Вывод:

Исходная: U+00A0 U+00A0
Очищенная: "Привет"

Работает! Но если вам нужно удалить только обычные пробелы и оставить неразрывные — используйте TrimLeft/TrimRight с явным списком " ".

Производительность: что быстре

Блоги

Рекомендаций по книгам