배열

Array

배열 역시 타입의 일종이다. 배열 작성 규칙은 다음과 같다.

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

ArrayLength에 대해서는 두 가지 단서가 붙는데, 음수일 수 없고, int 타입으로 표현 가능한 상수여야 한다.

이에 따라 다음과 같은 형태들을 배열로 사용 가능하다.

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

배열 요소 접근

배열 요소에 접근하기 위해서는 다른 언어들처럼 대괄호([]) 안에 0부터 시작하는 요소의 인덱스(index)를 쓴다.

var myArray [10]int
myArray[0] = 10

배열의 크기는 기본 함수(built-in function)인 len()을 이용해 구할 수 있다.

len(myArray) // = 10

만약 가용한 범위를 벗어난 요소 접근을 시도하면 다음과 같은 오류가 발생한다.

invalid array index 10 (out of bounds for 10-element array)

배열 초기화

배열을 초기화하기 위해서는 선언 후 반복문을 통해 각각의 요소에 값을 입력할 수도 있지만 이미 구조체 기초에서 살펴본 방식을 사용할 수도 있다. 관련 부분만 다시 정리하면 다음과 같다.

CompositeLit  = LiteralType LiteralValue .
LiteralType   = StructType | ArrayType | "[" "..." "]" ElementType |
                SliceType | MapType | TypeName .
LiteralValue  = "{" [ ElementList [ "," ] ] "}" .

변수 선언 후 =을 쓰고 위 방식으로 값을 입력하는데, 기본 사용법은 다음과 같다.

var myArray [3]int = [3]int {1, 2, 3}

LiteralType 중 ArrayType 뒤에 나오는 방식도 배열 초기화에 사용한다.

var myArray [3]int = [...]int {1, 2, 3}

...은 입력된 초기값의 개수에 따라 배열의 크기를 자동으로 지정해 주는 역할을 한다. 따라서 입력된 값의 개수와 선언된 배열의 크기가 다르면 다음과 같은 오류가 발생한다.

// var myArray [3]int = [...]int {1, 2, 3, 4}
cannot use [4]int literal (type [4]int) as type [3]int in assignment

배열과 배열 포인터

배열을 BaseType으로 하는 배열 포인터를 만들 수도 있다—포인터의 배열이 아닌 배열의 포인터이다. 배열 포인터를 만들기 위해서는 포인터에서 살펴본 것처럼 배열 타입 앞에 asterisk(*)를 붙여 포인터 타입으로 만들면 된다.

var myArray [3]int
var pMyArray *[3]int = &myArray

위와 같이 이미 존재하는 배열의 주소를 이용해 값을 할당할 수도 있고, new 함수를 이용해 동적 할당도 가능하다.

pMyArray := new([3]int)

Go가 C에 비해 한 가지 편리한 점은 많은 경우 포인터 타입을 다룰 때도 동일한 접근법을 사용할 수 있다는 점이다. 위 pMyArray에 C 방식으로 접근한다고 가정해 보자. pMyArray는 포인터이므로 다음과 같이 접근해야 한다.

*(pMyArray)[0]
len(*pMyArray)

Go도 동일한 방식으로 접근할 수 있지만, 다음과 같이 myArray를 접근할 때와 동일한 방식으로도 접근 가능하다.

pMyArray[0]
len(pMyArray)