Go에는 while 키워드가 없습니다. for 뒤에 조건을 쓰면 그게 while 반복문입니다:
조건은 매 반복 전에 검사되므로, 처음부터 거짓이면 본문은 한 번도 실행되지 않습니다. C, Java, JavaScript의 while (balance < 2000)과 같고, 괄호와 키워드만 빠졌습니다. Go 설계자들은 모든 반복 형태에 키워드 하나만 쓰기로 했습니다. 네 가지 형태는 for 반복문 페이지에서 볼 수 있습니다.
while(true): 무한 루프
조건을 아예 빼면, 안에서 무언가가 끝낼 때까지 반복이 계속됩니다:
관용적인 표기는 for { }입니다. for true { }도 컴파일되지만 다른 언어에서 온 사람이 쓴 코드처럼 읽힙니다.
무한 루프를 끝내는 방법은 네 가지입니다. break(반복문을 빠져나감), return(함수를 빠져나감), 패닉, 그리고 os.Exit입니다. main이 이 중 아무것도 없는 for {}에 머무는 프로그램은 강제로 종료될 때까지 실행되며, 서버나 워커라면 바로 그렇게 동작해야 합니다.
do-while
do-while은 조건을 검사하기 전에 본문을 한 번 실행합니다. Go에는 전용 문법이 없습니다. 무한 루프의 끝에 검사를 두면 됩니다:
본문은 무슨 일이 있어도 최소 한 번은 실행되고, 이것이 do-while을 정의하는 성질입니다. 이 예제의 난수 소스는 고정된 시드를 써서 실행할 때마다 같은 결과가 나옵니다. 진짜 무작위 값이 필요하면 시드를 지정한 소스 없이 rand.IntN을 쓰세요.
첫 번째 반복을 강제로 통과시켜 조건을 헤더에 남기는 두 번째 형태도 있습니다:
for first := true; first || condition(); first = false {
// body
}
동작은 하지만, 끝에 break가 있는 무한 루프가 더 읽기 쉽고 대부분의 Go 코드도 그렇게 씁니다.
끝날 때까지 읽기
실제 Go 코드에서 가장 흔한 while 반복문은 입력이 떨어질 때까지 읽는 것입니다. bufio.Scanner가 바로 이 용도로 만들어졌습니다. Scan은 입력이 끝나거나 오류가 나면 false를 반환하므로 그대로 반복 조건이 됩니다:
strings.NewReader(input)를 os.Stdin으로 바꾸면 같은 반복문이 사용자 입력을 한 줄씩 읽습니다. 반복이 끝난 뒤 scanner.Err()를 확인하세요. Scan이 false를 반환했다는 것만으로는 입력이 정상적으로 끝났는지 실패했는지 알 수 없습니다.
break와 continue
둘 다 모든 형태의 for에서 동작합니다:
조건만 있는 반복문에서 continue는 곧바로 조건으로 건너뜁니다. 그래서 미묘한 버그가 생기기 쉽습니다. 카운터를 본문 맨 아래에서 갱신하면, 그보다 위에 있는 continue가 갱신을 건너뛰어 반복이 끝나지 않습니다. 위 예제처럼 카운터를 맨 위에서 갱신하거나, continue 뒤에도 후처리 문장이 실행되는 세 절짜리 for를 쓰세요.
무언가를 기다리기
조건을 기다리는 반복문은 헛돌지 말고 블록되거나 잠들어야 합니다:
// Wrong: burns a CPU core while waiting
for !ready {
}
// Better: poll with a delay
for !isReady() {
time.Sleep(100 * time.Millisecond)
}
다른 고루틴이 쓰는 일반 변수를 폴링하는 것은 데이터 레이스이기도 합니다. 고루틴 사이에서는 채널, sync.WaitGroup, sync.Cond로 기다리거나 타이머와 함께 select를 쓰세요. 횟수 제한이 있는 재시도 반복문은 영원히 돌 수 없도록 횟수를 세는 for가 낫습니다:
for attempt := 1; attempt <= 5; attempt++ {
if err := connect(); err == nil {
break
}
time.Sleep(time.Duration(attempt) * 200 * time.Millisecond)
}
흔한 실수
- 조건 변수를 바꾸는 것을 잊음.
for i < 10 { fmt.Println(i) }는 끝나지 않습니다. 모든 while 반복문에는 본문 안에 종료 쪽으로 움직이게 하는 무언가가 있어야 합니다. while을 씀.while x < 5 {}는syntax error: unexpected name x at end of statement를 냅니다.while은 키워드가 아니라서 컴파일러가 평범한 이름으로 읽기 때문입니다.- 습관적인 괄호.
for (x < 5) {}는 컴파일되고,gofmt가 괄호를 지웁니다. - 반복문 안에서 변수 선언.
for n := 10; n > 0 {}는 문법 오류입니다. 초기화 절이 있는 반복문은 세 절이 모두 필요합니다.n을 반복문 앞에서 선언하거나 세 절 형태를 온전히 쓰세요.
자주 묻는 질문
Go에 while 반복문이 있나요?
키워드로는 없습니다. Go는 모든 반복문에 for를 쓰고, 조건만 있는 for가 정확히 while 반복문입니다:
for count < 10 {
count++
}
조건은 매 반복 전에 검사되며, C나 Java의 while (count < 10)과 똑같습니다.
Go에서 while(true)는 어떻게 작성하나요?
뒤에 아무것도 없는 for를 씁니다: for { ... }. break, return, 패닉, os.Exit 중 하나가 끝낼 때까지 반복합니다. for true { ... }도 컴파일되지만 관용적인 형태는 for { }입니다.
Go에서 do-while 반복문은 어떻게 작성하나요?
무한 루프를 쓰고 조건 검사를 본문 끝에 둡니다:
for {
// body runs at least once
if !condition {
break
}
}
조건을 검사하기 전에 본문이 항상 한 번은 실행되며, 이것이 do-while의 의미입니다.