12.2. 프로그램언어 고(Go)에서의 슬라이스 확장 및 축소

프로그램언어 고(Go)에서의 슬라이스 길이 확장 방법

프로그램언어 고(Go)에서 슬라이스의 길이를 확장하는 방법은 주로 append 함수를 사용하는 것입니다.

슬라이스는 크기가 동적으로 변화할 수 있는 배열과 유사한 자료구조입니다. 초기에 할당된 크기 이상으로 요소를 추가하면, 슬라이스는 자동으로 더 큰 메모리를 할당받아 크기를 늘려갑니다.


package main

import "fmt"

func main() {

    // 슬라이스 생성
    numbers := []int{1, 2, 3} 

    fmt.Println(len(numbers)) // 3

    // append 함수를 사용해 새로운 요소 추가
    numbers = append(numbers, 4, 5) 

    fmt.Println(len(numbers)) // 5

    fmt.Println(numbers) // [1 2 3 4 5]

}

위 예제코드에서 볼 수 있듯이, append 함수를 사용하여 슬라이스에 새로운 요소를 추가하면 슬라이스의 길이가 자동으로 늘어납니다.

append 함수는 기존 슬라이스 뒤에 새로운 요소를 추가하는 기능을 합니다. 추가되는 요소의 개수에 따라 슬라이스의 크기가 동적으로 확장됩니다.

따라서 프로그램언어 고(Go)에서 슬라이스의 길이를 늘리고 싶다면 append 함수를 활용하는 것이 가장 좋은 방법입니다. append 함수를 실행할 때마다 슬라이스 길이가 자동으로 조정되므로 편리합니다.

프로그램언어 고(Go)에서의 슬라이스 길이 축소 방법

프로그램언어 고(Go)에서 슬라이스의 길이를 축소하는 방법은 다음과 같습니다.


package main

import "fmt"

func main() {

    slice := []int{1, 2, 3, 4, 5}
    fmt.Println(slice)

    // 슬라이스의 길이를 축소
    slice = slice[:3]
    fmt.Println(slice)

}

요약하면, slice[a:b] 구문을 사용하여 기존 슬라이스의 일부를 잘라내어 새로운 슬라이스를 만드는 방법으로 구현합니다.

위 예제에서는 원본 슬라이스가 [1, 2, 3, 4, 5] 였지만 slice[:3]으로 길이를 3으로 제한하여 [1, 2, 3] 새 슬라이스를 만들었습니다.

여기서 주의할 점은 원본 슬라이스는 변경되지 않고, 새로운 슬라이스가 반환됩니다.

슬라이스의 길이를 늘이는 것도 비슷한 방식으로 작동합니다.


slice = slice[:cap(slice)] 

위 코드에서 cap() 함수를 사용하여 슬라이스의 용량까지 길이를 늘릴 수도 있습니다.

이처럼 고(Go)의 슬라이스는 길이 조절이 용이한 장점이 있습니다.

필요한 만큼의 데이터만 잘라서 사용할 수 있기 때문에 메모리 사용량 최적화에도 유용하다고 볼 수 있습니다.

프로그램언어 고(Go)에서의 슬라이스 용량 확장하기

슬라이스의 용량이 부족하면 새 슬라이스를 만들고 기존 슬라이스의 요소를 복사하는 방식으로 용량을 늘릴 수 있습니다.

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3}
    fmt.Println(len(slice), cap(slice))

    newSlice := append(slice, 4, 5)
    fmt.Println(len(newSlice), cap(newSlice))  
}

위 예제에서 기존 slice의 용량은 3입니다. 여기에 2개의 새 원소 4, 5를 추가하려고 합니다.
이 경우 기존 slice의 용량을 초과하므로 새로운 backing array가 할당되고 기존 slice의 내용이 복사됩니다.

append 함수를 사용할 때마다 이러한 작업이 반복되므로 비효율적일 수 있습니다. 이를 방지하고자 slice를 정의할 때 충분한 용량을 여유있게 잡아야 합니다.

slice := make([]int, 0, 1000)

위 코드 처럼 make 함수로 slice를 생성할 때 미리 큰 용량을 지정해주면 불필요한 backing array 복사를 방지할 수 있습니다.

당장 1000개가 필요한 것은 아니지만 추후 확장 가능성을 여유있게 고려하는 것이 좋습니다.

프로그램언어 고(Go)에서의 슬라이스 용량 축소하는 방법

슬라이스의 용량을 축소하는 방법에는 주로 copy 함수를 사용합니다. copy 함수를 사용하면 슬라이스를 복사할 때 실제 사용 중인 용량만큼 복사하여 새 슬라이스를 만들 수 있습니다.

예를 들어 다음과 같은 코드가 있다고 해보겠습니다.

package main

import "fmt"

func main() {
    slice := make([]int, 5, 10)
    copySlice := make([]int, 0, 5)

    for i := 0; i < 5; i++ {
        slice[i] = i 
    }

    copy(copySlice, slice)
    
    fmt.Println(len(slice), cap(slice))
    fmt.Println(len(copySlice), cap(copySlice)) 
}

여기서 slice 는 길이 5, 용량 10인 슬라이스입니다. 하지만 실제로는 0~4 인덱스까지만 사용 중입니다.
copySlice는 길이0, 용량5인 빈 슬라이스입니다.

copy 함수를 이용하여 slice를 copySlice에 복사하였습니다. 복사 결과 copySlice의 길이는 5가 되었고 용량은 5로 slice의 실제 사용 용량으로 축소되었습니다.

즉, copy 함수를 통해 불필요한 용량이 줄어든 새로운 슬라이스를 생성할 수 있습니다. 필요한 부분만 복사하기 때문에 메모리 사용량 측면에서 효율적입니다.

copy 함수 사용 시에는 dest 슬라이스와 src 슬라이스의 타입과元素 개수가 맞아야합니다. 복사되는 요소 개수는 dest의 길이를 넘을 수 없습니다.

이와 같이 Go언어의 copy 함수를 활용하면 슬라이스의 용량을 축소할 수 있습니다. 실제 사용 중인 용량만큼 새로운 슬라이스를 생성할 수 있어 유용합니다.

프로그램언어 고(Go)에서의 슬라이스 재할당 방법

프로그램언어 고(Go)에서 슬라이스는 참조타입입니다. 슬라이스를 다른 슬라이스에 할당하면 실제로는 같은 배열을 참조하게 됩니다.

슬라이스를 재할당하여 배열의 일부분만 참조하도록 변경할 수 있습니다. 이를 위해서는 copy 함수나 슬라이싱을 사용합니다.


package main

import "fmt"

func main() {

    arr := []int{1, 2, 3, 4, 5} 

    // 슬라이스 arr 참조
    slice := arr

    // slice를 재할당하여 arr[1:3] 배열 부분 참조
    slice = arr[1:3] 

    fmt.Println(slice) // [2 3] 출력

    // slice 변경해도 arr 값 변경 안됨
    slice[0] = 20
    fmt.Println(arr) // [1 2 3 4 5] 출력

}

위 예제에서 볼 수 있듯이 slice는 원래 arr 전체를 참조하고 있습니다.

slice = arr[1:3] 문장을 통해 slice를 재할당하여 arr의 일부분인 arr[1]과 arr[2]만 참조하도록 변경했습니다.

이제 slice의 값을 변경해도 기존의 arr 배열값은 영향을 받지 않습니다.

슬라이스를 재할당 없이 복사하려면 copy 함수를 사용할 수 있습니다.


arr := []int{1, 2, 3, 4, 5}
slice := make([]int, 2) 

copy(slice, arr[1:3]) // slice에 arr[1:3] 복사

slice[0] = 20 // 변경해도 arr값 영향 없음

fmt.Println(slice) // [20 3]
fmt.Println(arr) // [1 2 3 4 5]

copy 함수를 사용하면 새로운 슬라이스를 만들고 거기에 원하는 부분을 복사할 수 있습니다.

따라서 slice를 변경해도 기존 arr 값은 영향을 받지 않습니다.

이처럼 고(Go)에서는 슬라이스 재할당이나 복사를 통해 슬라이스를 수정하면서 기존 데이터와의 연결을 끊을 수 있습니다.

주의할 점은 슬라이스에 대한 복사나 재할당은 새로운 배열을 생성하는 것이 아니라 기존 배열을 참조하기 때문에 성능상 이점이 있다는 것입니다.

따라서 값 복사가 필요한 경우에만 슬라이스 재할당이나 복사를 사용하는 것이 좋습니다.

Leave a Comment