변수 선언

변수 선언

프로그램을 짜다 보면 값을 담아 둘 변수를 만드는 일이 정말 자주 생기죠. Go에서 변수 선언(variable declaration)은 한 번에 하나 또는 여러 개의 변수를 만들고, 각 변수에 대응하는 식별자를 묶어 주며, 타입과 초깃값을 함께 부여하는 문법이에요. 오늘은 이 선언이 어떤 모양으로 쓰이는지 하나씩 살펴볼게요.

출처: Go Specification

본문

변수 선언은 하나 또는 여러 개의 변수를 만들고, 그 변수들에 대응하는 식별자를 묶어 주며, 각각에 타입과 초깃값을 지정해요. 문법을 EBNF로 먼저 볼게요.

VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .

VarDecl이 곧 var 키워드로 시작하는 선언 하나를 뜻해요. 그 뒤에는 VarSpec 하나가 오거나, 괄호로 묶어서 VarSpec 여러 개를 나열할 수 있어요. VarSpec은 식별자 목록(IdentifierList)에 타입을 딸지, 아니면 초기화 표현식 목록(ExpressionList)을 바로 붙일지로 나뉘죠. 실제 코드로 보면 훨씬 익숙할 거예요.

var i int
var U, V, W float64
var k = 0
var x, y float32 = -1, -2
var (
	i       int
	u, v, s = 2.0, 3.0, "bar"
)
var re, im = complexSqrt(-1)
var _, found = entries[name]  // map lookup; only interested in "found"

첫 줄처럼 var i int는 변수 i를 정수 타입으로 선언해요. 여러 변수를 한 번에 만들 수도 있고, 괄호를 열어 그룹으로 묶을 수도 있어요. 마지막 예시의 밑줄(_)은 특별한 변수죠 — 값을 버릴 자리로, 본문 주석처럼 "found"에만 관심이 있을 때 유용해요.

표현식 목록이 주어지면, 변수들은 할당문(assignment statement)의 규칙에 따라 그 표현식들로 초기화돼요. 표현식이 주어지지 않으면 각 변수는 제로 값(zero value)으로 초기화됩니다. 그리고 타입이 있으면 그 타입이 적용되고, 타입이 없으면 초기화 값의 타입을 따라가요.

이때 타입이 없는 경우 좀 더 정확한 규칙이 있어요. 초기화 값이 타입이 없는 상수(untyped constant)라면 먼저 묵시적으로 기본 타입(default type)으로 변환되고, 타입이 없는 불리언 값이라면 bool로 변환돼요. 또 미리 선언된 식별자 nil은 타입이 명시되지 않은 변수의 초기화에는 쓸 수 없어요. 예시로 확인해 볼게요.

var d = math.Sin(0.5)  // d is float64
var i = 42             // i is int
var t, ok = x.(T)      // t is T, ok is bool
var n = nil            // illegal

math.Sinfloat64를 돌려주니 dfloat64가 되고, 정수 리터럴 42는 기본 타입인 int가 돼요. 타입 단언 x.(T)는 값과 성공 여부를 함께 돌려주니 tT, okbool이 되죠. 마지막 var n = nil은 타입을 알 수 없으니 불법(illegal)이에요.

한 가지 구현 제약(implementation restriction)도 기억해 둘게요. 컴파일러는 함수 본문 안에서 선언은 됐지만 한 번도 사용되지 않는 변수를 선언하는 것을 불법으로 만들 수 있어요. 즉 사용하지 않는 변수는 미리 제거하는 습관이 좋아요.

더 알아보기