Go의 제어문은 C나 Java와 비슷해 보이지만 문법과 기본 동작에는 차이가 있습니다.
if, for, switch의 조건에는 일반적으로 괄호를 사용하지 않으며, 실행할 본문은 중괄호로 감싸야 합니다. Go에는 while 키워드가 없으므로 조건 반복도 for로 작성합니다.
또한 Go의 switch는 일치하는 case를 실행한 뒤 자동으로 종료됩니다. 따라서 각 case 끝에 break를 반복해서 작성할 필요가 없습니다. break는 반복이나 제어문을 즉시 종료할 때 사용하고, continue는 현재 반복의 남은 코드를 건너뛰고 다음 반복으로 진행할 때 사용합니다.
핵심 정리
| 구문 | 역할 |
|---|---|
if |
조건에 따라 코드를 실행 |
for |
Go에서 사용하는 유일한 반복문 키워드 |
for condition |
다른 언어의 while (condition)과 같은 조건 반복 |
switch |
일치하는 case 하나를 실행한 뒤 자동 종료 |
break |
가장 가까운 for, switch, select를 즉시 종료 |
continue |
현재 for 반복의 남은 코드를 건너뛰고 다음 반복으로 이동 |
fallthrough |
다음 case의 조건을 확인하지 않고 본문을 이어서 실행 |
디렉터리 구조는 다음과 같이 구성합니다.
sources/
└── control-flow/
└── main.gosources 디렉터리에서 실행합니다.
cd sources
go run ./control-flow
Go의 일반적인
switch는 자동으로 다음case로 넘어가지 않습니다. 각case끝에break를 습관적으로 작성할 필요가 없습니다.
if와 for
if 조건문
Go에서는 조건식의 바깥 괄호를 생략하는 방식이 일반적입니다.
package main
import "fmt"
func main() {
age := 20
if age >= 19 {
fmt.Println("성인입니다.")
} else {
fmt.Println("미성년자입니다.")
}
}본문 중괄호는 필수이며, 여는 중괄호는 조건식과 같은 줄에 작성해야 합니다.
if에는 조건을 검사하기 전에 실행할 간단한 초기화문도 작성할 수 있습니다.
if score := 85; score >= 80 {
fmt.Println("합격입니다.")
}여기서 score는 해당 if와 연결된 else 범위 안에서만 사용할 수 있습니다.
기본 for 반복문
Go에는 while이나 do-while 키워드가 없습니다. 반복은 모두 for로 작성합니다.
for i := 1; i <= 3; i++ {
fmt.Println(i)
}실행 결과:
1
2
3while 형태의 조건 반복
조건식만 작성하면 다른 언어의 while과 같은 형태가 됩니다.
count := 1
for count <= 3 {
fmt.Println(count)
count++
}무한 반복
조건을 생략하면 무한 반복이 됩니다.
for {
fmt.Println("계속 실행됩니다.")
}무한 반복은 서버의 작업 처리 루프, 메시지 수신, 재시도 등에 사용할 수 있습니다. 실제 코드에서는 break, return, 채널 종료, context 취소 등 명확한 종료 방법이 필요합니다.
switch와 자동 종료
Go의 switch는 일치하는 case를 실행한 뒤 자동으로 종료됩니다.
package main
import "fmt"
func main() {
day := 2
switch day {
case 1:
fmt.Println("월요일")
case 2:
fmt.Println("화요일")
case 3:
fmt.Println("수요일")
default:
fmt.Println("알 수 없는 요일")
}
}실행 결과:
화요일case 2가 실행된 뒤 case 3은 실행되지 않습니다.
여러 값을 하나의 case에서 처리할 수도 있습니다.
switch day {
case "토요일", "일요일":
fmt.Println("주말입니다.")
default:
fmt.Println("평일입니다.")
}조건식이 없는 switch는 여러 개의 if-else if를 정리할 때 사용할 수 있습니다.
score := 85
switch {
case score >= 90:
fmt.Println("A")
case score >= 80:
fmt.Println("B")
case score >= 70:
fmt.Println("C")
default:
fmt.Println("F")
}첫 번째로 참이 된 case만 실행됩니다.
다음 case 본문까지 이어서 실행하려면 fallthrough를 명시해야 합니다.
level := 1
switch level {
case 1:
fmt.Println("기본 권한")
fallthrough
case 2:
fmt.Println("추가 권한")
}실행 결과:
기본 권한
추가 권한fallthrough는 다음 case의 조건을 검사하지 않습니다. 코드 흐름을 이해하기 어려워질 수 있으므로 꼭 필요한 경우에만 사용하는 것이 좋습니다.
break와 continue
break: 반복문 전체 종료
break는 현재 실행 중인 가장 가까운 for, switch, select를 즉시 종료합니다.
원하는 값을 찾은 뒤 반복할 필요가 없다면 다음처럼 사용합니다.
numbers := []int{3, 7, 10, 15}
for _, number := range numbers {
if number == 10 {
fmt.Println("10을 찾았습니다.")
break
}
fmt.Println("확인:", number)
}실행 결과:
확인: 3
확인: 7
10을 찾았습니다.break가 실행되면 15는 검사하지 않고 반복문이 끝납니다.
무한 반복을 끝낼 때도 사용할 수 있습니다.
count := 1
for {
fmt.Println(count)
if count == 3 {
break
}
count++
}
fmt.Println("반복 종료")실행 결과:
1
2
3
반복 종료switch에서 break가 필요한 경우
Go의 switch는 각 case가 자동 종료되므로 일반적인 case 마지막에는 break가 필요 없습니다.
다만 하나의 case 본문을 실행하는 도중 나머지 처리를 중단하고 switch 밖으로 나가려면 사용할 수 있습니다.
status := "processing"
hasError := true
switch status {
case "processing":
fmt.Println("처리 상태 확인")
if hasError {
fmt.Println("오류가 있어 후속 처리를 생략합니다.")
break
}
fmt.Println("후속 처리를 실행합니다.")
default:
fmt.Println("다른 상태입니다.")
}
fmt.Println("switch 이후 코드")break는 switch만 종료합니다. 함수 전체를 종료하려면 return을 사용해야 합니다.
continue: 현재 반복만 건너뛰기
continue는 반복문 전체를 끝내지 않습니다. 현재 반복에서 continue 아래에 있는 코드를 건너뛰고 다음 반복으로 이동합니다.
for i := 1; i <= 5; i++ {
if i == 3 {
continue
}
fmt.Println(i)
}실행 결과:
1
2
4
5i == 3인 반복만 건너뛰며, 이후 반복은 계속 실행됩니다.
조건에 맞지 않는 데이터를 제외할 때 유용합니다.
scores := []int{90, -1, 75, -1, 82}
for _, score := range scores {
if score < 0 {
continue
}
fmt.Println("유효 점수:", score)
}실행 결과:
유효 점수: 90
유효 점수: 75
유효 점수: 82이처럼 예외 조건을 먼저 제외하면 정상 처리 코드의 중첩을 줄일 수 있습니다.
break와 continue 비교
for i := 1; i <= 5; i++ {
if i == 2 {
continue
}
if i == 4 {
break
}
fmt.Println(i)
}실행 결과:
1
3동작 순서는 다음과 같습니다.
| 조건 | 동작 |
|---|---|
i == 2 |
현재 반복의 출력만 생략하고 i == 3으로 진행 |
i == 4 |
반복문 자체를 종료 |
continue 이후 반복 후 실행문
일반적인 for 초기화문; 조건식; 반복 후 실행문 형태에서 continue가 실행되면 반복 후 실행문이 수행된 뒤 조건을 다시 검사합니다.
for i := 0; i < 4; i++ {
if i == 1 {
continue
}
fmt.Println(i)
}i == 1에서 출력은 생략되지만 i++는 실행되므로 반복이 정상적으로 진행됩니다.
반면 조건식만 사용하는 반복에서는 증가나 상태 변경을 직접 작성해야 합니다. continue 전에 상태를 변경하지 않으면 무한 반복이 발생할 수 있습니다.
count := 0
for count < 3 {
count++
if count == 2 {
continue
}
fmt.Println(count)
}이 예제는 continue보다 먼저 count++를 실행하므로 정상 종료됩니다.
조건식만 사용하는
for에서continue를 사용할 때는 반복 조건에 영향을 주는 값이 실제로 변경되는지 확인해야 합니다.
중첩 반복문과 라벨
라벨 없는 break와 continue는 가장 가까운 반복문에만 적용됩니다.
for i := 1; i <= 2; i++ {
for j := 1; j <= 3; j++ {
if j == 2 {
continue
}
fmt.Println(i, j)
}
}위 continue는 안쪽 반복문의 다음 j로 이동합니다.
바깥쪽 반복문까지 종료하려면 라벨이 있는 break를 사용할 수 있습니다.
OuterLoop:
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
if i == 2 && j == 2 {
break OuterLoop
}
fmt.Println(i, j)
}
}실행 결과:
1 1
1 2
1 3
2 1바깥쪽 반복문의 다음 반복으로 바로 이동하려면 라벨이 있는 continue를 사용할 수 있습니다.
OuterLoop:
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
if j == 2 {
continue OuterLoop
}
fmt.Println(i, j)
}
}실행 결과:
1 1
2 1
3 1continue OuterLoop가 실행되면 안쪽 반복문의 나머지 실행을 중단하고 바깥쪽 for의 다음 반복으로 이동합니다.
라벨은 복잡한 중첩 반복을 명확하게 제어할 때 유용하지만, 라벨이 많아지면 흐름을 따라가기 어려울 수 있습니다. 가능하다면 함수를 분리하고 return하는 구조도 함께 검토하는 것이 좋습니다.
전체 예제
main.go:
package main
import "fmt"
func main() {
demonstrateIf()
demonstrateFor()
demonstrateSwitch()
demonstrateBreakAndContinue()
demonstrateLabeledStatements()
}
func demonstrateIf() {
fmt.Println("== if ==")
age := 20
if age >= 19 {
fmt.Println("성인입니다.")
} else {
fmt.Println("미성년자입니다.")
}
if score := 85; score >= 80 {
fmt.Println("점수 판정: 합격입니다.")
}
}
func demonstrateFor() {
fmt.Println("\n== for ==")
fmt.Println("기본 for")
for i := 1; i <= 3; i++ {
fmt.Println(i)
}
fmt.Println("조건식만 사용하는 for")
count := 1
for count <= 3 {
fmt.Println(count)
count++
}
fmt.Println("break로 종료하는 무한 반복")
retryCount := 1
for {
fmt.Println("시도:", retryCount)
if retryCount == 3 {
break
}
retryCount++
}
}
func demonstrateSwitch() {
fmt.Println("\n== switch ==")
dayNumber := 2
switch dayNumber {
case 1:
fmt.Println("월요일")
case 2:
fmt.Println("화요일")
case 3:
fmt.Println("수요일")
default:
fmt.Println("알 수 없는 요일")
}
dayName := "토요일"
switch dayName {
case "토요일", "일요일":
fmt.Println("주말입니다.")
default:
fmt.Println("평일입니다.")
}
score := 85
switch {
case score >= 90:
fmt.Println("등급: A")
case score >= 80:
fmt.Println("등급: B")
case score >= 70:
fmt.Println("등급: C")
default:
fmt.Println("등급: F")
}
level := 1
switch level {
case 1:
fmt.Println("기본 권한")
fallthrough
case 2:
fmt.Println("추가 권한")
}
status := "processing"
hasError := true
switch status {
case "processing":
fmt.Println("처리 상태 확인")
if hasError {
fmt.Println("오류가 있어 후속 처리를 생략합니다.")
break
}
fmt.Println("후속 처리를 실행합니다.")
default:
fmt.Println("다른 상태입니다.")
}
fmt.Println("switch 이후 코드")
}
func demonstrateBreakAndContinue() {
fmt.Println("\n== break와 continue ==")
numbers := []int{3, 7, 10, 15}
for _, number := range numbers {
if number == 10 {
fmt.Println("10을 찾았습니다.")
break
}
fmt.Println("확인:", number)
}
scores := []int{90, -1, 75, -1, 82}
for _, score := range scores {
if score < 0 {
continue
}
fmt.Println("유효 점수:", score)
}
fmt.Println("break와 continue 비교")
for i := 1; i <= 5; i++ {
if i == 2 {
continue
}
if i == 4 {
break
}
fmt.Println(i)
}
fmt.Println("조건 반복에서 continue 사용")
count := 0
for count < 3 {
count++
if count == 2 {
continue
}
fmt.Println(count)
}
}
func demonstrateLabeledStatements() {
fmt.Println("\n== 라벨이 있는 break ==")
OuterBreak:
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
if i == 2 && j == 2 {
break OuterBreak
}
fmt.Println(i, j)
}
}
fmt.Println("\n== 라벨이 있는 continue ==")
OuterContinue:
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
if j == 2 {
continue OuterContinue
}
fmt.Println(i, j)
}
}
}프로젝트 루트에서 실행합니다.
cd sources
go run ./02-control-flow실행 결과:
== if ==
성인입니다.
점수 판정: 합격입니다.
== for ==
기본 for
1
2
3
조건식만 사용하는 for
1
2
3
break로 종료하는 무한 반복
시도: 1
시도: 2
시도: 3
== switch ==
화요일
주말입니다.
등급: B
기본 권한
추가 권한
처리 상태 확인
오류가 있어 후속 처리를 생략합니다.
switch 이후 코드
== break와 continue ==
확인: 3
확인: 7
10을 찾았습니다.
유효 점수: 90
유효 점수: 75
유효 점수: 82
break와 continue 비교
1
3
조건 반복에서 continue 사용
1
3
== 라벨이 있는 break ==
1 1
1 2
1 3
2 1
== 라벨이 있는 continue ==
1 1
2 1
3 1정리
Go에서는 if, for, switch 조건의 바깥 괄호를 일반적으로 사용하지 않으며 본문 중괄호는 필수입니다. while 키워드는 없고 조건 반복은 for condition으로 작성합니다.
switch는 일치하는 case를 실행한 뒤 자동으로 종료되므로 일반적인 case 마지막에 break가 필요하지 않습니다.
break와 continue의 차이는 다음과 같습니다.
break = 현재 반복문 또는 제어문 전체 종료
continue = 현재 반복의 남은 코드만 생략하고 다음 반복 진행break는 검색 완료, 종료 조건 충족, 무한 반복 종료 등에 사용합니다. continue는 유효하지 않은 데이터나 처리 대상이 아닌 항목을 건너뛸 때 유용합니다.
중첩 반복문에서는 라벨이 없는 break와 continue가 가장 가까운 반복문에만 적용됩니다. 바깥쪽 반복문을 직접 제어해야 할 때는 라벨을 사용할 수 있지만, 흐름이 복잡해진다면 함수를 분리하는 것이 더 읽기 쉬울 수 있습니다.
참고 자료
- Go 언어 명세 - If statements: https://go.dev/ref/spec#If_statements
- Go 언어 명세 - For statements: https://go.dev/ref/spec#For_statements
- Go 언어 명세 - Switch statements: https://go.dev/ref/spec#Switch_statements
- Go 언어 명세 - Break statements: https://go.dev/ref/spec#Break_statements
- Go 언어 명세 - Continue statements: https://go.dev/ref/spec#Continue_statements
- Effective Go - Control structures: https://go.dev/doc/effective_go#control-structures
'프로그래밍 > Go' 카테고리의 다른 글
| Go 함수, closure, recursion (1) | 2026.07.14 |
|---|---|
| Go 배열, slice, map, range (0) | 2026.07.13 |
| Go fmt의 %v와 %q (0) | 2026.07.11 |
| Go 리터럴, 변수, 상수와 Zero Value (0) | 2026.07.10 |
| Go package main과 패키지 구조 이해하기 (0) | 2026.07.10 |
댓글