[Go] Control Structures (if, for, switch)

김무연·2025년 1월 24일

Go언어의 제어구조는 C와 연관성이 있지만, 중요한 점에서 차이가 있다. Go언어에서는 dowhile 반복문이 존재하지 않으며, 단지 좀 더 일반화된 for, 좀 더 유연한 switch가 존재한다. if와 switch는 선택적으로 for 와 같은 초기화 구문을 받을 수 있다.

breakcontinue 구문들은 선택적으로 어느 것을 멈추거나 계속할지 식별하기 위해 라벨을 받을 수 있다. 또한 타입 switch와 다방향 통신 멀티플랙서 select 의 새로운 제어 구조가 포함되어있다. 조건식에 괄호가 필요하지 않은 것이 특징이다

if

  • if문은 해당 조건이 맞으면 {} 블럭안의 내용을 실행한다. Go의 if 조건문은 조건식을 괄호()로 둘러싸지 않아도 된다. 그리고 반드시 조건 블럭 시작 브레이스 { 를 if문과 같은 라인에 ㄷ어야 한다. 다른 라인데 있을 경우 에러를 발생시킨다.
  • 그리고 한가지 주목할 점은 if 문의 조건식은 반드시 Boolean 식으로 표현되어야 한다. 다른 언어에서 조건식에 1, 0 을 쓸 수 있는 것과 대조적이다.
  • 또한 다른 언어와 마찬가지로 else, else if를 가질 수 있다. 이들 또한 시작브레이스는 같은 라인에 존재해야 한다.
package iftest

import "fmt"

func If() bool {
	test1 := 1

	if test1 == 1 {
    	// 이런식으로 return 값을 해 줄수도 있다, 대신 함수에 return 타입 명시 필요
		return true
	} else {
		fmt.Println("false")
	}

}

if 문에서 조건식을 사용하기 이전에 간단한 문장(Optional Statement)를 함께 실행할 수 있다. var := i*2 라는 문장을 조건식 이전에 실행할 수 있는데 여기서 주의할 점은 이때 정의된 변수 val는 if문 scope 내에서만 사용할 수 있다. 이러한 Optional Statement 표현은 switch, for 문 등 Go의 여러 문법에서 통용된다.

package iftest

import (
	"fmt"
	"io/ioutil"
	"os"
)

func If()  {

	// 파일 열기
	f, err := os.Open("C:/te22st.txt")
	if err != nil {
		fmt.Println("파일 열기 오류:", err)
		return
	}
	defer f.Close() // 함수가 끝나면 파일 닫기

	// 파일의 내용을 읽기
	content, err := ioutil.ReadAll(f)
	if err != nil {
		fmt.Println("파일 읽기 오류:", err)
		return
	}

	// 파일 내용 출력
	fmt.Println("파일 내용:", string(content))

}

Go패키지에서는 값과 에러를 둘 다 return 해주는 방식의 패키지가 많다. 때문에 가장 흔한 에러 처리 방법은 위와 같은 식으로 진행이 되면 될 것이다.

switch

여러 값을 비교해야 하는 경우 혹우 다수의 조건식을 체크해야 하는 경우 switch문을 사용한다. 타 언어들과 비슷하게 switch 문 뒤에 변수(혹은 Expression)를 지정하고, case 문에 해당 변수가 가질 수 있는 값들을 지정해, 다른 블럭들을 실행할 수 있다.

package switchtest

import "fmt"

func Switchtest() {
	test := 1.4

	switch test {
	case 0.5:
		fmt.Println("1")
	case 0.6:
		fmt.Println("2")
	default:
		fmt.Println("3")
	}
}

타 언어들과 비교한 switch 특징

  1. switch 뒤에 expression이 없을 수 있음
  • 타 언어는 switch 키워드 뒤에 변수나 expression을 반드시 두지만, Go는 이를 쓰지 않아도 된다. 이 경우 Go는 switch expression을 true로 생각하고 첫 번재 case문으로 이동하여 검사한다.
  1. case문에 expression을 쓸 수 있음
  • 다른 언어의 case문은 일반적으로 리터럴 값만을 갖지만, Go는 case문에 복잡한 expression을 가질 수 있다.
  • 즉 다른 언어는 case문에 데이터 or 값만을 넣지만 , Go는 x >= 50 과 같은 expression이 가능하기 때문에 if...else if...else if 와 같은 중복을 단순화 할 수 있다.
package switchtest

import "fmt"

func Switchtest() {
	test := 1.4
	// switch구문 뒤에 변수나 expression을 안두어도 된다
	switch {
    // case 구문 뒤에도 단순한 리터럴 값이 아니라 expression(표현식)이 가능
	case test >= 0.5:
		fmt.Println("1")
	case test >= 0.6:
		fmt.Println("2")
	default:
		fmt.Println("3")
	}
}
  1. No default fall through
  • 다른 언어의 case문은 break를 쓰지 않는 한, 다음 case로 이동하지만, Go는 다음 case로 가지 않는다.
  • 타 언어에서 만약 break문이 없으면, case 문 밑의 모든 문장들은 실행해 버린다. Go는 case문 마지막에 break 문을 적든 말든 항상 break하여 switch문을 빠져나온다. 이는 Go 컴파일러가 자동으로 break문을 각 case문 블럭 마지막에 추가하기 때문이다.
  • Go에서 default break를 사용하지 않고, 타언어 처럼 밑에 구문을 계쏙 실행하게 하려면, fallthrough 문을 명시해주면 된다.
  • 허나 fallthrough는 현재 case 블록에만 해당한다는 것을 유념해야 한다. 끝까지 적용되는 것이 아닌 해당 블록에만 적용이 되어, 만약 다음 블록에 fallthrough가 없을 경우 거기서 멈추게 된다.
package iftest

import "fmt"

func Switchtest() {
	test := 1.4

	switch {
	case test >= 0.5:
		fmt.Println("1")
		fallthrough
	case test >= 0.6:
    // 여기 case 블록에는 fallthrough가 없으니 , 1 2 까지만 출력이 된다.
    // 3도 출력을 하게 하고 싶으면, 아래에 fallthrough를 추가한다.
		fmt.Println("2")
	default:
		fmt.Println("3")
	}
}
  1. Type switch
  • 다른 언어의 switch는 일반적으로 변수의 값을 기준으로 case로 분기하지만, Go는 그 변수의 Type에 따라 case로 분기할 수 있다.
  • 주로 빈 interface{} 타입으로 쓴다
package iftest

import (
	"fmt"
	"reflect"
)

func CheckType(arg any) any {
	return reflect.TypeOf(arg)
}

func Switchtest() {
	var test interface{} = CheckType('q')

	switch test.(type) {
		case int: 
			fmt.Println("int")
		case string: 
			fmt.Println("string")
		default: 
			fmt.Println("default")
	}

}

for 반복문

Go 프로그래밍 언어에서 반복문은 for 루프를 이용한다. Go는 반복문에 while 이런건 존재하지않고 유일하게 for 하나만 존재한다. 구조는 다른어어와 유사하게 "for 초기값; 조건식; 증감 {...}" 의 형식을 따른다.
대신 타 언어 처럼 초기값, 조건식, 증감을 둘러싸는 괄호 ()는 생략된다. 또한 초기값은 병렬 할당이 가능하다. 증감또한 꼭 ++, -- 만 있는 것이 아니라 i = i + 2와 같이 표현식을 써줄수 도 있다

package forexample

import "fmt"

func Forexample() {
	sum := 0

	for i := 1; i < 11; i++ {
		sum += i
	}

	fmt.Println(sum, "합계")
}

병렬할당

package forexample

import "fmt"

func Forexample() {
	sum := 0

	for x, y := 1, 3; x < 10; x , y = x+2, y+2 {
		sum += x
		sum -= y
	}
	fmt.Println("합계 = " ,sum)

}

조건식만 쓰는 for 반복문

Go에서 for루프는 초기값, 증감식이 생략이 가능하다. 조건식만을 사용할 수 있는ㄷ네, 이는 타 언어의 while 반복문과 유사하게 쓸 수 있도록 제공한다. 따라서 조건식에는 bool 타입이 와야한다.

package forexample

import "fmt"

func Forexample() {
	sum := 0

	i := 1
	
	for i < 101 {
		sum += i
		i++
	}

	fmt.Println("합계 :", sum)
}

무한 roof

for 루프로 무한 루프를 만드려면 초기값, 조건식, 증감 모두를 생략 하면된다. 빠져나오기 위해서는 ctrl + c 를 누르거나, break를 써준다.

package forexample

import "fmt"

func Forexample() {
	sum := 0
	i := 1

	for {
		sum += i
		i++

		if i == 100 {
			break
		}
	}

	fmt.Println("합계 :", sum)
}

for range 문

for range 문은 컬렉션으로 부터 한 요소(element)씩 가져와 차례로 for 블럭의 문장들을 실행한다. python의 for i in [list] 와 비슷할 것이고, js의 for of 와 비슷할 것이다.

for range 문은 "for index, ele := range 컬렉션" 과 같이 for 루프를 구성하는데, range 키워드 다음의 컬렉션으로부터 하나씩 요소를 리턴해서 그 요소의 위치인덱스와 값을 for 키워드 다음의 2개의 변수에 각각 할당한다.

package forexample

import "fmt"

func Forexample() {
	sum := 0

	name := []string{"김두한", "구마적", "쌍칼"}

	for i, e := range name {
		fmt.Println(i, " ",e)
	}
}

//
0   김두한
1   구마적
2   쌍칼

break, continue, goto 문

경우에 따라 for 루프 내에서 즉시 빠져나올 필요가 있는데, 이 때 break 문을 사용한다. continue도 타 언어와 마찬가지로, 현재 실행 구문에서 for 루프 시작 부분으로 가려고 할 때, continue를 사용하고, 임의의 문장으로 이동하기 위해서는 goto문을 이용할 수 있다. goto문은 for 루프와 관련없이 사용될 수 있다.

break문은 for 루프 이외에 switch문이나 select문에서도 사용할 수 있다. 하지만, continue문은 for 루프와 연관되어 사용된다.

package forexample

import "fmt"

func Forexample() {
    var a = 1
    for a < 15 {
        if a == 5 {
            a += a
            continue // for루프 시작으로
        }
        a++
        if a > 10 {
            break  //루프 빠져나옴
        }
    }
    if a == 11 {
        goto END //goto 사용예
    }
    fmt.Println(a)
 
	END:
    fmt.Println("End")
}
profile
Notion에 정리된 공부한 글을 옮겨오는 중입니다... (진행중)

0개의 댓글