배열 타입

배열 타입 (Array types)

배열은 같은 타입의 요소들을 번호를 붙여 차례대로 나열한 것이에요. 여기서 '같은 타입'이라는 점이 중요해요. 하나의 배열에는 서로 다른 타입을 섞어 넣을 수 없고, 오직 한 가지 타입의 요소만 담을 수 있어요. 이때 그 단일 타입을 배열의 요소 타입(element type) 이라고 불러요. 또 요소의 개수를 배열의 길이(length) 라고 하는데, 이 길이는 절대 음수가 될 수 없어요.

출처: Go Specification

본문

배열의 길이는 배열 타입 자체의 일부예요. 이 길이는 값으로 평가했을 때 int 타입의 값으로 표현 가능한(representable) 음이 아닌 상수(non-negative constant) 여야 해요. 다시 말해, 배열을 선언할 때 길이로 상수 표현식이 들어가야 하고, 그 값은 int로 나타낼 수 있어야 한다는 뜻이에요.

배열 a의 길이는 내장 함수 len으로 알아낼 수 있어요. 요소들은 정수 인덱스 0부터 len(a)-1까지의 번호로 접근할 수 있어요.

배열 타입은 항상 1차원이지만, 배열이 배열을 감싸는 방식으로 조합하면 다차원 타입을 만들 수 있어요. 예를 들어 아래처럼 중첩하면 2차원, 3차원 배열처럼 쓸 수 있죠.

[32]byte
[2*N] struct { x, y int32 }
[1000]*float64
[3][5]int
[2][2][2]float64  // same as [2]([2]([2]float64))

그런데 배열 타입 T에는 한 가지 제약이 있어요. T는 자기 자신(T)을 요소 타입으로 가질 수 없고, 배열이나 struct 타입만을 경유해 T를 요소로 포함하는 타입도 요소로 가질 수 없어요. 쉽게 말해, 배열이 자기 자신을 담는 순환 구조는 만들 수 없다는 거예요. 다만 그 순환을 포인터나 함수 타입, 슬라이스 같은 다른 타입이 끊어준다면 허용돼요.

아래 코드로 확인해 볼게요. 먼저 잘못된(무한한 크기가 되어버리는) 배열 타입들이에요.

// invalid array types
type (
	T1 [10]T1                 // element type of T1 is T1
	T2 [10]struct{ f T2 }     // T2 contains T2 as component of a struct
	T3 [10]T4                 // T3 contains T3 as component of a struct in T4
	T4 struct{ f T3 }         // T4 contains T4 as component of array T3 in a struct
)

T1은 자기 자신을 직접 요소로 가지고 있고, T2는 struct 안에서, T3T4는 서로를 struct와 배열로 얽혀서 포함하기 때문에 모두 유효하지 않아요. 반면 아래는 순환이 포인터나 함수 타입, 슬라이스에 의해 끊겨서 유효한 배열 타입이에요.

// valid array types
type (
	T5 [10]*T5                // T5 contains T5 as component of a pointer
	T6 [10]func() T6          // T6 contains T6 as component of a function type
	T7 [10]struct{ f []T7 }   // T7 contains T7 as component of a slice in a struct
)

T5는 포인터(*T5)로, T6는 함수 타입(func() T6)으로, T7은 슬라이스([]T7)로 순환 구조를 끊어주고 있기 때문에 문제없이 선언할 수 있어요.

이 섹션의 구조를 EBNF로 나타내면 다음과 같아요.

ArrayType   = "[" ArrayLength "]" ElementType .
ArrayLength = Expression .
ElementType = Type .

더 알아보기

  • 배열 타입의 문법과 문법 요소는 Go Specification의 ArrayType, ArrayLength, ElementType 정의에서 직접 확인할 수 있어요.
  • 배열의 길이를 알아내는 len 내장 함수와, 요소에 접근하는 인덱스 표현식에 대해서는 각각 해당 섹션을 참고하면 좋아요.
  • 더 자주 쓰는 가변 길이 시퀀스인 슬라이스(slice) 는 배열과 어떤 관계가 있는지 다음 섹션에서 이어서 살펴볼게요.