Как правильно проверить строку на пустоту в Go?
Лучший способ: сравнение с пустой строкой
В Go наиболее идиоматичным и эффективным способом проверки строки на пустоту является прямое сравнение с пустой строкой через оператор ==:
if str == "" {
// строка пуста
}
Этот подход считается стандартом в Go-сообществе и используется в официальной документации, стандартной библиотеке и большинстве open-source проектов. Давайте разберёмся, почему именно этот вариант оптимален.
Почему это лучший выбор?
- Идиоматичность: Go — язык, где читаемость кода ценится превыше всего. Сравнение с пустой строкой наиболее явно выражает намерение программиста.
- Производительность: В Go строка — это структура из двух полей: указатель на данные и длина. При сравнении с
""компилятор генерирует максимально эффективный код, который просто проверяет длину строки (сравнивает поле длины с нулём). - Безопасность: В отличие от
len(str) == 0, этот подход не может быть случайно применён к nil-указателю (хотя для строк это не актуально, так как строки — value types).
Сравнение подходов по производительности
Все три способа, которые вы привели, имеют одинаковую производительность в скомпилированном коде. Компилятор Go достаточно умён, чтобы оптимизировать:
str == ""→ проверка длины == 0len(str) == 0→ проверка длины == 0len([]byte(str)) == 0→ проверка длины == 0 (аллокация не происходит, так как строка пуста)
Однако третий вариант (len([]byte(str))) потенциально опасен: для непустой строки он создаёт копию данных в байтовый срез, что приводит к аллокации памяти. Никогда не используйте его для проверки на пустоту!
Что насчёт пробелов?
Если вам нужно считать строки, состоящие только из пробелов, как "пустые" (для бизнес-логики), используйте функцию strings.TrimSpace:
import "strings"
func isEmptyOrWhitespace(s string) bool {
return strings.TrimSpace(s) == ""
}
// Или более эффективный способ (без создания новой строки):
func isBlank(s string) bool {
for _, r := range s {
if !unicode.IsSpace(r) {
return false
}
}
return true
}
Практические рекомендации
// Для обычной проверки на пустоту:
if input == "" {
log.Println("Пустой ввод")
return
}
// Для проверки на пустоту с учётом пробелов:
if strings.TrimSpace(input) == "" {
log.Println("Ввод пуст или содержит только пробелы")
return
}
// Для массовых проверок (например, в валидаторе):
func validateInputs(inputs ...string) bool {
for _, input := range inputs {
if input == "" {
return false
}
}
return true
}
Распространённые ошибки
- Не используйте
len(str) == 0для проверки строк, полученных из внешних источников — они могут быть nil (хотя в Go строки не могут быть nil, но могут быть указатели на строки). - Избегайте приведения к
[]byte— это лишняя операция, которая может вызвать проблемы с производительностью в горячих циклах. - Не путайте пустую строку
""с нулевым значением""(в Go это одно и то же).
В итоге: используйте str == "" — это просто, читаемо и эффективно. Go-сообщество единогласно в этом вопросе.
Альтернативный подход: использование пакета strings
Хотя прямое сравнение с пустой строкой — самый распространённый метод, в некоторых случаях удобнее использовать функции из стандартного пакета strings:
import "strings"
func main() {
name := "Alice"
// Проверка на пустоту
if len(strings.TrimSpace(name)) == 0 {
fmt.Println("Имя пустое или содержит только пробелы")
}
// Проверка с помощью Contains
if strings.Contains(name, "") {
// Всегда true! Так делать не надо
}
}
Когда это может быть полезно?
- Валидация форм: когда нужно проверить несколько полей сразу, удобно использовать
strings.TrimSpaceдля всех полей перед проверкой. - Работа с пользовательским вводом: часто требуется не только проверка на пустоту, но и удаление лишних пробелов — функции
strings.TrimSpaceрешают обе задачи. - Обработка CSV/JSON: при парсинге данных из файлов строки могут содержать невидимые символы (табуляцию, переносы строк).
Производительность
Метод с strings.TrimSpace создаёт новую строку, что приводит к аллокации памяти. Для разовых проверок это не критично, но в циклах с миллионами итераций лучше использовать кастомную функцию, которая проверяет символы на месте (как показано в первом ответе).
В целом, если вам не нужна обработка пробелов — придерживайтесь str == "". Это самый простой и эффективный способ в Go.