Menu

Golang 삼항 연산자: Go에 없는 이유와 대신 쓸 것

Go에는 삼항 연산자(cond ? a : b)가 없습니다. 그 이유와 관용적인 if/else 대체법, 기본값을 위한 cmp.Or, 제네릭 헬퍼 함수, 그리고 진짜 삼항 연산자와 다르게 만드는 함정을 설명합니다.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

Go에는 삼항 연산자가 없습니다. cond ? a : b가 없습니다. 관용적인 대체법은 if 문입니다:

변수를 기본값으로 선언한 뒤 if 안에서 바꿉니다. 두 분기 모두 작업이 필요하면 if/else를 씁니다:

var fee int
if member {
	fee = 0
} else {
	fee = computeFee(order)
}

Go가 삼항 연산자를 뺀 이유

Go FAQ가 직접 답합니다. 설계자들은 ?: 연산자가 도저히 읽을 수 없는 복잡한 표현식을 만드는 데 너무 자주 쓰이는 것을 봤고, if/else가 길긴 해도 확실히 더 명확하다고 판단했습니다. 언어에는 조건 제어 흐름 구문이 하나만 있으면 된다는 것입니다.

실제로 이 연산자가 없어서 드는 비용은 쓸 때마다 두세 줄이고, 그 대신 a ? b ? c : d : e 같은 중첩 표현식이 통째로 사라집니다.

대신 일찍 반환하기

함수 안에서는 변수를 아예 쓰지 않는 형태가 가장 깔끔한 경우가 많습니다:

조건을 이름 붙은 작은 함수로 빼내는 것이 가장 좋은 답일 때가 많습니다. 호출하는 곳은 원하던 삼항 연산자처럼 읽히고, 함수 이름이 조건의 의미를 설명해 줍니다.

cmp.Or로 기본값 정하기 (Go 1.22)

다른 언어에서 가장 흔한 삼항 연산자 용도는 "이 값을 쓰고, 비어 있으면 대체값을 쓴다"입니다. name ? name : "anonymous", JavaScript라면 name || "anonymous". Go 1.22는 바로 이 용도로 cmp.Or를 추가했습니다. 해당 타입의 제로 값이 아닌 첫 번째 인자를 반환합니다:

제로 값을 "없음"으로 취급하므로 "port가 일부러 0이다"와 "port가 설정되지 않았다"를 구분하지 못합니다. 0이 유효한 값이라면 포인터나 별도의 bool, 또는 명시적인 if를 쓰세요.

제네릭 If 헬퍼와 그 함정

제네릭(Go 1.18)을 쓰면 삼항 연산자처럼 보이는 함수를 만들 수 있습니다:

func If[T any](cond bool, a, b T) T {
	if cond {
		return a
	}
	return b
}

status := If(ok, "pass", "fail")

단순한 값에는 동작하고, 이렇게 쓰는 코드베이스도 있습니다. 하지만 이것은 삼항 연산자가 아니며, 그 차이가 중요합니다. Go는 함수를 호출하기 전에 모든 인자를 평가하므로 ab는 항상 둘 다 계산됩니다:

첫 번째 호출은 "a""b"를 모두 계산하고, 두 번째 호출은 조건이 거짓인데도 nil 포인터 역참조로 패닉이 납니다. 진짜 삼항 연산자라면 선택된 쪽만 평가합니다. 그러므로:

  • 한쪽이 포인터를 역참조하거나, 슬라이스를 인덱싱하거나, 없을 수도 있는 맵 항목을 읽는다면 이런 헬퍼를 절대 쓰지 마세요.
  • 한쪽이 비싸거나 부수 효과가 있다면 쓰지 마세요.
  • 가볍고 안전한 값에는 동작하지만, 많은 Go 리뷰어는 여전히 평범한 if를 요구할 것입니다.

함수를 넘겨서 분기를 지연 평가하게 만들 수도 있습니다. If(ok, func() string { return a }, func() string { return b }). 하지만 그쯤 되면 if 문이 더 짧습니다.

다른 요령들과 피해야 하는 이유

맵 조회. map[bool]string{true: "yes", false: "no"}[ok]는 동작하지만, 평가할 때마다 맵을 만들고 해시를 계산하며 두 값을 모두 평가합니다. 관용구가 아니라 신기한 요령일 뿐입니다.

즉시 호출 함수. 그 자리에서 호출하는 익명 함수로 표현식을 만들 수 있습니다:

label := func() string {
	if n > 0 {
		return "positive"
	}
	return "non-positive"
}()

이 방식은 실제로 지연 평가되고, 문장을 넣을 수 없는 복합 리터럴 안에서 가끔 도움이 됩니다. 대부분은 리터럴 바로 앞에서 변수에 값을 계산해 두는 편이 더 명확합니다.

대체법 고르기

상황사용할 것
두 값 중 하나 고르기기본값 대입 후 if
두 분기 모두 계산이 필요if/else
값이 함수의 결과를 결정이른 return
값이 비었을 때 대체값cmp.Or(value, fallback)
경우가 셋 이상switch
의미가 있는 반복되는 조건이름 붙은 작은 함수

조건 표현식을 추가하자는 제안은 Go 이슈 트래커에 꾸준히 올라오지만 지금까지 모두 거절되었습니다. if를 쓰세요.

자주 묻는 질문

Go에 삼항 연산자가 있나요?

없습니다. Go에는 cond ? a : b 표현식이 없습니다. Go FAQ에 따르면 설계자들은 이 연산자가 읽기 어려운 표현식을 만드는 데 너무 자주 쓰인다고 보고 넣지 않았습니다. 대신 if/else 문을 쓰세요.

Go에서 한 줄짜리 조건부 대입은 어떻게 쓰나요?

기본값을 먼저 대입한 뒤 덮어씁니다:

label := "odd"
if n%2 == 0 {
	label = "even"
}

이것이 관용적인 대체법입니다. gofmtif 본문을 한 줄로 두지 않으므로 항상 최소 세 줄이 됩니다.

Go에서 제네릭 삼항 함수를 만들 수 있나요?

네: func If[T any](cond bool, a, b T) T { if cond { return a }; return b }. 문제는 Go가 함수를 호출하기 전에 모든 인자를 평가한다는 점이라서 ab가 둘 다 계산됩니다. If(p != nil, p.Name, "")는 여전히 nil인 p를 역참조해서 패닉이 납니다. 진짜 삼항 연산자라면 한쪽만 평가합니다.

Go에서 문자열이 비어 있으면 기본값을 넣으려면 어떻게 하나요?

Go 1.22부터 cmp.Or(name, "anonymous")가 제로 값이 아닌 첫 번째 인자를 반환하므로, name""가 아니면 name을 돌려줍니다. 비교 가능한 모든 타입에 쓸 수 있고, 다른 함수 호출과 마찬가지로 인자를 모두 평가합니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기