Table of Contents
Golang - 제어문 사용하기
if 문
다른 프로그래밍 언어의 if 문과 매우 유사하다. 가장 큰 차이점은 조건을 감싸는 괄호가 없다는 것이다.
if 문 선언
기본적으로 다음과 같이 선언한다.
1n := rand.Intn(10)
2
3if n == 0 {
4 fmt.Println("That's too low")
5} else if n > 5 {
6 fmt.Println("That's too big:", n)
7} else {
8 fmt.Println("That's a good number:", n)
9}
if 혹은 else 문의 중괄호 내에 선언된 모든 변수는 블록 내에서만 유효하다.
if, else 블록 범위내에서만 사용 가능한 변수를 설정할 수 있다.
1if n := rand.Int(10); n == 0 {
2 fmt.Println("That's too low")
3} else if n > 5 {
4 fmt.Println("That's too big:", n)
5} else {
6 fmt.Println("That's a good number:", n)
7}
if/else 문이 마무리되면 n은 더 이상 접근이 되지 않는다.
for 문
다른 언어와 마찬가지로 루프를 위해 for 문을 사용한다. 차이점은 Go에서는 for가 유일한 반복문 키워드이다.
완전한 for 문
다른 언어의 for 문과 유사하다. if 문 처럼 감싸는 괄호는 없다.
1for i := 0; i < 10; i++ {
2 fmt.Println(i)
3}
변수를 초기화하기 위해서는 반드시 := 를 사용해야 한다. → var 키워드는 허용하지 않는다.
조건식만 사용하는 for 문
for 문에서 초기값과 증감식을 생략할 수 있다.
1for i < 100 {
2 fmt.Println(i)
3 i = i * 2
4}
다른 언어의 while 문을 사용하는 것과 비슷하다.
for 문을 이용한 무한루프
조건식도 사용하지 않고 for 문을 사용하면 무한루프가 된다.
1for {
2 fmt.Println("Hello")
3 if !CONDITION {
4 break
5 }
6}
즉시 루프에서 빠져나오려면 break 문을 사용하고 다음 루프로 넘기려면 continue 를 사용한다.
for-range 문
Go의 어떤 내장 타입의 요소를 순회하며 루프를 수행하는 for 문이다. for-range 문의 각각의 값들은 복합 타입 변수의 값을 복사한 값이므로 for-range 문 내에서 값을 수정하더라도 원본이 변경되지 않는다.
슬라이스를 사용하여 for-range 루프를 만든 코드이다.
1evenVals := []int{2, 4, 6}
2for i, v:= range evenVals {
3 fmt.Println(i, v)
4}
5
6// 0 2
7// 1 4
8// 2 6
for-range 루프는 두 개의 변수를 얻을 수 있다. 첫 번째는 현재 순회 중인 값의 위치이고, 두 번째는 해당 위치의 값이다.
맵을 사용하여 for-range 루프를 만든 코드이다.
1m := map[string]int{
2 "a": 1,
3 "c": 3,
4 "b": 2,
5}
6
7for k, v := range m {
8 fmt.Println(k, v)
9}
출력은 맵의 순서와 관계 없이 매번 다르게 나온다. 그 이유는 Go 팀이 해시 도스 공격 같은 문제를 해결하기 위해 해시 알고리즘을 수정하여 맵 변수가 생성될 때마다 무작위 숫자를 포함시켰고, for-range 순회 순서를 루프가 반복될 때마다 조금씩 달라지게 했기 때문이다.
문자열을 사용하여 for-range 루프를 만든 코드이다.
1samples := "a_π!"
2for i, r := range samples {
3 fmt.Println(i, r, string(r))
4}
5
6// 0 97 a
7// 1 95 _
8// 2 960 π
9// 4 33 !
index가 3을 건너뛴 것을 알 수 있다. for-range 루프로 문자열을 순회할 때는 룬을 순회하기 때문에 오프셋은 룬이 가지고 있는 바이트 수에 따라 증가한다.
잘 사용하지는 않지만 중첩된 순회문이 있을 경우 바까쪽 루프의 순회를 종료하고 싶을 경우 레이블을 사용한다.
1outer:
2 for _, outerVal := range outerValues {
3 for _, innerVal := rnage outerVal {
4 // innerVal 처리
5 if invalidSituation(innerVal) {
6 continue outer
7 }
8 }
9 // innerVal 처리가 성공적으로 처리되었을 때 수행되는 부분
10 }
Switch 문
다른 언어들은 break 문을 명시하지 않는다면 아래의 case 문도 함께 실행되어 switch 문의 사용을 선호하지 않는다. 하지만 Go는 다른 언어와 다르게 break 문을 사용하지 않아도 다음 case 문을 실행하지 않는다는 것을 기본으로 한다.
1words := []string{"a", "smile", "octopus", "anthropologist"}
2for _, word := range words {
3 switch size := len(word); size {
4 case 1, 2, 3, 4:
5 fmt.Println(word, "is a short word!")
6 case 5:
7 wordLen := len(word)
8 fmt.Println(word, "is exactly the right length:", wordLen)
9 case 6, 7, 8, 9:
10 default:
11 fmt.Println(word, "is a long word!")
12 }
13}
14
15// a is a short word!
16// smile is exactly the right length: 5
17// anthropologist is a long word!
if 문과 마찬가지로 비교가 되는 값을 감싸는 괄호는 넣을 필요가 없다. 또한 switch 문 내에 어디든 접근 가능한 변수를 선언할 수 있다. 비어 있는 case 문에 대해서는 아무 일도 일어나지 않는다.
for문 안에 switch 문이 들어가 있을 경우 for 루프를 빠져나와야 한다면 레이블을 활용할 수 있다.
1loop:
2 for i := 0; i < 10; i++ P
3 switch {
4 // 생략..
5 case 1:
6 break loop // for 문 루프 빠져나오기
7 }
switch 문에서 비교가 되는 값을 명시하지 않는 공백 switch 문을 사용할 수도 있다.
1words := []string{"a", "smile", "octopus", "anthropologist"}
2for _, word := range words {
3 switch wordLen := len(word); {
4 case wordLen < 5:
5 fmt.Println(word, "is a short word!")
6 case wordLen > 10:
7 fmt.Println(word, "is a long word!")
8 default:
9 fmt.Println(word, "is exactly the right length.")
10 }
11}
각 case 문에 boolean 결과를 내는 비교는 모두 가능하다.