ArrayList
와 비슷하다.arr1 := [...]int{1, 2, 3} // 배열
arr2 := [3]int{1, 2, 3} // 배열
slice1 := []int{1, 2, 3} // 슬라이스
slice2 := make([]int, len(arr1)) // 슬라이스
There are major differences between the ways arrays work in Go and C. In Go,
- Arrays are values. Assigning one array to another copies all the elements.
- In particular, if you pass an array to a function, it will receive a copy of the array, not a pointer to it.
- The size of an array is part of its type. The types [10]int and [20]int are distinct.
배열 포인터
, 길이
, 용량
세 필드로 이루어진 구조체다.cap
인 배열을 가리키고 있고, 복사를 위한 배열 이동이 일어나면 슬라이스는 다른 배열을 가리키게 된다.append
nums := make([]int, 3, 5)
nums = append(nums, 1)
copy
src := []int{1, 2, 3}
dst := src
dst
는 src
슬라이스 자체의 주소값만 복사된다.src
가 변경되면 dst
도 함께 변경된다.src := []int{1, 2, 3}
if n := copy(dest, src); n != len(src) {
fmt.Println("복사가 덜 됐습니다.")
}
len(src)
와 len(dst)
중 더 작은 값만큼만 복사된다.// 1번
src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src)
// 2번
src := []int{1, 2, 3}
var dst []int
dst := append(dst, src...)
insert
func Example_sliceInsert1() {
a := []int{0, 1, 2, 3, 4}
var res []int
n := 2
if n <= len(a) {
res = append(a[:n+1], a[n:]...)
res[n] = 100
} else {
res = append(a, 100)
}
fmt.Println(res)
// Output:
// [0 1 100 2 3 4]
}
func Example_sliceInsert2() {
a := []int{0, 1, 2, 3, 4}
n := 2
a = append(a, 1)
copy(a[n+1:], a[n:])
a[n] = 100
fmt.Println(a)
// Output:
// [0 1 100 2 3 4]
}
delete
O(N)
func Example_sliceDelete1() {
a := []int{0, 1, 2, 3, 4}
n := 2
a = append(a[:n], a[n+1:]...)
fmt.Println(a)
// Output:
// [0 1 3 4]
}
func Example_sliceDelete2() {
a := []int{0, 1, 2, 3, 4}
n := 2
k := 2 // 연속된 k개의 원소 삭제
a = append(a[:n], a[n+k:]...)
fmt.Println(a)
// Output:
// [0 1 4]
}
O(1)
func Example_sliceDelete3() {
a := []int{0, 1, 2, 3, 4}
n := 2
a[n] = a[len(a)-1]
a = a[:len(a)-1]
fmt.Println(a)
// Output:
// [0 1 4 3]
}
func Example_sliceDelete4() { // 이 경우 O(N)
a := []int{0, 1, 2, 3, 4}
n := 1
k := 4
split := len(a)-k
if n+k > split {
split = n+k
}
copy(a[n:n+k], a[split:])
a = a[:len(a)-k]
fmt.Println(a)
// Output:
// [0]
}
삭제 대상 슬라이스 내부에 포인터가 있는 경우 메모리 누수가 발생한다.
슬라이스를 잘라내도 사용하는 배열(메모리)은 그대로라 GC 대상에서 제외된다. 이 때 배열 원소가 포인터인 경우 그 포인터가 가리키는 객체도 유효하다고 판단되어 메모리 공간을 차지하고 GC되지 않기 때문에 누수가 발생한다.
따라서 아래와 같이 nil
로 지워줘야 한다.
copy(a[i:], a[i+k:])
for i := 0; i < k; i++ {
a[len(a)-1-i] = nil
}
a = a[:len(a)-k]