🔥 슬라이스 길이와 용량

505자
7분

슬라이스에는 길이용량 이라는 두 가지 속성이 있습니다. 길이는 슬라이스에 포함된 요소의 개수를 나타내고, 용량은 슬라이스가 내부적으로 가리키고 있는 배열에서 슬라이스가 시작되는 위치부터 배열의 끝까지 남아있는 요소의 개수를 나타냅니다.

슬라이스는 내부적으로 배열을 가리키고 있습니다. 이 배열을 "슬라이스의 기본 배열"이라고 부릅니다. 슬라이스의 용량은 이 기본 배열에서 슬라이스가 시작되는 위치부터 배열의 끝까지 요소의 개수를 나타냅니다.

예를 들어, 다음과 같이 배열을 생성하고 슬라이스를 만들어 보겠습니다.

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

위 코드에서 arr은 길이가 5인 배열입니다. slicearr의 인덱스 1부터 3 전까지의 요소를 가리키는 슬라이스입니다.

이 경우 slice의 길이는 2입니다. 왜냐하면 슬라이스에 포함된 요소가 2개(arr[1]arr[2])이기 때문이죠.

하지만 slice의 용량은 4입니다. 슬라이스가 arr의 인덱스 1부터 시작하고, arr의 끝까지 남아있는 요소의 개수가 4개(arr[1], arr[2], arr[3], arr[4])이기 때문입니다.

즉, 슬라이스의 용량은 슬라이스가 시작되는 위치부터 슬라이스의 기본 배열의 끝까지 남아있는 요소의 개수를 나타낸다고 할 수 있습니다.

슬라이스 s의 길이와 용량은 len(s)cap(s) 표현식을 사용하여 얻을 수 있습니다. 아래 예제 코드를 통해 슬라이스의 길이와 용량을 확인해 보겠습니다.

package main
 
import "fmt"
 
func main() {
	s := []int{2, 3, 5, 7, 11, 13} // 초기 슬라이스 생성
	printSlice(s)                 // 슬라이스 정보 출력
 
	s = s[:0]       // 슬라이스의 길이를 0으로 설정
	printSlice(s)   // 길이가 0인 슬라이스 정보 출력
 
	s = s[:4]       // 슬라이스의 길이를 4로 확장
	printSlice(s)   // 길이가 4인 슬라이스 정보 출력
 
	s = s[2:]       // 슬라이스의 첫 2개 요소 제거
	printSlice(s)   // 첫 2개 요소가 제거된 슬라이스 정보 출력
}
 
func printSlice(s []int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
 
go

위 코드를 실행하면 다음과 같은 결과를 얻을 수 있습니다.

len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
text

초기 슬라이스 s는 길이와 용량이 모두 6입니다. 슬라이스 s는 내부적으로 길이가 6인 배열을 가리키고 있습니다.

s[:0]을 사용하여 슬라이스의 길이를 0으로 설정하면, 슬라이스는 빈 상태가 되지만 여전히 원래 배열을 가리키고 있기 때문에 용량은 그대로 유지됩니다.

s[:4]를 사용하여 슬라이스의 길이를 4로 확장하면, 슬라이스는 원래 배열의 첫 4개 요소를 포함하게 됩니다. 이때 용량은 여전히 6입니다.

s[2:]를 사용하여 슬라이스의 첫 2개 요소를 제거하면, 슬라이스는 원래 배열의 세 번째 요소부터 시작하는 부분 슬라이스가 됩니다. 이때 길이는 2이고, 용량은 슬라이스가 시작되는 위치부터 배열의 끝까지 남아있는 요소의 개수인 4로 줄어듭니다.

슬라이스는 재슬라이싱(re-slicing)을 통해 길이를 확장할 수 있습니다. 단, 확장된 길이가 용량을 초과하면 안 됩니다. 만약 슬라이스의 길이를 용량 이상으로 확장하려고 하면 런타임 에러가 발생할 거예요.

아래는 슬라이스의 길이를 용량 이상으로 확장하려고 할 때 발생하는 에러를 보여주는 예제 코드입니다.

package main
 
import "fmt"
 
func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)
 
	s = s[:cap(s)+1] // 슬라이스의 길이를 용량 이상으로 확장하려고 함
	printSlice(s)    // 런타임 에러 발생
}
 
func printSlice(s []int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
 
go

이 코드를 실행하면 다음과 같은 런타임 에러가 발생합니다.

len=6 cap=6 [2 3 5 7 11 13]
panic: runtime error: slice bounds out of range [:7] with capacity 6
text

슬라이스의 길이와 용량을 이해하는 것은 Go 프로그래밍에서 매우 중요합니다. 슬라이스가 내부적으로 어떤 배열을 가리키고 있는지, 그리고 슬라이스의 길이와 용량이 어떻게 결정되는지를 잘 이해하고 적절하게 사용하면 효율적이고 안전한 코드를 작성할 수 있습니다.