이 글은 Effective Go를 일부 번역한 글입니다.


제어 구조

Go의 제어 구조는 C의 그것과 연관이 있지만 중요한 차이가 있다. dowhile 반복이 없고 조금 일반화된 for만 있다. switch는 더 유연하다. ifswitch에도 for처럼 초기화 문장을 넣을 수 있다. breakcontinue 문장엔 이름표를 붙여 벗어나거나 재개할 것을 지정할 수 있다. 또한 새롭게 type switch와 다방향 통신 멀티플렉서 select가 제어 구조에 추가되었다. 구문도 약간 다르다. 괄호가 없으며 본문은 반드시 항상 중괄호로 감싸야 한다.

For

Go의 for 반복문은 C와 비슷하다. (같진 않다.) for와 while을 통합했고, do-while은 없다. 세 가지 형태가 있으며, 그 중 단 하나만 쌍반점을 사용한다.

// Like a C for
for init; condition; post { }

// Like a C while
for condition { }

// Like a C for(;;)
for { }

축약 선언으로 편하게 색인(Index) 변수를 바로 반복문에 선언할 수 있다.

sum := 0
for i := 0; i < 10; i++ {
    sum += i
}

배열, 조각(Slice), 문자열, 맵 전체나, 채널 읽기를 반복하려면, range로 반복을 관리할 수 있다.

for key, value := range oldMap {
    newMap[key] = value
}

범위 중 첫 번째(열쇠(Key), 색인)만 필요하다면 두 번째를 버리라.

for key := range m {
    if key.expired() {
        delete(m, key)
    }
}

범위 중 두 번째(값)만 필요하다면 공백 식별자인 밑줄(Underscore)을 사용해 첫 번째를 버리라.

sum := 0
for _, value := range array {
    sum += value
}

공백 식별자는 쓰임이 많다. 후에 서술한다.

range는 문자열을 다룰 때 더 많은 일을 한다. UTF-8을 분석해 유니코드 코드 포인트 단위로 나눈다. 인코딩이 잘못되면 바이트 하나를 사용해 U+FFFD 룬(Rune)을 채워 넣는다. (룬이란 이름은 내장된 유형과 관련 있다. 유니코드 코드 포인트 하나를 부르는 Go 용어다. 언어 명세에 자세히 썼으니 보라.)

for pos, char := range "日本\x80語" { // \x80 is an illegal UTF-8 encoding
    fmt.Printf("character %#U starts at byte position %d\n", char, pos)
}

이 반복문은 아래와 같이 출력한다.

character U+65E5 '日' starts at byte position 0
character U+672C '本' starts at byte position 3
character U+FFFD '�' starts at byte position 6
character U+8A9E '語' starts at byte position 7

마지막으로, Go엔 반점 연산자가 없다. 또한 ++와 --는 식(Expression)이 아닌 문장이다. 따라서 for에 여러 변수를 굴리고 싶다면 (++와 --를 사용할 수 없더라도) 다중 할당을 사용해야 한다.

// Reverse a
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
    a[i], a[j] = a[j], a[i]
}