본문 바로가기

Language/Go

[기초] Go 기초 정리 - 2 (For, If, Switch, Defer)

Tour of Go를 기반으로한 Go의 기본 내용입니다.

 

For

  • Go는 for라는 단 하나의 반복 구조를 가짐.
  • for 반복문은 ;로 구분되는 세 가지 구성 요소를 가짐
    • 초기화 구문 : 첫 번째 iteration 전에 수행.
    • 조건 표현 : 매 모든 iteration 이전에 판별.
    • 사후 구문 : 매 iteration 마지막에 수행.
  • 초기화 구문은 주로 :=를 이용한 변수 선언이고, for 스코프 내에서만 유효하다.
  • 반복문은 조건 판별이 false일 경우, 종료될 것.
  • C, Java, Javascript와 같은 언어들과 달리, Go는 for의 세가지 구성 요소를 감싸는 괄호는 없고, { }괄호가 항상 필수.
package main

import "fmt"

func main() {
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	
	for i:=0; i < 10 ; i++{
		sum += i
	}
	fmt.Println(sum)
}

 

package main

import "fmt"

func main() {
	sum := 1
    //초기화 구문과 사후 구문은 필수 아님.
	for ; sum < 1000; {
		sum += sum
	}
	fmt.Println(sum)
}

 

package main

import "fmt"

func main() {
	sum := 1
    
    //;를 생략할 수 있다는 점에서 
    //C의 while은 Go에서 for로 쓰임.
	for sum < 1000 {
		sum += sum
	}
	fmt.Println(sum)
}

 

package main

func main() {

	//for를 이용한 무한 루프
	for {
	}
}

 

If

  • Go의 if문은 for반복문과 비슷함.
  • 표현식은 ( ) 괄호로 둘러쌓일 필요는 없지만, { } 괄호는 필수.
package main

import (
	"fmt"
	"math"
)

func sqrt(x float64) string {
	if x < 0 {
		return sqrt(-x) + "i"
	}
	return fmt.Sprint(math.Sqrt(x))
}

func main() {
	fmt.Println(sqrt(2), sqrt(-4))
	
	
	string := "test"
	
	if string != "test"{
		fmt.Println("Done")
	}
}

 

짧은 구문의 If

  • for과 마찬가지로, if문 또한 조건문 전에 수행될 짧은 구문으로 시작될 수 있음.
  • 짧은 구문에서 선언된 변수는 if문 안에서만 유효.
package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	}
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}

 

if와 else

  • 짧은 if문 안에서 선언된 변수들은 어떠한 else블럭에서든 사용이 가능.
package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	} else {
		fmt.Printf("%g >= %g\n", v, lim)
	}
	// can't use v here, though
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}

 

Switch

switch 구문은 연속적인 if-else 구문을 깔끔하게 작성할 수 있는 방법.

  • Go의 switch문은 뒤이어 오는 모든 case를 실행하는 것이 아니라 오직 첫 번째로 선택된 케이스만 실행.(break 작성 불요.)
  • Go의 switch case는 상수일 필요가 없으며 값들은 정수일 필요도 없음.
package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Print("Go runs on ")
	switch os := runtime.GOOS; os {
	case "darwin":
		fmt.Println("OS X.")
	case "linux":
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.\n", os)
	}
	
	check := "Go"
	
	switch check = "Java";check {
		case "Java" :
			fmt.Println("Java")
		case "Javascript" :
			fmt.Println("Javascript")
		case "Go" :
			fmt.Println("Go")
		default:
			fmt.Println("Default")
	}
}

 

  • Switch case는 하나의 케이스라도 성공하면 멈추는 식으로 위에서부터 아래로 case를 평가.
    (예를 들어, 만약 i==0 이라면 f를 호출하지 않음.)
switch i {
  case 0:
  case f():
}

 

  • 조건이 없는 Switch는 switch true와 동일.
  • 긴 if-else 체인을 작성하는 아주 깔끔한 방식으로 활용가능.
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("Good morning!")
	case t.Hour() < 17:
		fmt.Println("Good afternoon.")
	default:
		fmt.Println("Good evening.")
	}
}

 

Defer

defer문은 자신을 둘러싼 함수가 종료할 때까지, 함수의 실행을 연기합니다.

  • defer된 인자는 즉시 evaluate되지만 함수 호출은 둘러싼 함수가 종료할 때까지 수행되지 않음.
  • defer된 함수 호출은 스택에 쌓여 FILO의 순서로 수행.
package main

import "fmt"

func main() {
	defer fmt.Println("world")
	defer fmt.Println("world2")
	defer fmt.Println("world3")
	fmt.Println("hello")
	defer fmt.Println("world4")
}
//hello
//world4
//world3
//world2
//world