03/02 Study Daily record

손진성·2022년 2월 3일
0

Slice

  • go.dev/blog/slices-intro
  • slice consists of three things: a pointer to an array, length and capacity.
  • nil and empty slices (with 0 capacity) are not the same, but their observable behavior is the same.
  • All slices (slice headers) have different memory addresses
  • The nil slice has 0 data pointer
s := []int{3,4,5} // Initialize with values
s := []int{} // Initialize but with no values, memory is allocated
var s []int // Declare a slice but don't allocated memory just yet
s := make([]int,5,10) // Initialize with no values, allocate memory, specify the length of the slice and the capacity of the underlying array

Print result

[3 4 5]
[]
[]
[0 0 0 0 0]

Check length and capacity and Nil

	fmt.Println("s[] length:", len(s), "Capacity:", cap(s), "Nil:", nilchecker(s))
	fmt.Println("t[] length:", len(t), "Capacity:", cap(t), "Nil:", nilchecker(t))
	fmt.Println("u[] length:", len(u), "Capacity:", cap(u), "Nil:", nilchecker(u))
	fmt.Println("v[] length:", len(v), "Capacity:", cap(v), "Nil:", nilchecker(v))
}

func nilchecker(s []int) bool {
	if s == nil {
		return true
	} else {
		return false
	}
}

Print result

s[] length: 3 Capacity: 3 Nil: false
t[] length: 0 Capacity: 0 Nil: false
u[] length: 0 Capacity: 0 Nil: true
v[] length: 5 Capacity: 10 Nil: false
  • go.dev/play/p/QDcrCLRevyC
func main() {
	a := []int{1, 2, 3, 4, 5, 6}
	b := a[2:4]
	c := a[:3]
	d := a[3:]
	fmt.Println("Slices a: ", a, " b:", b, " c:", c, " d:", d)
	fmt.Println("Capacity of b:", cap(b))
}

Print result

Slices a:  [1 2 3 4 5 6]  b: [3 4]  c: [1 2 3]  d: [4 5 6]
Capacity of b: 4
  • Because d took a slices from 2, 4 capacities were allocated(from the start to the end of the array).
  • It has access to the rest of the underlying array that it originally presented(a[0:5]).
  • go.dev/play/p/aC_sZuihZcb
func main() {
	s1 := []int{1, 2, 3, 4, 5, 6}
	fmt.Println("s1:", s1)
	s2 := s1[2:4]
	s2[0] = 10
	fmt.Println("s1:", s1)
}

Print result

s1: [1 2 3 4 5 6]
s1: [1 2 10 4 5 6]

- go.dev/play/p/_HJ04t2rP-L
- This is because, unlike an array, a slice does not copy a value, but refers to the address value referenced by the slice itself. But in the same situation, the array is initialized by simply copying the values


```go
func main() {
	s1 := []int{1, 2, 3, 4, 5, 6}
	fmt.Println("s1:", s1)
	s2 := make([]int, 2)
	n := copy(s2, s1[2:4])
	fmt.Println("Number of items copied: ", n)
	s2[0] = 10
	fmt.Println("s1:", s1)
	fmt.Println("s2:", s2)
}
s1: [1 2 3 4 5 6]
Number of items copied:  2
s1: [1 2 3 4 5 6]
s2: [10 4]
  • copy function returns qty of items copied
  • changed s2[0] couldn't affect s1. because we used copy function.
var s = make([]int, 3)
n := copy(s, []int{0, 1, 2, 3}) // n == 3, s == []int{0, 1, 2}
  • because s len is 3, so it cannot take more than 3.
  • So n also took 3 as copied numbers.

Copy from a slice to itself

s := []int{0, 1, 2}
n := copy(s, s[1:]) // n == 2, s == []int{1, 2, 2}
  • If copy itself, The last slice was allocated to the end.

Memory leaking

func main() {
	subslice := testSubSlice()
	fmt.Println(subslice, " length: ", "remaining underlying array: ", subslice[:cap(subslice)])
}

func testSubSlice() []int {
	s := []int{1, 2, 3, 4, 5, 6, 8, 9, 10}
	return s[1:4]
}

Print result

[2 3 4]  length:  remaining underlying array:  [2 3 4 5 6 8 9 10]
  • subslice should have only s[1:4] = {2,3,4].

Prevent leaking memory by using copy function


func main() {
	subslice := testSubSlice()
	fmt.Println(subslice, " length: ", "remaining underlying array: ", subslice[:cap(subslice)])
}

func testSubSlice() []int {
	s := []int{1, 2, 3, 4, 5, 6, 8, 9, 10}
	sub := make([]int, 3)
	copy(sub, s[1:4])
	return sub
}

Print result

[2 3 4]  length:  remaining underlying array:  [2 3 4]
func main() {
	s1 := []int{1, 2, 3}
	s1 = append(s1, 4, 5, 6)
	s2 := []int{7, 8, 9}
	s1 = append(s1, s2...)
	fmt.Println(s1)
}

Print result

[1 2 3 4 5 6 7 8 9]
  • Triple dot converts slice to colletion of arguments.
  • Instead of adding a slice to a slice, elements are added to slice s1.

Slice tricks

-remove items => a = append(a[:i], a[j:]...)
-remove one item => a = append(a[:i], a[i+1]...)
-Cut if the slice contains pointers:

copy(a[i:], a[j:])
for k, n := len(a)-j+i, len(a); k<n; k++ {
	a[k] = nil // or the zero value of T
 }
 a = a[:len(a)-j+i]

-Delete if the slice contains pointers: a, a[len(a)-1] = append(a[:i]. a[i+1]...), nil

Code

func main() {
	a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	i := 2
	j := 4
	copy(a[i:], a[j:])
    fmt.Println(a, len(a))
	for k, n := len(a)-j+i, len(a); k < n; k++ {
		a[k] = 0 // or the zero value of T
	}
	a = a[:len(a)-j+i]
	fmt.Println(a, len(a))
}
[1 2 5 6 7 8 9 10 9 10] 10
[1 2 5 6 7 8 9 10] 8

Code

func main() {
	a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	a = append(a[:2], a[4:]...)
	fmt.Println(a)
}
[1 2 5 6 7 8 9 10]
profile
Gopyther

0개의 댓글