Intro
A slice in Golang is an abstraction that sits on top of an array. An array normally has a set size and must be initialised with a size. A slice is a little more like an array in javascript or an ArrayList in Java.
A slice is a descriptor of an array segment. It consists of a pointer to the array, the length of the segment, and its capacity (the maximum length of the segment). The internals of a slice are quite clever and mean that working with a slice is as efficient as working with an array. Read more: slice internals.
It is unusual in Golang to use an array and for our needs it is unlikely you will need one, so we will focus on slices. As with maps a slice is not naturally thread safe. As with maps we will go over these things when we get to concurrency.
Define slice
As with a map there are two ways of making a slice.
1) Slice literals
package main
import "fmt"
func main (){
captains := []string{"Picard","Janeway","Kirk"} //the type the slice will hold must be specified
fmt.Println(captains)
}
2) As with maps you can use the make function
package main
import "fmt"
func main (){
captains := make([]string,3) //notice the second arg here, this is the initial length and is required in the case of a slice
captains[0] = "Picard"
captains[1] = "Janeway"
captains[2] = "Kirk"
fmt.Println(captains)
}
Slicing a slice
Slices can be re-sliced, creating a new slice value that points to the same array.
The expression s[lo:hi] evaluates to a slice of the elements from lo through hi-1, inclusive. Thus s[lo:lo] is empty and s[lo:lo+1] has one element.
Note: lo and hi would be integers representing indexes.
package main
import "fmt"
func main() {
mySlice := []int{2, 3, 5, 7, 11, 13}
fmt.Println(mySlice) // [2 3 5 7 11 13]
fmt.Println(mySlice[1:4]) // [3 5 7]
// missing low index implies 0
fmt.Println(mySlice[:3]) // [2 3 5]
// missing high index implies len(s)
fmt.Println(mySlice[4:]) // [11 13]
}
Appending to a slice
To add new items to a slice we use the built in append function. append takes the original slice as it’s first argument
and any number of follwing args to append to that slice. It returns the new slice to you.
package main
import "fmt"
func main (){
captains := make([]string,0) //notice the second arg here, this is the initial length
captains = append(captains,"Picard","Janeway","Kirk") //append takes any number of additions
fmt.Println(captains)
}
Appending slice to other slice
And you can also append a slice to another using an ellipsis:
package main
import "fmt"
func main() {
cities := []string{"San Diego", "Mountain View"}
otherCities := []string{"Santa Monica", "Venice"}
cities = append(cities, otherCities...)
fmt.Printf("%q", cities)
// ["San Diego" "Mountain View" "Santa Monica" "Venice"]
}
Note that the ellipsis is a built-in feature of the language that means that the element is a collection. We can’t append an element of type slice of strings ([]string) to a slice of strings, only strings can be appended. However, using the ellipsis (...) after our slice, we indicate that we want to append each element of our slice. Because we are appending strings from another slice, the compiler will accept the operation since the types are matching.
You obviously can’t append a slice of type []int to another slice of type []string.
Getting the length of a slice
This is the same as a map, you make use of the builtin len function.
package main
import "fmt"
func main (){
captains := []string{"Picard","Janeway","Kirk"} //the type the slice will hold must be specified
length := len(captains)
fmt.Println(length)
}
Iterate through a slice
Once again we will use the range key word. After all underneath every good map is an array.
package main
import "fmt"
func main (){
captains := []string{"Picard","Janeway","Kirk"}
for index,value := range captains{
fmt.Printf("index %d value %s",index,value)
}
}
Delete an item from a slice
To delete an item from a slice we need to get a new slice with the element removed. To do this we use the append function to append all the items but the one we don’t want.
package main
import "fmt"
func main (){
captains := []string{"Picard","Black Beard", "Janeway","Kirk"}
captains = append(captains[:1],captains[2:]...) //lets take a minute and go over this
fmt.Println(captains)
}
So what is happening here. It looks a little strange.
We are assigning the returned slice from append to the captains reciever.
Inside append we are appending everything after the [2] index to everything before the [1] first index. So cutting out the value at [1] [:1] before [2:] after.
The ... is how Golang declares a variadic argument. So can be read as every value including the one at the [2] index.
Nil slices
The zero value of a slice is nil. A nil slice has a length and capacity of 0.
package main
import "fmt"
func main() {
var z []int
fmt.Println(z, len(z), cap(z))
// [] 0 0
if z == nil {
fmt.Println("nil!")
}
// nil!
}
Reference
http://www.golangbootcamp.com/book/collection_types