Go에서의 열거형 상수 (Enums in Go)

@Frank Oh · December 20, 2020 · 6 min read

1. 들어가며

Go에서는 Java에서 제공하는 Enums 타입은 존재하지 않는다. 하지만, Go에서도 iota를 이용해서 Enums과 같은 상수값을 쉽게 선언하여 사용할 수 있다.

iota 키워드는 const 선언에서 사용할 수 있는 predefined identifier로 연속적인 정수 상수 0, 1, 2, ...를 나타낸다. 예제를 통해서 어떻게 사용하는지 알아보자.

//#builtin.go
// iota is a predeclared identifier representing the untyped integer ordinal
// number of the current const specification in a (usually parenthesized)
// const declaration. It is zero-indexed.
const iota = 0 // Untyped int.

2. iota 예제

2.1 기본 예제

iota의 시작 값은 0이고 이후부터는 +1 증가된 값으로 선언된다.

func Example_iota_기본() {
  const (
    c0 = iota
    c1 = iota
    c2 = iota
  )

  fmt.Println(c0, c1, c2)
  //Output:
  //0 1 2
}

매번 iota 키워드를 사용하지 않고 한번만 선언하면 나머지 변수에는 연속적인 값이 선언된다.

func Example_iota_기본2() {
	const (
		c0 = iota
		c1
		c2
	)

	fmt.Println(c0, c1, c2)
	//Output:
	//0 1 2
}

2.2 시작 값 변경하기

시작 값도 쉽게 변경할 수 있다.

func Example_iota_시작값_변경() {
	const (
		c0 = iota + 5
		c1
		c2
	)

	fmt.Println(c0, c1, c2)
	//Output:
	//5 6 7
}

2.3 중간 값 스킵하기

2.3.1 하나의 값을 스킵하는 방법

중간 값을 스킵하려면 blank identifier를 사용해서 중간 값을 스킵한다.

func Example_iota_중간값_skipped() {
	const (
		c0 = iota + 1
		_
		c1
		c2
	)

	fmt.Println(c0, c1, c2)
	//Output:
	//1 3 4
}

2.4.2 하나 이상의 값 스킵하는 방법

아래와 같이 하나 이상의 값을 스킵하고 상수 값을 선언하는 방법에 대해서 알아보자.

1, 2, 100, 101, 500, 501

2.4.2.1 jump해야 하는 값을 직접 계산하기

스킵해야 하는 구간의 값을 직접 계산해서 선언하면 된다.

func Example_iota_중간값_다르게_지정() {
	//수동으로 계산하기
	const (
		c0 = iota + 1   //1
		c1              //2
		c2 = iota + 98  //100
		c3              //101
		c4 = iota + 496 //500
		c5              //501
	)

	fmt.Println(c0, c1, c2, c3, c4, c5)
	//Output:
	//1 2 100 101 500 501
}
2.4.2.2 const 그룹 별로 나눠서 선언하기

jump 뛰어야 하는 구간을 직접 계산하기보다는 아래와 같이 여러 그룹으로 나눠서 선언하면 조금 더 쉽게 선언이 가능하다.

func Example_iota_중간값_다르게_지정2() {
	//수동으로 계산하기
	const (
		c0 = iota + 1 //1
		c1            //2
	)
	const (
		c2 = iota + 100 //100
		c3              //101
	)
	const (
		c4 = iota + 500 //500
		c5              //501
	)

	fmt.Println(c0, c1, c2, c3, c4, c5)
	//Output:
	//1 2 100 101 500 501
}

3. Enums 예제 모음

Enums 식으로 사용할 수 있는 예제들이다.

3.1 ByteSize 상수 값 선언하기

데이터 단위를 아래와 같이 선언한다. KB 단위만 선언하면 나머지 MB, GB... 단위도 쉽게 선언이 된다.

func Example_iota_BYTE_예제() {
	type ByteSize float64

	const (
		_           = iota             // blank identifier로 첫번째는 그냥 무시함
		KB ByteSize = 1 << (10 * iota) //2^(10*1) = 1024
		MB                             //2^(10*2) = 1,048,576
		GB
		TB
		PB
		EB
		ZB
		YB
	)
	var fileSize ByteSize = 4000000000 //4 GB
	fmt.Printf("%.2f GB", fileSize/GB)
	//Output:
	//3.73 GB
}

3.2 Bitwise 연산으로 플래그 값이나 옵션 확인하기

비트 연산을 통해서 여러 옵션이나 플래그를 적용하고 AND 연산으로 적용되었는지 확인하는 예제이다. 이 예제에서는 사용자에게 여러 역할을 부여하고 역할을 확인한다.

func Example_iota_bitwise_role_예제() {
	const (
		isAdmin          = 1 << iota //1
		isHeadquarters               //10
		canSeeFinancials             //100

		canSeeAfrica       //1000
		canSeeAsia         //10000
		canSeeEurope       //100000
		canSeeNorthAmerica //1000000
		canSeeSouthAmerica //10000000
	)

	var myRoles byte = isAdmin | canSeeFinancials | canSeeEurope
	fmt.Printf("%b\n", myRoles)
	fmt.Printf("is admin? %v\n", isAdmin & myRoles == isAdmin)
	fmt.Printf("is HQ? %v\n", isHeadquarters & myRoles == isHeadquarters)
	//Output:
	//100101
	//is admin? true
	//is HQ? false
}

3.3 선언한 Enums iterate해보기

상수 선언시 마지막 값을 이용해서 iterate한다.

type WeekDay int

func Example_iterate_weekdays() {
	const (
		Sunday WeekDay = iota
		Monday
		Tuesday
		Wednesday
		Thursday
		Friday
		Saturday
		numberOfDays
	)

	for day := WeekDay(0); day < numberOfDays; day++ {
		fmt.Print(" ", day)
	}
	fmt.Println("")
	//Output:
	//Sunday Monday Tuesday Wednesday Thursday Friday Saturday
}

func (d WeekDay) String() string {
	var weekDays = [...]string{
		"Sunday",
		"Monday",
		"Tuesday",
		"Wednesday",
		"Thursday",
		"Friday",
		"Saturday",
	}

	return weekDays[int(d)%len(weekDays)]
}

4. 마무리

Go 언어에서 Enums 형식으로 선언하는 방법에 대해서 알아보았다. 쉽게 상수 값을 선언하기 위해서 iota 키워드를 사용했고 다양한 예제도 볼 수 있었다. 본 포스팅에서 작성한 코드는 github에서 확인할 수 있다.

5. 참고

@Frank Oh
안녕하세요. 방문해주셔서 감사합니다. 컴퓨터 관련 스터디한 내용 기록하는 블로그입니다.