[1. length]
- make() 를 이용해 Slice 를 생성 할 때, slice 의 길이를 명시한다.
- C++ std::vector 에서 resize() 와 같은 역할을 한다.
- built-in 함수 len() 을 이용해 Slice 의 length 를 얻을 수 있다.
- 1 이상의 length 가 할당 된 경우 [] 연산자를 통해 값에 접근 할 수 있다.
=> C++ vector 에서 resize() 후 [] 연산자로 container 를 업데이트 하는 방식 - ex) slice := make([]int, 10)
[2. capacity]
- make() 를 이용해 Slice 를 생성 할 때, slice 의 capacity 를 명시한다.
- C++ std::vector 에서 reserve() 와 같은 역할을 한다.
- built-in 함수 cap() 을 이용해 Slice 의 capacity 를 얻을 수 있다.
- Slice 의 capacity 가 1 이상이고 length 가 0 일 때, append() 를 이용해 slice 내 tail 쪽에 값 저장 시 Slice 내부 배열 주소가 바뀌지 않는다.
=> C++ vector 처럼 capacity 가 length 보다 큰 경우 이미 할당된 메모리에 데이터를 추가한다.
=> reserve() 후 push_back() 으로 값을 추가하는 방식 - ex) slice := make([]int, 0, 10)
[3. append]
- built-in 함수이다.
- slice 의 capacity 가 충분하지 않으면, reslice 된다.
새로 충분한 메모리를 할당하고, 기존 데이터를 복사시킨 후 추가한다는 의미로 보면 될 듯 - append 후 업데이트 된 slice 를 반환한다.
reslice 된다는 특성을 통해서 충분한 capacity 를 갖는 slice에 대해서 append 를 같은 지역내에서 사용할 때와 달리
call by value 형태로 다른 함수로 넘겨서 append 하는 것은 일반적으로 생각 할 수 있는 slice 내부 구조 처럼 의도한 대로 동작하지 않는다는 점을 아래 코드를 통해 확인 할 수 있다.
package main
import "fmt"
func appends(sl []int) {
fmt.Printf("%p ", &sl)
sl = append(sl, 1, 2, 3, 4, 5)
fmt.Printf("%p ", &sl)
fmt.Println(sl)
}
func main() {
sl := make([]int, 0, 10)
sl1 := make([]int, 0, 3)
appends(sl)
fmt.Printf("%p ", &sl)
fmt.Println(sl)
fmt.Println()
appends(sl1)
fmt.Printf("%p ", &sl1)
fmt.Println(sl1)
}
위 코드에서 main() 내 slice sl 은 충분한 capacity 를 갖고 있다.
따라서 appends() 함수에 call by value 로 넘겨도 내부 배열 포인터가 충분한 공간을 갖고 있으니,
다른 메모리 주소로 바뀌지 않을 것이라고 생각 할 수 있다.
그러나 출력 결과는 위 생각과 같지않다.
위 출력을 통해
함수 appends() 에서 sl 의 주소는 append() 후에 바뀌지 않는 것을 확인 할 수 있고, 값도 정상적으로 Push 되었음을 볼 수 있다.
그러나 main() 에서 sl 의 초기 capacity 가 10 이라는 것을 고려 할 때, 그 출력이 empty 한 것은 잘 이해가 가지 않는 부분이다.
따라서 위와 같은 형태로 slice 가 업데이트 될 필요가 있다면
아래와 같이 call by reference 형태로 작성해야 한다.
package main
import "fmt"
func appends(sl *[]int) {
fmt.Printf("%p ", &sl)
*sl = append(*sl, 1, 2, 3, 4, 5)
fmt.Printf("%p ", &sl)
fmt.Println(sl)
}
func main() {
sl := make([]int, 0, 10)
sl1 := make([]int, 0, 3)
appends(&sl)
fmt.Printf("%p ", &sl)
fmt.Println(sl)
fmt.Println()
appends(&sl1)
fmt.Printf("%p ", &sl1)
fmt.Println(sl1)
}
아니면 deep copy 를 하지 않는 것 같으니 아래와 같이 return 을 통해 업데이트 된 slice 를 전달 받는 구조로 할 수 있다.
package main
import "fmt"
func appends(sl []int) []int {
fmt.Printf("%p ", &sl)
sl = append(sl, 1, 2, 3, 4, 5)
fmt.Printf("%p ", &sl)
fmt.Println(sl)
return sl
}
func main() {
sl := make([]int, 0, 10)
sl1 := make([]int, 0, 3)
sl = appends(sl)
fmt.Printf("%p ", &sl)
fmt.Println(sl)
fmt.Println()
sl1 = appends(sl1)
fmt.Printf("%p ", &sl1)
fmt.Println(sl1)
}
[4. copy]
- built-in 함수이다.
- 복사한 element 의 개수를 반환한다.
=> source 와 destination 의 length 중 최소값이다. - source 와 destination 은 겹칠 수 있다.
'Go' 카테고리의 다른 글
GO111MODULE (0) | 2022.08.10 |
---|---|
go 패키지 설치, 관리 (0) | 2022.08.10 |
ubuntu go version update (0) | 2022.04.06 |
cgo (0) | 2022.03.19 |
Array & Slice (0) | 2022.02.07 |