Go의 조건문: if-else 및 고급 switch 사용법 심층 분석
Min-jun Kim
Dev Intern · Leapcell

조건문은 프로그래밍 언어의 기본적인 빌딩 블록으로, 프로그램이 결정을 내리고 다양한 조건에 따라 다른 코드 블록을 실행할 수 있도록 합니다. Go는 실용적이고 명확한 구문을 사용하여 if-else
및 switch
문을 통해 조건부 논리를 효과적으로 관리합니다. if-else
는 간단한 분기를 제공하는 반면, Go의 switch
문은 여러 if-else if
블록이 필요할 수 있는 복잡한 조건부 논리를 단순화하는 경우가 많습니다. 이 글에서는 두 구문 모두를 살펴보고, 특히 switch
의 고급 기능에 초점을 맞출 것입니다.
if-else
구문: 직관적인 의사 결정
Go의 if-else
문은 C계열 언어의 익숙한 패턴을 따르지만, 조건 주변의 괄호가 없다는 Go 고유의 특징이 있습니다.
기본 구조는 다음과 같습니다.
if condition { // condition이 참일 때 실행될 코드 } else { // condition이 거짓일 때 실행될 코드 }
Go는 여러 조건에 대해 else if
도 지원합니다.
if condition1 { // condition1이 참일 때 코드 } else if condition2 { // condition1이 거짓이고 condition2가 참일 때 코드 } else { // condition1과 condition2 모두 참이 아닐 때 코드 }
Go의 if
문에서 주목할 만한 기능은 조건 앞에 올 수 있는 *선택적 짧은 문장(short statement)*입니다. 이렇게 하면 if
및 else
블록에 지역적인 변수를 초기화할 수 있어 범위 제한과 더 깔끔한 코드를 촉진합니다.
예시: 짧은 문장을 사용한 if-else
사용자 점수가 특정 순위에 해당하는지 확인하고 싶다고 가정해 봅시다. if
문 자체 내에서 순위 임계값을 계산할 수 있습니다.
package main import "fmt" func main() { score := 75 if requiredScore := 70; score >= requiredScore { fmt.Printf("축하합니다! %d점은 Rank A의 요구 점수인 %d점을 충족합니다.\n", score, requiredScore) } else { fmt.Printf("계속 노력하세요! %d점은 Rank A의 요구 점수인 %d점보다 낮습니다.\n", score, requiredScore) } // `requiredScore`는 여기서 접근할 수 없습니다 // fmt.Println(requiredScore) // 컴파일 오류 발생 }
이 짧은 문장은 다중 값을 반환하는 함수, 일반적으로 선택적 결과와 오류를 처리할 때 특히 유용합니다.
package main import ( "fmt" "strconv" ) func main() { input := "123" if num, err := strconv.Atoi(input); err != nil { fmt.Printf("'%s' 변환 오류: %v\n", input, err) } else { fmt.Printf("'%s'를 정수 %d로 성공적으로 변환했습니다.\n", input, num) } input = "abc" if num, err := strconv.Atoi(input); err != nil { fmt.Printf("'%s' 변환 오류: %v\n", input, err) } else { fmt.Printf("'%s'를 정수 %d로 성공적으로 변환했습니다.\n", input, num) } }
오류 확인을 위한 이 관용구는 Go 프로그래밍 전반에 퍼져 있으며 명확한 오류 처리로 명성을 얻는 데 기여합니다.
switch
문: 우아한 다중 분기
Go의 switch
문은 특히 단일 표현식에 대한 여러 가능한 값 또는 복잡한 비상수 조건의 경우, if-else if
구문의 순차적인 대안으로 강력합니다.
기본 switch
사용법
기본 switch
문은 표현식을 평가한 다음 표현식의 값과 일치하는 첫 번째 case
와 관련된 코드 블록을 실행합니다. 다른 많은 언어와 달리 Go의 switch
는 기본적으로 각 case
블록 끝에 break
를 포함하므로 기본적으로 다음 case
로 "fall through"되지 않습니다.
package main import "fmt" func main() { day := "Wednesday" switch day { case "Monday": fmt.Println("한 주의 시작.") case "Friday": fmt.Println("거의 주말!") case "Saturday", "Sunday": // 단일 case에 여러 값 fmt.Println("주말!") default: // 다른 case와 일치하지 않는 경우 선택적 기본 case fmt.Println("주중 블루스 또는 기타 요일.") } }
고급 switch
기능
1. 표현식이 없는 switch
(태그 없는 switch
)
switch
의 가장 다재다능한 형태 중 하나는 switch
키워드 뒤에 표현식이 없는 "태그 없는 switch"입니다. 이 모드에서는 각 case
문이 부울 표현식으로 취급되며, 참으로 평가되는 첫 번째 case
가 실행됩니다. 이는 if-else if-else
체인과 동일하지만 종종 더 읽기 쉽습니다.
예시: 성적 계산
package main import "fmt" func main() { score := 85 switch { // 여기에 표현식이 없음 case score >= 90: fmt.Println("등급: A") case score >= 80: fmt.Println("등급: B") case score >= 70: fmt.Println("등급: C") case score >= 60: fmt.Println("등급: D") default: fmt.Println("등급: F") } }
이 태그 없는 switch
는 다양한 범위 또는 조건 조합이 결과를 결정하는 복잡한 조건부 논리에 매우 강력합니다.
2. 짧은 문장을 사용한 switch
if
와 유사하게 switch
문은 표현식 앞(또는 태그 없는 switch의 첫 번째 case
앞)에 선택적 짧은 문장을 포함할 수도 있습니다. 이는 변수를 지역화하는 데 도움이 됩니다.
예시: 입력의 길이 및 타입 확인
package main import "fmt" func processInput(input string) { switch l := len(input); { // 짧은 문장 `l := len(input)` case l == 0: fmt.Println("입력이 비어 있습니다.") case l > 0 && l < 5: fmt.Printf("입력 '%s'은(는) 짧습니다 (길이 %d).\n", input, l) case l >= 5 && l < 10: fmt.Printf("입력 '%s'은(는) 중간입니다 (길이 %d).\n", input, l) default: fmt.Printf("입력 '%s'은(는) 깁니다 (길이 %d).\n", input, l) } } func main() { processInput("") processInput("Go") processInput("Golang") processInput("Programming") }
3. fallthrough
문
Go의 switch
는 각 case
후에 암묵적으로 break
하지만, fallthrough
키워드를 사용하여 다음 case
로 실행이 "fall through"하도록 명시적으로 강제할 수 있습니다. 이는 덜 일반적이지만, 일부 작업이 겹치는 특정 시나리오에서는 유용할 수 있습니다.
중요 참고 사항: fallthrough
는 바로 다음 case
로 제어 흐름만 전달합니다. 다음 case
의 조건은 다시 평가되지 않습니다.
예시: 서비스 수준 계산
고객 서비스 등급이 계층화된 시스템을 상상해 봅시다. 고객이 Platinum이면 Gold 및 Silver의 혜택도 받습니다.
package main import "fmt" func main() { customerTier := "Platinum" fmt.Printf("고객 등급: %s\n", customerTier) fmt.Println("혜택:") switch customerTier { case "Platinum": fmt.Println("- 전담 계정 관리자") fallthrough case "Gold": fmt.Println("- 우선 지원 라인") fallthrough case "Silver": fmt.Println("- 독점 할인") default: fmt.Println("- 표준 지원") } }
출력:
고객 등급: Platinum
혜택:
- 전담 계정 관리자
- 우선 지원 라인
- 독점 할인
customerTier
가 "Gold"였다면 "전담 계정 관리자"는 인쇄되지 않고 "우선 지원 라인"과 "독점 할인"은 인쇄됩니다. 이는 fallthrough
가 실행 흐름에 대한 세밀한 제어를 제공하는 방법을 보여줍니다.
4. 타입 스위치 (switch
on types)
Go에서 switch
의 가장 강력하고 관용적인 용도 중 하나는 "타입 스위치"입니다. 이를 통해 인터페이스 값의 구체적인 타입을 확인하고 해당 타입에 따라 다른 코드를 실행할 수 있습니다. 이는 어떤 타입의 값이든 저장할 수 있는 Go의 interface{}
(빈 인터페이스)를 다룰 때 중요합니다.
타입 스위치의 구문은 .(type)
을 사용합니다.
switch variable.(type) { case Type1: // variable이 Type1인 경우 실행될 코드 case Type2: // variable이 Type2인 경우 실행될 코드 default: // 위의 타입이 일치하지 않을 경우 코드 }
타입 스위치의 case
블록 내에서 해당 case
에 의해 단언된 구체적인 타입을 갖게 될 새 변수(또는 이름이 같은 경우 기존 변수를 재사용)를 선언할 수 있습니다.
예시: 혼합 데이터 타입 처리
package main import "fmt" func processData(data interface{}) { switch v := data.(type) { // `v`는 case 블록 내에서 구체적인 타입을 가집니다 case int: fmt.Printf("정수 수신: %d. 값의 두 배는 %d입니다.\n", v, v*2) case string: fmt.Printf("문자열 수신: '%s'. 길이: %d.\n", v, len(v)) case bool: fmt.Printf("불리언 수신: %t.\n", v) case float64: fmt.Printf("부동소수점 수신: %.2f. 두 배: %.2f.\n", v, v*2) default: fmt.Printf("다른 것 수신: %T (%v).\n", v, v) } } func main() { processData(10) processData("Hello, Go!") processData(true) processData(3.14159) processData([]int{1, 2, 3}) processData(nil) }
출력:
정수 수신: 10. 값의 두 배는 20입니다.
문자열 수신: 'Hello, Go!'. 길이: 11.
불리언 수신: true.
부동소수점 수신: 3.14. 두 배: 6.28.
다른 것 수신: []int ([1 2 3]).
다른 것 수신: <nil> (<nil>).
타입 스위치는 다음과 같은 작업에 매우 유용합니다.
- 범용 포맷(예: JSON, XML)에서 특정 Go 타입으로 데이터를 역직렬화합니다.
- 공통 인터페이스 메소드를 공유하지 않는 객체에 대해 다형적 동작을 구현합니다(인터페이스는 일반적으로 이를 위해 선호됨).
- 다양한 타입의 이벤트 또는 메시지를 처리합니다.
if-else
와 switch
선택하기
if-else
와 switch
의 선택은 종종 가독성과 조건의 특성에 따라 달라집니다.
if-else
: 이진 분기 또는 조건이 서로 매우 종속적이고 순차적인 방식으로 이루어질 때, 그리고 아마도 특정case
값에 깔끔하게 맞지 않는 복잡한 부울 논리를 포함할 때if-else
를 선호하십시오.switch
(기본): 단일 표현식을 여러 특정 값과 비교하려는 경우에 이상적입니다. 이 목적을 위해서는 긴if-else if
체인보다 종종 더 깔끔하고 간결합니다.switch
(태그 없는): 여러 개의 상호 배타적이지 않은 조건을 처리하는 데 탁월하며, 특히 범위 또는 더 복잡한 부울 표현식을 다룰 때 그렇습니다. 종종 연쇄적인if-else if
블록보다 더 깔끔하게 읽힙니다.switch
(타입 스위치): 인터페이스 값의 구체적인 타입을 동적으로 결정하고 이에 따라 동작하는 유일한 방법입니다. 이것은 독특하고 강력한 Go 관용구입니다.
결론
Go의 조건문인 if-else
와 switch
는 프로그램 흐름을 제어하는 강력한 도구를 제공합니다. if-else
는 간단한 이진 분기와 짧은 문장 변수 초기화를 제공하는 반면, Go의 switch
문은 그 유연성으로 두드러집니다. 태그 없는 다중 조건 분기, 내장된 break
동작, 명시적인 fallthrough
, 그리고 특히 강력한 타입 스위치 기능으로 작동할 수 있는 능력은 이를 매우 다재다능한 구문으로 만듭니다. 이러한 기능들을 마스터하면 더 간결하고 읽기 쉬우며 관용적인 Go 코드를 작성할 수 있게 될 것입니다.