2. Flow control statement
For
- the init statement: 첫 번째 반복 전 실행
- the condition statement: 모든 반복 전 실행
- the post statement: 모든 반복 후 실행
- for statement 에 () 사용 안 한다. 단 {} 은 필수
for i := 0; i < 10: i++ {
sum += i
}
For is Go's while
- false가 될 때까지 실행.
for sum < 1000 {
sum += sum
}
Forever
for {
}
If
- for와 동일 하게 () 필요 없다. {} 필수
if x < 0 {
...
}
If with short statement
- 짧은 문장을 if 문에 사용 가능
- 변수의 scope 는 if 블록 안에서만 유효.
if v := get(); v < lim {
...
}
If and else
if v < lim {
} else {
}
Switch
- if else 의 축약형 표현.
- 매치 되는 첫 번째 문을 실행 시킴
- 브레이크 문이 없어도 된다. 한 개 실행 후 swich block 을 빠져 나간다.
- 스위치의 케이스 값이 상수나 int가 아니어도 가능.
switch os := runtime.GOOS; os {
case "darwin":
...
default:
...
}
Switch evaluation order
- 위에서 아래로 실행 된다.
- 아래의 예제에서 i == 0 이라면 f() 호출 안 된다.
switch i {
case 0:
case f():
}
Switch with nocondition
- switch true 와 동일 하다.
switch {
case t.Hour < 12:
...
default:
...
}
Defer
- 감싸고 있는 함수가 리턴 될 때까지 실행이 지연된다.
- defer 함수에 들어가는 인자는 바로 평가 된다. 하지만 defer된 함수는 감싼 함수가 리턴 될 때 실행
func world() string {
fmt.Println("world() called")
return "world"
}
func main() {
defer fmt.Println(world())
fmt.Println("hello")
}
// world() called
// hello
// world
Stacking defer
- 디퍼 함수는 스택처럼 작동 last in first out
func main() {
fmt.Println("counting")
// for i := 0; i < 3; i++ {
// defer fmt.Println(i)
// } // 아래와 동일
defer fmt.Println(0)
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println("done")
}
// counting
// done
// 2
// 1
// 0
defer, panic, recover detail
- https://blog.golang.org/defer-panic-and-recover
defer
- 디퍼문은 디퍼된 함수를 리스트에 집어 넣는 느낌으로 작동.
- 감싼 함수가 리턴 되면 리스트를 실행.
- 클린업 action 이 필요 한 경우 사용.
- 3개 규칙
- 디퍼 문장이 평가 될때 아규먼트값을 결정.
- 디퍼 함수는 후입선출 방식으로 실행.
- 디퍼 함수는 감싼 함수의 아웃 이름 변수를 변경 할 수 있다.
panic
- 함수 실행을 멈추고 panicking 현상으로 들어감. 디퍼된 함수를 실행 시키고,
- 스택을 따라 가면 계속 panicking 현상을 발생 시킨다.
- goroutin 끝에 닿으면 리턴.
recover
- panicking 을 멈추고 다시 컨트롤을 가져 온다, defer 함수 안에서만 유효.
- 일반 함수에서는 언제나 nil을 리턴 한다. 아무런 영향이 없다.