100 Go Mistakes and How to Avoid Them
Not understanding slice length and capacity (#20)
slice 의 length 와 capacity 를 이해하는 것은 고퍼에게 매우 중요한 정보다.
length
는 slice 에 있는 원소의 수capacity
는 해당 slice 가 가질 수 있는 사이즈make
함수를 사용해서 생성한다.// int 를 원소로 가지고, length=3, capactiy=6 인 슬라이스
s := make([]int, 3, 6)
fmt.Println(s) // [0 0 0]
s[1] = 1
fmt.Println(s) // [0 1 0]
s[3] = 3 // panic: runtime error: index out of range [3] with length 3
s = append(s, 3)
fmt.Println(s) // [0 1 0 3]
s = append(s, 4, 5)
fmt.Println(s) // [0, 2, 0, 4, 3, 4, 5]
s = append(s, 4, 5, 6)
fmt.Println(s) // [0 1 0 3 4 5 6]
append
함수를 사용append
를 통해 원소를 추가하다가 capacity 가 넘어가는 경우, go 에서는 기존 capacity 의 2배를 가지는 array 를 새로 생성하고 해당 array 에 append
로 받은 원소를 추가.s1 := make([]int, 3, 6) // Three-length, six-capacity slice
s2 := s1[1:3] // Slicing from indices 1 to 3
fmt.Println(s1) // [0, 0, 0]
fmt.Println(s2) // [0, 0]
s1[1] = 1
fmt.Println(s1) // [0, 1, 0]
fmt.Println(s2) // [1, 0]
s2 = append(s2, 2)
fmt.Println(s1) // [0, 1, 0]
fmt.Println(s2) // [1, 0, 2]
s2 = append(s2, 3)
s2 = append(s2, 4) // backing array 가 가득차는 경우
s2 = append(s2, 5)
type MyModel struct {
field1 string
field2 int
}
a := []MyModel{}
for _, m := range asdf {
a = append(a, m)
}
go를 처음 사용할 때 별 생각없이 이런 식으로 많이 사용했었는데 빈 값으로 초기화 됐기 때문에 array capacity doubling 과 메모리 재할당이 계속 일어나는 코드였을 것 같다. (인지하고서는 make
를 사용해서 선언해주기는 했지만)
하지만 capacity 를 2배씩 늘리고, 메모리를 재할당하고, slicing을 했을 때 같은 array 를 참조하고 이런 내용은 몰랐다.
기본적인 내용이지만 항상 숙지하고 습득해서 개발하도록 하자