프로그래밍 작성시 상수를 지정하는 일은 굉장히 흔한 일인데, golang에서는 iota를 이용해 어떻게 상수를 지정할 수 있는지 알아보자.

iota

iota를 사용하면 상수를 유연하게 지정할 수 있는데, 이를테면 다음의 예를 golang wiki에서 확인할 수 있다. 우선 iota를 사용하지 않았다면 다음과 같이 표기할 수 있을 것이다.

package main

import "fmt"

type ByteSize float64

const (
	KB ByteSize = 1 << (10 * 1)
	MB ByteSize = 1 << (10 * 2)
	GB ByteSize = 1 << (10 * 3)
	TB ByteSize = 1 << (10 * 4)
	PB ByteSize = 1 << (10 * 5)
	EB ByteSize = 1 << (10 * 6)
	ZB ByteSize = 1 << (10 * 7)
	YB ByteSize = 1 << (10 * 8)
)

func main() {
	fmt.Printf("KB?: %f\n", KB)
	fmt.Printf("MB?: %f\n", MB)
	fmt.Printf("GB?: %f\n", GB)
	fmt.Printf("TB?: %f\n", TB)
	fmt.Printf("PB?: %f\n", PB)
	fmt.Printf("EB?: %f\n", EB)
	fmt.Printf("ZB?: %f\n", ZB)
	fmt.Printf("YB?: %f\n", YB)
}

KB,MB,GB… 등의 단위는 단위가 커질수록 1024배, 즉 2**10승씩 커지게 되므로 이를 그대로 늘려주면 된다. 위 코드의 출력 결과는 아래와 같다.

$ go run main2.go
KB?: 1024.000000
MB?: 1048576.000000
GB?: 1073741824.000000
TB?: 1099511627776.000000
PB?: 1125899906842624.000000
EB?: 1152921504606846976.000000
ZB?: 1180591620717411303424.000000
YB?: 1208925819614629174706176.000000

사실 이 정도는 불편하다고 하긴 조금 그렇다. 다들 적당히 이런 식으로 상수를 지정하지 않을까 싶은데, 그러면 iota를 사용하면?

type ByteSize float64

const (
	_           = iota // ignore first value by assigning to blank identifier
	KB ByteSize = 1 << (10 * iota)
	MB
	GB
	TB
	PB
	EB
	ZB
	YB
)

위와 같은 코드로 간략하게 적을 수 있다. 위의 코드가 불편하진 않다 하더라도 아래 코드가 더 간단한 것은 확실하다.

iota의 규칙들

iota의 첫 번째 규칙은, iota는 단순히 0부터 순서대로 1씩 증가하는 값을 갖는다는 것이다. 무슨 복잡한 수식을 쓰고 하더라도, iota가 1씩 순서대로 증가한다는 것이 제일 중요하다. 두 번째로는, _, blank identifier를 통해 사용하지 않는 iota의 값을 만들 수 있다는 것이다.

const (
	_
	ONE = iota
	TWO
	THREE
	FOUR
        _
	SIX
)

이런 상수 선언을 만들었다면 그 출력값은

ONE?:  1
TWO?:  2
THREE?:  3
FOUR?:  4
SIX?:  6

이 된다. iota는 0부터 증가하므로, ONE을 지정하기 위해 _를 통해 iota 0을 무시하도록 처리했다.

또 다른 중요한 규칙으로, iota는 블록 내에서 연관성을 가진다. go에서는 var/const 등을 하나의 블록에서 함께 선언할 수 있는데, 이 안에서라면 iota가 순서를 갖는 것이다. 예를 들면 위의 KB,MB...등의 예제가 바로 그렇다. 간단히 코드를 보면

const (
	ONE = iota
	TWO
	THREE
	FOUR
)

const (
	OONE   = iota
	TTWO
)
const (
	TTHREE = iota
	FFOUR
)

이런 코드라면 ONE, TWO, THREE, FOUR는 순서대로 값을 갖지만, OONE, TTWO, TTHREE, FFOUR는 값을 순서대로 갖지 않는다.

ONE?:  0
TWO?:  1
THREE?:  2
FOUR?:  3
OONE?:  0
TTWO?:  1
TTHREE?:  0
FFOUR?:  1

또 다른 규칙으로는 iota의 값 뿐 아니라 iota를 사용한 표현까지 다음 라인으로 내려온다는 것이다. 위의 _를 사용하여 ONE, TWO… 등을 표현한 라인을 예를 들어 설명하면,

const (
	ONE = iota + 1
	TWO
	THREE
	FOUR
	_
	SIX

_를 사용하지 않고도 ONEiota + 1로 표현했다. TWO 또한 자연스럽게 2가 될 것이다.