Go의 if는 조건을 괄호로 감싸지 않고, 중괄호를 항상 요구하며, 그 if 안에서만 쓰이는 변수를 선언하는 짧은 문장으로 시작할 수 있습니다.
조건은 위에서부터 검사되고 처음으로 참인 분기가 실행됩니다. else if와 else는 선택입니다.
문법 규칙
C, Java, JavaScript와 다른 규칙이 세 가지 있습니다:
- 조건을 감싸는 괄호가 없습니다.
if (x > 5)도 컴파일되지만gofmt가 괄호를 지웁니다. - 문장이 하나뿐이어도 중괄호가 필수입니다. 중괄호 없는
if x > 5 return은 없습니다. else는 닫는 중괄호와 같은 줄에 씁니다. Go는 줄 끝의}뒤에 세미콜론을 넣으므로 다음 코드는 실패합니다:
if x > 5 {
fmt.Println("big")
}
else {
fmt.Println("small")
}
syntax error: unexpected keyword else, expected }
} else {를 한 줄에 쓰세요.
조건은 bool이어야 합니다. Go는 0, "", nil을 거짓으로 취급하지 않으므로 if count {}와 if name {}은 컴파일되지 않습니다. 명시적으로 비교하세요: if count > 0, if name != "", if user != nil.
조건은 &&(그리고), ||(또는), !(부정)로 조합합니다. &&와 ||는 모두 단락 평가를 하므로 nil 검사를 안전하게 할 수 있습니다:
if user != nil && user.IsAdmin() {
// user.IsAdmin() is only called when user is not nil
}
초기화 구문이 있는 if
if는 조건 앞에서 세미콜론으로 구분한 짧은 문장 하나를 실행할 수 있습니다. 거기서 선언한 변수는 그 if의 모든 분기에서 보이고, 그 뒤로는 보이지 않습니다:
이 패턴은 잠깐 쓰는 변수를 바깥 스코프에 두지 않게 해 줍니다. 맵 조회(v, ok := m[k]), 타입 단언(s, ok := v.(string)), 오류 처리에서 늘 볼 수 있습니다.
반대로, 값을 if 뒤에서 써야 한다면 앞에서 선언하세요. 결과를 초기화 구문에 넣어 놓고 아래에서 쓰려고 하는 것이 흔한 실수입니다.
if err != nil 관용구
실패할 수 있는 함수는 마지막에 error를 반환합니다. 바로 확인해서 처리하거나 반환하고, 정상 경로는 들여쓰지 않은 채 이어 갑니다:
if err != nil { return ... } 뒤에 else가 없다는 점에 주목하세요. Go 스타일은 오류를 처리하고 반환한 뒤, 정상 흐름을 왼쪽 여백에 둡니다. 오류 감싸기와 오류 타입 확인은 오류 처리 페이지에서 다룹니다.
중첩 대신 이른 반환
깊게 중첩된 if 블록은 읽기 어렵습니다. 조건을 뒤집어서 일찍 반환하면 각 검사가 가드처럼 읽힙니다:
// Nested
func canCheckout(u *User, cart *Cart) bool {
if u != nil {
if u.Verified {
if len(cart.Items) > 0 {
return true
}
}
}
return false
}
// Guards
func canCheckout(u *User, cart *Cart) bool {
if u == nil || !u.Verified {
return false
}
if len(cart.Items) == 0 {
return false
}
return true
}
Go 개발자들은 이것을 정상 경로를 왼쪽에 정렬한다고 표현합니다. revive 같은 린터는 return으로 끝나는 블록 뒤의 else를 지적합니다. 그 else는 쓸데없이 들여쓰기만 늘리기 때문입니다.
if/else와 switch
한 값을 여러 경우와 비교하는 긴 else if 체인은 switch로 쓰는 편이 읽기 좋습니다. 표현식이 없는 switch는 임의의 조건으로 된 if/else if 체인을 대신합니다:
switch {
case score >= 90:
return "A"
case score >= 80:
return "B"
default:
return "F"
}
분기가 한두 개면 if, 셋 이상이면 switch를 쓰세요.
삼항 연산자는 없다
Go에는 cond ? a : b가 없습니다. if로 대입하세요:
label := "odd"
if n%2 == 0 {
label = "even"
}
이유와 대안은 삼항 연산자 페이지에서 설명합니다.
흔한 실수
- :=로 인한 섀도잉.
if x, err := f(); err == nil { ... }는 그if에서만 쓰이는 새x를 선언합니다. 바깥의x는 갱신되지 않습니다. - 조건 안의 대입.
if x = 5 {}는 C처럼 조용한 버그가 아니라 컴파일 오류(cannot use assignment x = 5 as value)입니다.==를 쓰세요. - 실수를 ==로 비교. 계산된 값에
if total == 0.3은 실패합니다. 허용 오차를 두고 비교하세요. - 엉뚱한 오류 확인.
a, err := f()와b, err := g()다음에는 각if err != nil이 해당 호출 바로 뒤에 있는지 확인하세요.
자주 묻는 질문
Go에서 if else는 어떻게 작성하나요?
조건을 괄호로 감싸지 않고, 중괄호는 항상 씁니다:
if x > 10 {
fmt.Println("big")
} else if x > 5 {
fmt.Println("medium")
} else {
fmt.Println("small")
}
else는 앞 블록의 닫는 중괄호와 같은 줄에 있어야 합니다.
Go에서 초기화 구문이 있는 if문이란 무엇인가요?
조건 앞에 세미콜론으로 구분한 짧은 문장을 두는 형태입니다: if n, err := strconv.Atoi(s); err != nil { ... }. 여기서 선언한 변수는 그 if와 else if, else 분기 안에서만 존재하므로 함수의 나머지 부분으로 새어 나가지 않습니다.
Go에서 한 줄짜리 if를 쓸 수 있나요?
중괄호 없이는 안 됩니다. if ok return과 if (ok) x = 1;은 문법 오류입니다. 가장 짧은 형태는 if ok { return }이고, gofmt는 본문을 별도의 줄로 옮깁니다. Go에는 삼항 연산자도 없으므로 조건에 따른 값은 if/else나 작은 헬퍼 함수로 만들어야 합니다.
Go는 왜 어디서나 if err != nil을 쓰나요?
Go에는 예외가 없습니다. 실패할 수 있는 함수는 마지막 결과로 error를 반환하고, 호출한 쪽은 바로 if err != nil로 확인합니다. 이 반복은 모든 실패 지점을 발생한 자리에서 보이게 하는 대가입니다.