1. Slice
Slice Header 구조는 아래와 같다.
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
그래서 Copy하면 Len, Cap은 따로 움직일 수 있으나, Data pointer는 동일하다. (같은 Slice을 가르키지만, Len과 Cap이 다를 수 있다
Slice는 Cap이 부족하여 배열을 늘려야할 때, 2배씩 array의 길이를 늘린다.
func main() {
slice1 := []int{1, 2, 3}
slice1 = append(slice1, 500) // Size Doubled
fmt.Println("slice1:", slice1, len(slice1), cap(slice1))
}
2. Slicing
배열 또는 슬라이스의 일부를 집어내어 슬라이스로 표현하는 것 array[startIndex:endIndex] => 시작 인덱스 ~ 끝 인덱스 - 1 까지의 배열 일부를 나타낸다.
package main
import "fmt"
func main() {
array := [5]int{1, 2, 3, 4, 5}
slice := array[1:2]
fmt.Println("array:", array)
fmt.Println("slice:", slice, len(slice), cap(slice))
array[1] = 100
fmt.Println("After change second element")
fmt.Println("array:", array)
fmt.Println("slice:", slice, len(slice), cap(slice))
slice = append(slice, 500)
fmt.Println("After append 500")
fmt.Println("array:", array)
fmt.Println("slice:", slice, len(slice), cap(slice))
}
/* Result
❯ go run ex16.7.go
array: [1 2 3 4 5]
slice: [2] 1 4
After change second element
array: [1 100 3 4 5]
slice: [100] 1 4
After append 500
array: [1 100 500 4 5]
slice: [100 500] 2 4
*/
Python과 다르게 슬라이스를 정의할 때, 3번째 값은 Cap의 제한
a := []int{0, 1, 2, 3, 4}
s1 := s[1:3] // 1 ~ 2 인덱스 가져옴
s1 = append(s1, 99) // a = [0, 1, 2, 99, 4]!!!!
// 안전: cap을 딱 len 만큼만
s2 := a[1:3:3]
s2 = append(s2, 99) // cap 초과 -> 새 배열 할당, a는 그대로
Copy Slice
slice2 := make([]int, len(slice1))
for i, v := range slice1 {
slice2[i] = v
}
// More trendy
slice2 := make([]int, len(slice1))
copy(slice2, slice1) // copy(to, from)
Copy 명령어는 Len의 한계까지만 Copy한다. (Cap은 copy의 한계에 영향을 주지 않는다.)
func main() {
slice1 := []int{1, 2, 3, 4, 5}
slice2 := make([]int, 3, 10) // Len3, Cap 10
slice3 := make([]int, 10) // Len 10, Cap 10
cnt1 := copy(slice2, slice1)
cnt2 := copy(slice3, slice1)
fmt.Println(cnt1, slice2)
fmt.Println(cnt2, slice3)
}
// Copy의 주석을 보면 알 수 있다.
// The copy built-in function copies elements from a source slice into a
// destination slice. (As a special case, it also will copy bytes from a
// string to a slice of bytes.) The source and destination may overlap. Copy
// returns the number of elements copied, which will be the minimum of
// len(src) and len(dst).
// 마지막 줄을 보면 len(src) and len(dst) 중에 작은 값만큼만 복사된다.
/* Result
❯ go run ex16.9.go
3 [1 2 3]
5 [1 2 3 4 5 0 0 0 0 0]
*/
Sort
정렬은 Sort 하며, 원본 slice를 변경한다.
package main
import (
"fmt"
"sort"
)
func main() {
s := []int{5, 2, 6, 3, 1, 4}
sort.Ints(s)
fmt.Println(s)
}
구조체 슬라이스는 Len, Less, Swap 을 정의합니다.
type Student struct {
Name string
Age int
}
type Students []Student
func (s Students) Len() int { return len(s) }
func (s Students) Less(i, j, int) bool { return s[i].Age < s[j].Age }
func (s Students) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func main() {
s := []Student {
{"화랑", 31}, {"백두산", 52}, {"류", 42},
{"켄", 38}, {"송하나", 18}
}
sort.Sort(Students(s))
fmt.Println(s)
}