본문 바로가기
그 외

1. go 의 if, switch, for, 함수

by Hindsight.. 2020. 9. 9.

go는 vscode에서 환경설정을 잘 했다면 저장 시 코드가 prettier된다..(우리말로 뭐라고하지..)

편하다 편해!

 

1. if

package main

import "fmt"

func main(){
  i := 1
  if i > 0 { // go의 if문 조건식에는 반드시 boolean 타입이 반환되는 조건식이 들어와야한다.
      fmt.Printf("good")
  }else{
      fmt.Printf("bad")
  }
}

 

2. switch

package main

import "fmt"

func main(){
	i := 1
    
    switch i{
    
    case 1, 2:
    	fmt.Println(i, "i는 1 또는 2다")
    case 3, 4:
    	fmt.Println(i, "i는 3 또는 4다")
    }
 }

일반적인 프로그래밍 언어의 switch문은 이 코드 실행 시 case 1,2와 case 3,4 가 모두 실행되지만, 정말 편하게도 go의 switch는 해당하는 case만 실행된다. switch case를 if else의 대체재로 사용하기 좋다.

 

하지만, 때에 따라 하위 case들 모두 실행되길 원하는 경우도 있기 때문에 fallthrough 라는 키워드를 사용한다.

 

package main

import "fmt"

func main(){
	i := 1
    
    switch i{
    
    case 1, 2:
    	fmt.Println(i, "i는 1 또는 2다")
        fallthrough // 하위 케이스까지 진행
    case 3, 4:
    	fmt.Println(i, "i는 3 또는 4다")
    }
 }

 

if else문을 완벽하게 대체하기위해 case의 조건에 boolean형도 지원한다.

package main

import "fmt"

func main() {
	i := -2

	switch {
	case i < 0:
		fmt.Println(i, "는 음수")
	case i == 0:
		fmt.Println(i, "는 0")
	case i > 0:
		fmt.Println(i, "는 양수")
	}
}

 

if else가 쌓일 경우 가독성이 떨어지는 경우가 있는데 좋다고 생각한다.

 

3. for

기본적인 기능은 같고 다중 for 에서의 레이블 사용과 range를 예시로 소개한다.

package main

import "fmt"

func main() {
	x := 7
	table := [][]int{{1, 5, 9}, {2, 6, 5, 13}, {5, 3, 7, 4}}

LOOP: // 레이블 LOOP
	for row, rowValue := range table { // 컬렉션 데이터 반복시 편리한 range
		for col, colValue := range rowValue {
			if colValue == x {
				fmt.Printf("found %d(row:%d, col:%d)\n", x, row, col)
				break LOOP // LOOP 종료 => 이중 for 종료
			}
		}
	}
}

 

4. 함수 선언 방식

package main

import "fmt"

func test(a int, b int) (num int, num2 int) { // a, b 입력값   // num, num2 반환값
	num = a // 입력값 a를 반환값 num에 전달
	num2 = b // 입력값 b를 반환값 num2에 전달
	return
}

func main() {
	x, y := test(1, 2) // 1, 2 입력 // 각각 x, y에 1, 2 반환
	fmt.Printf("x : %d , y : %d\n", x, y)
}

//결과
//x : 1 , y : 2

 

함수는 이 코드 하나에서 끝낼 수 있다. 다수의 언어와는 분명 뭔가 다르다.

 

첫번째로 함수 test의 반환값에 변수명이 지정되어 있다. go는 반환값에 미리 변수명을 지어주어 가독성을 높였다.

 

두번째로 반환값 num에는 입력값 a를, num2에는 b를 전달했고, 그냥 return 했다.

 

그런데 main에서 x와 y를 출력하면 입력값이 그대로 잘 return 되었음을 확인할 수 있다. 여기서 test 함수에서 반환값의 변수명을 미리 주어진 이유가 드러나는데, 미리 정의한 반환값의 변수명을 함수 내에서 잘 갖고 놀다가 return시, 그대로 반환됨을 알 수 있다.

물론 반환 변수명을 미리 입력하지 않고, (int, int)형식으로 기존과 그대로 가져갈 수도 있으므로 적절한 방식을 사용하자!

 

package main

import (
	"fmt"
	"strconv"
)

func displayInt(s string) {
	if v, err := strconv.Atoi(s); err != nil { // strconv.Atoi(s) return 정수형 변수, err == nil , 함수 정상 실행 시 nil 반환
		fmt.Printf("%s는 정수가 아니다.\n%s", s, err)
	} else {
		fmt.Printf("정수 값은 %d입니다.\n", v)
	}
}

func main() {
	displayInt("two")
	displayInt("2")
}

//실행결과
//two는 정수가 아니다.
//strconv.Atoi: parsing "two": invalid syntax
//정수 값은 2입니다.

 

Go에서의 대부분의 미리 정의된 함수는 반환값이 두개이다. 결과 반환값과 에러 여부를 함께 반환한다. strconv.Atoi는 string형 데이터를 정수형으로 변환해주는데 string으로 숫자가 들어오지 않을 경우 err에 에러를 반환하고, 정상적으로 들어왔을 경우 nil을 반환해준다.

대부분의 함수가 err 여부와 반환 값을 함께 반환한다는 것을 기억하자.

그렇지만 모든 함수가 err 여부가 궁금하지 않을 수 있는데. 그럴 땐 '_'(빈 식별자) 를 사용해 임시로 받아주자.

i, _ := test()

'_'는 go에서 변수로 인식하지 않고, 계속해서 :=로 값을 할당할 수 있다.