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)
}