Эквивалент тернарного оператора в Go: как написать условное выражение в одну строку?
Почему в Go нет тернарного оператора и что использовать вместо него
Go — это язык, созданный с упором на читаемость и простоту. Создатели языка (Роб Пайк, Кен Томпсон и Роберт Гризмер) сознательно отказались от тернарного оператора, считая, что он часто ведёт к запутанному коду. Вместо этого в Go используется явный if-else, который, хотя и занимает больше строк, делает логику очевидной.
Идиоматичный способ: обычный if-else
В Go принято писать так:
package main
import "fmt"
func main() {
age := 20
var status string
if age >= 18 {
status = "взрослый"
} else {
status = "ребёнок"
}
fmt.Println(status)
}
Это 4 строки вместо одной — да. Но такой код:
- Очевиден — любой разработчик сразу поймёт логику
- Отлаживаем — можно поставить точку остановки на каждую ветку
- Расширяем — легко добавить
else ifбез переписывания структуры
Лайфхак: если очень хочется в одну строку
Можно использовать функцию-помощник. Это нестандартный, но допустимый приём:
package main
import "fmt"
// If — функция-аналог тернарного оператора
func If[T any](condition bool, trueVal, falseVal T) T {
if condition {
return trueVal
}
return falseVal
}
func main() {
age := 20
status := If(age >= 18, "взрослый", "ребёнок")
fmt.Println(status) // "взрослый"
// Работает с любыми типами
max := If(10 > 5, 10, 5)
fmt.Println(max) // 10
}
Эта функция использует дженерики (появились в Go 1.18), поэтому работает с любым типом данных. Но помните: такой подход не является идиоматичным для Go. Сообщество в большинстве случаев предпочитает явный if-else.
Когда if-else действительно неудобен
Есть ситуации, где хочется компактности — например, при инициализации карты или передаче значения в функцию:
// Плохо (тяжело читать)
value := map[string]int{}
if someCondition {
value["key"] = 100
} else {
value["key"] = 200
}
// Лучше (явно, но громоздко)
var v int
if someCondition {
v = 100
} else {
v = 200
}
value["key"] = v
// Можно через функцию If (компактно)
value["key"] = If(someCondition, 100, 200)
Вывод
Идиоматичный Go — это явный if-else. Если вы пишете код, который будут читать другие Go-разработчики, используйте его. Функция If — это "костыль" для случаев, когда краткость критична (например, в однострочных лямбдах или тестах). Но в production-коде лучше придерживаться стандартного подхода.
Альтернативный подход: используйте switch для множественных условий
Если у вас больше двух веток, if-else может стать громоздким. В таких случаях идиоматичнее использовать switch:
package main
import "fmt"
func main() {
score := 85
var grade string
switch {
case score >= 90:
grade = "Отлично"
case score >= 75:
grade = "Хорошо"
case score >= 50:
grade = "Удовлетворительно"
default:
grade = "Неудовлетворительно"
}
fmt.Println(grade)
}
switch в Go не требует break (он автоматический) и может использоваться без выражения (как в примере выше) — это делает его отличной заменой цепочке if-else if. Код становится более плоским и читаемым.
Ещё один совет: если вам нужно присвоить значение в зависимости от условия прямо при объявлении переменной, используйте анонимную функцию (IIFE — Immediately Invoked Function Expression):
status := func() string {
if age >= 18 {
return "взрослый"
}
return "ребёнок"
}()
Это редко используется, но иногда помогает сохранить компактность без выноса логики в отдельную функцию.