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 코드를 작성할 수 있게 될 것입니다.