여러가지 형태의 for 사용법 및 레이블로 빠져나가기

Go 에는 while 루프가 없기 때문에, 사실상 for 를 사용해 while 처럼 동작하게 해야 한다.

for문에 들어갈 초기문, 조건문, 후처리문에 대해 생략 가능하게 만들어져있기 때문에 다양한 방식으로 활용이 가능하다.

아래는 가장 기본적인 for문의 형태이다.

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

아래처럼 반복에 들어가기 전에 한번 실행하는 초기문을 생략할 수 있으며, 생략한다고 하더라도 문장들을 구분해주는 ;를 빼먹는것은 안된다.

for ; 조건문 ; 후처리문 {
    // statements
}

초기문 뿐만 아니라 후처리 하는 문장도 생략 가능하다.

for 초기문 ; 조건문 ; {
    // statements
}

사실상 ; 조건문 ; 만 들어가 있을 경우 앞뒤에 뭐가 들어오든 상관 없다고 볼 수 있으며, 실제로 아래처럼 쓸 수도 있으며 while 문과 비슷한 형태가 된다.

for ; 조건문 ; {
    //statements
}

조건문만 넣는 경우에는 ;를 모두 없애고 사용할 수도 있다.

for 조건문 {
    //statements
}

조건문을 생략할 경우에는 while True 처럼 무한루프가 된다.

for {
    //statements
}


일반적으로 하나의 for 문을 빠져나가기 위해서는 break 을 사용한다.

그러나 중첩 for문을 한번에 빠져나가는 것은 지원되지 않기 때문에, 간단하게 플래그로써 사용할 bool 변수 하나를 두고 해당 플래그를 검사해 반복적으로 break 해나가는 방법을 사용하기도 한다.

파이썬 같은 경우에는 for-else 문 같은 것이 존재하기도 하는데, Go 에서는 특정 for 문에 해당하는 레이블을 지정하고 해당 레이블까지 break 이 가능하다.

for문을 시작하기 전에 해당 반복문의 레이블을 지정해 두고, break [레이블명]과 같이 사용할 경우, 해당 for 문까지 빠져나오게 된다.

레이블은 for문 위에다가 레이블명에 콜론을 붙여 정의하며, 예를 들어 아래의 경우 이중포문을 돌리다가 i = j = 1 인 상황에서 break ForBreak을 통해 i 와 관련된 for문 까지 같이 종료시킨다.

func main() {
	ForBreak:
	for i := 0 ; i < 3 ; i++ {
		for j := 0 ; j < 3 ; j++ {
			if i == 1 && j == 1 {
				break ForBreak
			}
			fmt.Println(i, j)
		}
	}
}
0 0
0 1
0 2
1 0

레이블을 여러개 둠으로써 더 많은 중첩 속에서 필요에 맞게 break 할 수 있다.

func main() {
	cnt := 0

	Pbreak:
	for p := 0 ; p < 3 ; p++ {
		for q := 0 ; q < 3 ; q++ {
			if cnt == 10 {
				break Pbreak
			}
			Rbreak:
			for r := 0 ; r < 3 ; r++ {
				for c := 0 ; c < 3 ; c++ {
					if r == 0 && c == 2 {
						break Rbreak
					}
					cnt++
				}
			}
		}
	}
}

레이블은 버그를 발생시키는 원인이 되기도 하므로 권장하는 방법도 아니지만, 단순 로직을 짤 때 편리하긴 하다.

그래서 권장되는 방법으로는 반복문을 중첩시키다가 break 로 빠져나가는 것이 아닌, 잘라낼 수 있는 부분에 대해서는 따로 함수로 정의하여 그 안에서 return 하는 방식이 깔끔하다.