Golang: Slice
What is Slice
Slice is like Array but length can be changed. (Golang slice is essentially a reference to a segment of array. )
Syntax of Slice Type
[]type
-
Syntax for slice type, with each slot of type type.
[see Golang: Basic Types]
Example:var x []int
, declare a variable x of int slice type.
package main import "fmt" func main() { // declare var of type slice var ss []int // print the type fmt.Printf("%T", ss) // []int }
Literal Expression of Slice
[]type{v1, v2 …}
-
Create a slice with values. Example:
var ss = []int{9, 2, 6}
package main import "fmt" func main() { // slice var ss = []int{9, 2, 6} fmt.Printf("%v\n", ss) // [9 2 6] fmt.Printf("%T\n", ss) // []int }
Print Slice
Create slice with “make”
You can create a slice with make
. It lets you specify how many items to begin with, and capacity for growth.
make([]type, n)
-
Create a slice of n number of slots of type type, with default values of
nil
. [see Golang: Zero Value] n can be 0. make([]type, n, capacity)
-
With capacity of capacity number of slots. capacity defaults to the value of n.
Example:make([]int, 10, 1000)
Note: capacity is not necessary, because golang automatically grow the slice capacity when youappend(…)
beyond the capacity. However, capacity is there for efficiency reasons, because creating a new array with lots items is relatively slow. Best to always create a slice with expected max of items.
package main import "fmt" func main() { // 3 slots of int var s = make([]int, 3) fmt.Println(s) // [0 0 0] // 3 slots of int, capacity of 9 var s2 = make([]int, 3, 9) fmt.Println(s2) // [0 0 0] }
Length
len(s)
- Return the length of slice s.
Capacity
cap(s)
- Return the capacity.
Slice of Slice
s[a:b]
- Return a slice of s from index a to b. The a is included, The b is excluded. The result shares the same data with original. If you modify it, the original will also be modified.
s[:n]
-
Same as
s[0:n]
s[n:]
-
Same as
s[n:len(s)]
package main import "fmt" func main() { var s = []int{0, 1, 2, 3} // take a slice of values var x = s[1:3] fmt.Println(x) // [1 2] }
Here's a example where modifying the slice also modifies the original.
package main import "fmt" func main() { var s = []int{0, 1, 2, 3} // take a slice var x = s[1:3] // modify it x[0] = 99 // original also changed fmt.Printf("%v\n", s) // [0 99 2 3] }
Append to Slice
The append
is a critical function in golang.
It's used to append, prepend, join, slices, or delete elements in slice.
You need to pay attention whether it returns a new slice or just modify the original.
append(slice_x, new_item1, new_item2 …)
- Append new items to a slice, returns a new slice only if the result is more than the original slice's capacity.
(WARNING: if the original slice is a slice of slice, then result may not go beyond its capacity, therefore, the result is modified original slice. Meaning, change to the result also changes original slice.)
package main import "fmt" func main() { var s1 = []int{3, 5} var s2 = append(s1, 8, 9) fmt.Println(s2) // [3 5 8 9] // original not changed, in this case fmt.Println(s1) // [3 5] }
Append creates a new slice ONLY WHEN the result is beyond original capacity.
package main import "fmt" func main() { var x1 = []int{0, 1, 2, 3, 4, 5} var x2 = x1[:3] // [0 1 2] var x3 = append(x2, 22) fmt.Println(x3) // [0 1 2 22] // x1 is changed fmt.Println(x1) // [0 1 2 22 4 5] // -------------------------------------------------- // if the append added more items than the capacity of x1, then x1 will not be changed // now we do the above again to see var y1 = []int{0, 1, 2, 3, 4, 5} var y2 = y1[:3] // [0 1 2] var y3 = append(y2, 21, 22, 23, 24, 25) fmt.Println(y3) // [0 1 2 21 22 23 24 25] // y1 is not changed fmt.Println(y1) // [0 1 2 3 4 5] }
Join Slices
Use triple dots operator to turn a slice into function arguments,
then use append
.
append(slice_x, slice_y ...)
package main import "fmt" func main() { var s1 = []int{3, 5} var s2 = []int{6, 7} var s3 = append(s1, s2...) fmt.Println(s3) // [3 5 6 7] }
Append String as Byte Slice to Slice
Use triple dots operator to turn a string into byte slice,
then use append
.
append(slice_x, string ...)
Cut Slice (Delete Elements)
Use append
to delete elements, like this:
append(s[:i], s[j:]...)
- Delete from index i to j.
package main import "fmt" func main() { var x = []byte("0123456") x = append(x[:3], x[5:]...) fmt.Printf("%s\n", x) // 1236 }
Copy Slice
copy(dst, src)
-
Copy elements of slice from src to dst. The number of elements copied is the smaller of lengths of argument, whichever is shorter. It wipes the values in the dst slice starting at index 0. Return the number of items copied.
Arguments must be slice of the same type.
In the case of byte slice, the src can be a string too.
package main import "fmt" func main() { var x = []int{0, 1, 2, 3, 4, 5} var y = []int{99, 999} copy(y, x) fmt.Println(y) // [0 1] }
Example of copying shorter to longer:
package main import "fmt" func main() { var x = []int{99, 999} var y = []int{0, 1, 2, 3, 4, 5} copy(y, x) fmt.Println(y) // [99 999 2 3 4 5] }
Clear Slice
To clear slice, set it to nil
or set it to a slice of 0 length.
mySlice = nil
or
mySlice = mySlice[0:0]
The recommended way is to set to nil
.
Nested Slice
Slices can be nested. Just declare that the slots are also type slice.
var x [][]int
- Declare a nested slice of int type.
package main import "fmt" func main() { var x [][]int fmt.Println(x) // [] }
Nested Slice with Values
var y = [][]int{{3, 4}, {7}, {1, 2}}
- Declare nested slice, with initial values.
package main import "fmt" func main() { // y is slice of slice of int var y = [][]int{{3, 4}, {7, 8, 9}, {1, 2}} fmt.Println(y) // [[3 4] [7 8 9] [1 2]] }
Create Nested Slice with make
var ns = make([][]string, 2)
- Create a nested slice.
package main import "fmt" func main() { // nested slice. 2 items. each item is a slice of string var ns = make([][]string, 2) // fill the slots ns[0] = []string{"a", "b"} ns[1] = []string{"x", "y", "z"} fmt.Println(ns) // [[a b] [x y z]] }
Getting and setting values.
package main import "fmt" func main() { var ss = make([][]int, 2) ss[0] = []int{1, 2} ss[1] = []int{3, 4} ss[1][1] = 5 fmt.Println(ss) // [[1 2] [3 5]] }
Slice of Strings to String
strings.Join(slice, seperator)
- Join a Slice of Strings to one big string.
package main import "fmt" import "strings" // join slice of strings to one big string func main() { var sls = []string{"abc", "xyz"} var result = strings.Join(sls, ",") fmt.Printf("%v\n", result) // abc,xyz }
Loop Thru Slice
for i, v := range slice {…}
-
Loop thru slice, where i is current index and v the value.
If a variable is not used, name it
_
to stop compiler from complaining. Example:for _, v := range slice {…}
The_
is called blank identifier.
package main import "fmt" func main() { var s = []int{9, 2, 8, 61} for i, x := range s { fmt.Println(i, x) } } // 0 9 // 1 2 // 2 8 // 3 61