Go (2) - If문, switch문, for문

If 문

 

if문은 조건에 따라 분기하는 구문입니다.

if 조건문 {
    문장
} else if 조건문 {
    문장
} else {
    문장
}

if 초기문; 조건문 {
    문장
}

 

두 번째 if문과 같이 조건을 검사하기 전에 초기문을 넣을 수 있습니다. 초기문은 검사에 사용할 변수를 초기화할 때 주로 사용하며, 초기문에서 선언한 변수의 범위는 if문 안으로 한정됩니다.

 

package main

func getMyAge() int {
    return 25
}

func main() {
    if age := getMyAge(); age > 20 {
    	문장
    }
}

 

쇼트 서킷

 

조건문에서 논리 연산자를 사용할 때 && 연산은 좌변이 false이면 우변을 검사하지 않고 false 처리를 하고, || 연산은 좌변이 true이면 우변은 검사하지 않고 true처리를 하는데 이를 쇼트서킷(short-circuit)이라고 합니다. 따라서 조건문의 우변이 실행되지 않을 수도 있으므로 이를 염두에 두고 코드를 구현해야 합니다.

package main

import "fmt"

func BoolFunc() boolean {
	// 문장
}

func main() {
    if false && BoolFunc() {
    	// 문장
    }
}

 

위 코드의 조건문을 보면 && 연산자를 사용했는데 좌변이 이미 false이기 때문에 우변의 BoolFunc() 함수는 실행되지 않고 false 처리를 합니다.

 

 

switch문

 

switch문은 값에 따라 다른 로직을 수행할 때 사용하는 구문입니다.

복잡한 if문의 경우 switch문을 사용하면 더 가독성 좋고 깔끔하게 정리할 수 있습니다.

switch 비굣값 {
case 값1:
    문장
case 값2:
    문장
default:
    문장
}

switch 초기문; 비굣값 {
case 값1:
    문장
case 값2:
    문장
default:
    문장
}

 

일반적으로 Go의 switch문에서는 case를 들여쓰기 하지 않습니다. 또한 if문과 마찬가지로 switch문에서도 초기문을 넣을 수 있습니다.

 

다양한 switch문 형태

 

1. 한 번에 여러 값 비교

package main

func main() {
    day := "Mon"
    
    switch day {
    case "Mon", "Tue":
    	문장
    case "Wed", "Thu", "Fri":
    	문장
    }
}

 

2. 조건문 비교

package main

func main() {
    temp := 20
    
    switch true {
    case temp < 10, temp >30:
    	문장
    case temp >= 15 && temp < 25:
    	문장
    default:
    	문장
    }
    
    switch {
    	...
    }
}
switch 다음에 비굣값을 적지 않는 경우 default값으로 true를 사용합니다.

 

break와 fallthrough 키워드

 

일반적으로 다른 언어에서는 switch문의 각 case 종료 시에 break 키워드를 사용해야 다음 case로 코드가 이어서 실행되지 않습니다. 하지만 Go 언어에서는 break를 사용하지 않아도 case 하나를 실행 후 자동으로 switch문을 빠져나가게 됩니다. 물론 명시적으로 break를 사용하여 switch문을 종료해도 됩니다.

 

그런데 만약 하나의 case를 실행 후 다음 case까지 이어서 실행하고 싶을 때에는 fallthrough 키워드를 사용하면 됩니다.

package main

func main() {
    a := 3
    
    switch a {
    case 1:
        문장
    case 2:
        문장
        break
    case 3:
        문장
        fallthrough
    case 4:
        문장
    default:
        문장
    }
}

 

 

for문

 

for문은 반복 작업을 수행할 때 사용하는 구문입니다.

for 초기문; 조건문; 후처리 {
    문장
}

 

for문이 실행될 때 초기문이 먼저 실행됩니다. 그리고 조건문을 검사합니다. 만약 조건문의 결과가 true이면 for문 안쪽의 코드를 실행합니다. 그리고 후처리 구문을 실행합니다. 그리고 이 과정을 조건문이 false가 되기 전까지 반복합니다.

 

다양한 for문 형태

 

1. 초기문 생략

for ; 조건문; 후처리 {
    문장
}

 

초기문을 생략하더라고 ; 를 붙여 조건문 자리를 표시해줘야 합니다.

 

2. 후처리 생략

for 초기문; 조건문; {
    문장
}

 

후처리를 생략하더라도 조건문 뒤에 ; 를 붙여줘야 합니다.

 

3. 초기문, 후처리 생략

for ; 조건문; {
    문장
}

for 조건문 {
    문장
}

 

초기문과 후처리를 모두 생략하는 경우에는 ; 를 생락할 수 있습니다.

 

4. 무한 루프

for true {
    문장
}

for {
    문장
}

 

조건문이 true이면 반복문이 무한이 실행되는 무한 루프가 됩니다. 무한 루프는 조건문과 break를 사용해 종료 시점을 설정해주지 않으면 무한히 실행되기 때문에 주의해야 합니다. 

switch문과 동일하게 조건문을 생략하면 default값으로 true를 사용하여 무한 루프가 됩니다.

 

continue와 break 키워드

 

continue와 break는 반복문을 제어하는 키워드입니다. continue는 이후 코드 블록을 수행하지 않고 후처리로 건너뛰고, break는 for문에서 곧바로 빠져 나옵니다.

for i : 0; i < 10; i++ {
    if i == 3 {
    	continue
    }
    if i == 6 {
    	break
    }
}

 

중첩 for문과 레이블

 

for문 안에서 또 for문을 사용하는 중첩 for문을 사용할 경우 break를 사용하면 break가 속한 for문만 빠져나옵니다. 중첩 for문은 사용된 for문의 개수만큼 break를 사용해야합니다. 이때 레이블을 사용하면 중첩된 모든 for문을 한 번에 빠져나올 있습니다.

package main

func main() {
   a := 1
   b := 1
   
OuterFor:
    for ; a <= 9; b++ {
        for b = 1; b <= 9; b++ {
            if a*b == 45 {
                break OuterFor
            }
        }
    }
}

 

위 코드와 같이 레이블을 사용하는 방법은 편리할 수 있으나 혼동을 불러일으킬 수 있고 자칫 잘못 사용하면 예기치 못한 버그가 발생할 수 있습니다. 그래서 되도록이면 for문 밖에 boolean 타입의 플래그(flag) 변수를 선언하고 이 값을 기준으로 중첩된 for문을 종료하는 것을 권장합니다.

 

더 나아가 클린 코드를 지향하려면 중첩된 내부 로직을 함수로 묶어 중첩을 줄이는 것이 좋습니다.

package main

func find45(a int) (int bool) {
    for b : = 1; b <= 9; b++ {
        if a*b == 45 {
            return b, true
        }
    }
    return 0, false
}

func main() {
    a := 1
    b := 0

    for ; a <= 9; a++ {
        var found bool		// flag 변수
        if b, found = find45(a); found {
            break
        }
    }
}