배열 사용하기

Golang 에서의 배열은 생성할 때 요소의 개수가 고정되어, 늘리거나 줄일 수 없는 등 길이가 변하지 않는 고정 길이 배열이다.

기본적으로 배열은 아래와 같은 방식들로 생성할 수 있다.

func main() {
    var arr1 [5]int = [5]int{1, 2, 3, 4, 5}
    var arr2 [5]int = [5]int{1, 2, 3}
    arr3 := [5]int{1, 2, 3, 4, 5}
    arr4 := [...]int{1, 2, 3}
    var arr5 = [5]int{0:10, 2:-10, 4:99}
}

arr1 의 경우 다른 변수 선언과 비슷하게 var 키워드에 변수명과 변수타입을 붙여주는데, 이 때 변수 타입 앞에 배열 원소의 개수를 대괄호로 묶어주면 된다.

변수 선언시에 들어가는 원소의 개수는 반드시 상수여야 한다(변수값 사용 불가).

arr2 는 같은 방식으로 배열을 선언하고 초기화하지만, 5개짜리 배열에 값을 3개로만 초기화하고 있다.

이런 경우에는 배열의 앞에서부터 순서대로 값을 할당해주고, 나머지 남는 공간들에 대해서는 각 타입별 기본값으로 초기화된다(int의 경우 0).

arr3 에서 배열 역시 := 를 통한 선언 및 초기화를 지원하는 걸 확인할 수 있고, 배열의 초기화는 동일한 방식이다.

arr4 는 원소의 개수에 … 을 사용함으로써, 초기화를 위해 입력된 원소의 개수만큼 배열의 크기를 맞춰준다.

마지막으로 arr5 처럼 특정 인덱스에 값을 지정해줄 수도 있다.

0번 인덱스에는 10, 2번 인덱스에는 -10, 4번 인덱스에는 99 를 넣는다는 뜻이 되며, 나머지 인덱스들에는 기본값을 할당해줌으로써 [10, 0, -10, 0, 99] 와 같이 생성된다.


두 배열의 크기와 타입이 같을 경우에는 원소값들을 복사할 수 있다.

배열은 실제로 메모리 공간 상에서 지정된 크기만큼의 연속된 공간들을 할당받아서 그 안에 값을 유지하고 있는 것이기 때문에, 크기가 같은 두 배열은 서로 다른 메모리 상에서 같은 크기만큼 공간을 가지고 있다는 뜻이다.

아래처럼 같은 크기의 배열을 만든 뒤 복사하면 메모리 공간 전체의 값을 가져다가 씌워버리는 것이기 때문에, 사실상 deep copy가 일어난다.

func main() {
    arr1 := [5]int{1, 2, 3, 4, 5}
    arr2 := [...]int{10, 20, 30, 40, 50}

    fmt.Println("arr1:", arr1)
    fmt.Println("arr2:", arr2)
    arr1 = arr2
    arr1[0] = -1
    fmt.Println("arr1 <- arr2")
    fmt.Println("arr1:", arr1)
    fmt.Println("arr2:", arr2)
}
$ go run test.go
arr1: [1 2 3 4 5]
arr2: [10 20 30 40 50]
arr1 <- arr2
arr1: [-1 20 30 40 50]
arr2: [10 20 30 40 50]

Go에서는 타입 검사를 강하게 하기 때문에, 모든 연산자에서 각각의 타입은 반드시 동일해야 한다.

그렇기 때문에 배열을 복사할때는 크기 뿐만 아니라 두 배열의 타입 역시 동일해야 한다.


n차원 배열은 그냥 배열과 사실 동일한 개념이다.

2차원 배열은 배열을 타입으로 갖는 배열이고, 3차원 배열은 2차원 배열을 타입으로 갖는 배열일 뿐이다.

그렇기 때문에 일반 배열과 같이, n-1 차원 배열이라는 원소들을 배열의 크기만큼 메모리에 가지고 있다.

예를 들어 2차원 배열의 경우는 아래처럼 사용하는데,

func main() {
   var arr2d [3][4]int = [3][4]int{
       {1, 2, 3, 4},
       {3, 4, 5, 6},
       {5, 6, 7, 8},    // 닫는 중괄호가 다른 줄에 위치할 경우 쉼표 필요!
   }

   for _, row := range arr2d {
       for _, v := range row {
           fmt.Print(v, " ")
       }
       fmt.Println()
   }
}
$ go run test.go
1 2 3 4 
3 4 5 6 
5 6 7 8 

arr2d 의 경우는 “길이가 4인 배열”을 하나의 원소로 가지며 그걸 3개 갖는 배열이기 때문에, 메모리에는 사실상 [int 4개] [int 4개] [int 4개] 의 공간을 차지하ㅑ는 것이다.

배열을 초기화하면서 위처럼 줄바꿈이 들어가는 경우에는, 닫는 중괄호가 같은 라인에 위치하지 않을 경우에는 반드시 ,를 넣어줘야 한다.

예를 들어 마지막에 {5, 6, 7, 8} 뒤에 쉼표를 찍지 않으면 에러가 발생하는데, 이는 항목이 늘어날 경우 발생할 수 있는 실수들에 대비해 만들어놓은 규칙이다.