switch는 값 하나를 case 목록과 비교해 처음 일치하는 것을 실행합니다. C, Java, JavaScript와 달리 Go의 case는 다음 case로 넘어가지 않으므로, 잊어버릴 break도 없습니다.
case는 위에서 아래로 검사되며, 처음 일치하는 case만 실행됩니다. default는 아무것도 일치하지 않을 때 실행됩니다. 선택 사항이고 목록 어디에나 둘 수 있지만, 관례상 마지막에 둡니다.
case 하나에 여러 값
case "sat", "sun":은 둘 중 어느 값과도 일치합니다. C에서 빈 case를 쌓아 하던 일을 Go는 이렇게 표현합니다. 비교 가능한 타입이라면 무엇이든 됩니다. 문자열, 숫자, 룬, 불리언, 포인터, 그리고 열거형 같은 이름 있는 타입도 가능합니다:
같은 상수 값을 가진 case가 둘이면 컴파일 오류입니다:
./main.go:10:7: duplicate case 1 (constant of type int) in expression switch
./main.go:8:7: previous case
조건 없는 switch
표현식을 빼면 각 case가 불리언 검사가 됩니다. 긴 if/else if 체인을 Go답게 더 깔끔하게 쓰는 형태입니다:
switch {는 switch true {의 줄임말입니다. 처음으로 참인 case가 이기므로 순서가 중요합니다. bmi < 25는 bmi < 18.5가 거짓일 때만 도달하므로, 각 case는 위의 case들이 실패했다고 가정할 수 있습니다.
초기화 구문이 있는 switch
if처럼 switch도 짧은 문장으로 시작할 수 있습니다. 거기서 선언한 변수의 스코프는 switch로 한정됩니다:
초기화 구문은 조건 없는 switch와 함께 쓸 수도 있습니다: switch n := len(items); { case n == 0: ... }.
fallthrough
정말로 다음 case로 이어 가고 싶다면 case의 마지막 문장으로 fallthrough를 씁니다. 다음 case의 조건을 평가하지 않고 그 본문으로 제어를 넘깁니다:
레벨 2는 write를 출력한 다음 read를 출력하며, 권한이 아래로 누적됩니다. 뒤쪽 case의 조건은 검사되지 않습니다. case 2에서 fallthrough한 뒤에는 level이 2인데도 case 1이 실행됩니다.
fallthrough 규칙:
- case의 마지막 문장이어야 합니다.
- 마지막 case에는 쓸 수 없습니다:
cannot fallthrough final case in switch. - 타입 스위치에서는 허용되지 않습니다.
실제 Go 코드에서 fallthrough는 드뭅니다. case당 여러 값으로 흔한 필요는 해결되고, fallthrough를 연쇄하는 것보다 함수를 명시적으로 호출하는 편이 보통 더 명확합니다.
switch 안의 break
case 안의 break는 switch를 빠져나갑니다. case는 알아서 끝나므로 case를 일찍 벗어날 때만 필요합니다. 함정은 반복문 안의 switch입니다:
loop 레이블이 없으면 break는 switch를 끝내고 반복문은 "c"로 계속 진행합니다. 반면 continue는 switch가 반복문이 아니므로 항상 감싸는 반복문을 가리킵니다.
타입으로 switch하기
타입 스위치는 특별한 형태 v.(type)을 써서 인터페이스 값의 동적 타입에 따라 분기합니다:
타입이 하나인 case에서 x는 그 타입을 가집니다(string case에서 len(x)가 동작합니다). 여러 타입을 나열한 case에서 x는 인터페이스 타입을 유지합니다. 타입 스위치와 v.(T) 단언은 타입 단언 페이지에서 자세히 다룹니다.
Go의 switch가 다르게 하는 것들
| 동작 | C, Java, JavaScript | Go |
|---|---|---|
| 다음 case로 넘어가기 | 기본 동작 | fallthrough로만 |
각 case 끝의 break | 필수 | 불필요 |
| case당 여러 값 | 빈 case 쌓기 | case a, b, c: |
| case 값 | (대부분) 상수 | 어떤 표현식이든, 위에서 아래로 평가 |
| switch 값 | 정수 타입(C) | 비교 가능한 모든 타입 |
| switch 표현식 없음 | 불가 | switch { case cond: } |
case 표현식은 상수일 필요가 없습니다. case limit(), max + 1:도 문법상 맞습니다. 하나가 일치할 때까지 순서대로 평가되므로 뒤쪽 표현식은 실행되지 않을 수도 있습니다.
모든 경우를 다루는지 검사
Go는 열거형에 대한 switch가 모든 값을 다루는지 확인하지 않습니다. 예상하지 못한 값에 대해 로그를 남기거나, 오류를 반환하거나, 패닉을 일으키는 default를 추가하세요. 또는 exhaustive 린터(golangci-lint에 포함)를 써서 빠진 case를 빌드할 때 보고받을 수 있습니다.
자주 묻는 질문
Go의 switch는 다음 case로 넘어가나요?
아니요. Go의 case는 다음 case에서 자동으로 끝나며, 멈추려고 break를 쓸 일이 없습니다. 다음 case의 본문으로 실행을 이어 가고 싶다면 case의 마지막 문장으로 fallthrough를 씁니다. 다음 case의 조건을 확인하지 않고 무조건 넘어갑니다.
Go에서 case 하나로 여러 값을 매칭하려면 어떻게 하나요?
쉼표로 구분해 나열합니다: case "sat", "sun":. switch 값이 그중 하나와 같으면 case가 실행됩니다. C나 Java에서 빈 case를 쌓아 넘어가게 하던 방식을 대신합니다.
Go에서 조건 없는 switch란 무엇인가요?
switch { case x < 0: ...; case x == 0: ...; default: ... }. switch 뒤에 표현식이 없으면 각 case가 불리언 조건이 되고, 처음으로 참인 case가 실행됩니다. 긴 if/else if 체인을 대신하는 관용적인 형태입니다.
Go의 switch 안에서 break는 무엇을 하나요?
감싸는 for 반복문이 아니라 switch를 끝냅니다. case는 알아서 끝나므로 필요한 경우는 드물지만, 반복문 안의 switch에서 반복문을 빠져나오려고 break를 쓴 사람은 놀라게 됩니다. 그럴 때는 레이블이 붙은 break나 return을 쓰세요.