mirror of
https://github.com/alrayyes/wiki.git
synced 2024-11-23 03:56:23 +00:00
289 lines
4.5 KiB
Markdown
289 lines
4.5 KiB
Markdown
---
|
|
id: 8b5fb822-d1ad-46de-9299-37e3d3f5108c
|
|
title: Golang slices
|
|
---
|
|
|
|
# Basics
|
|
|
|
A slice is a dynamically sized, flexible view into the elements of an
|
|
array. Apparently they are much more common than arrays. Initialization
|
|
is pretty straight forward:
|
|
|
|
``` go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
func main() {
|
|
primes := [6]int{2, 3, 5, 7, 11, 13}
|
|
|
|
var s []int = primes[1:4]
|
|
fmt.Println(s)
|
|
}
|
|
```
|
|
|
|
Slices are like references. Change something in the slice and the
|
|
[array](20200828182327-arrays) it references also changes
|
|
|
|
``` go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
func main() {
|
|
names := [4]string{
|
|
"John",
|
|
"Paul",
|
|
"George",
|
|
"Ringo",
|
|
}
|
|
fmt.Println(names)
|
|
|
|
a := names[0:2]
|
|
b := names[1:3]
|
|
fmt.Println(a, b)
|
|
|
|
b[0] = "XXX"
|
|
fmt.Println(a, b)
|
|
fmt.Println(names)
|
|
}
|
|
```
|
|
|
|
Slices can contain any type, including other slices:
|
|
|
|
``` go
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
// Create a tic-tac-toe board.
|
|
board := [][]string{
|
|
[]string{"_", "_", "_"},
|
|
[]string{"_", "_", "_"},
|
|
[]string{"_", "_", "_"},
|
|
}
|
|
|
|
// The players take turns.
|
|
board[0][0] = "X"
|
|
board[2][2] = "O"
|
|
board[1][2] = "X"
|
|
board[1][0] = "O"
|
|
board[0][2] = "X"
|
|
|
|
for i := 0; i < len(board); i++ {
|
|
fmt.Printf("%s\n", strings.Join(board[i], " "))
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
# Slice literals
|
|
|
|
A slice literal is like an array, but without the length, so we add more
|
|
stuff to it later
|
|
|
|
``` go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
func main() {
|
|
q := []int{2, 3, 5, 7, 11, 13}
|
|
fmt.Println(q)
|
|
|
|
r := []bool{true, false, true, true, false, true}
|
|
fmt.Println(r)
|
|
|
|
s := []struct {
|
|
i int
|
|
b bool
|
|
}{
|
|
{2, true},
|
|
{3, false},
|
|
{5, true},
|
|
{7, true},
|
|
{11, false},
|
|
{13, true},
|
|
}
|
|
fmt.Println(s)
|
|
}
|
|
```
|
|
|
|
# Slice defaults
|
|
|
|
You can omit high and low bounds. As one would expect these default to 0
|
|
and slice length respectively
|
|
|
|
``` go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
func main() {
|
|
s := []int{2, 3, 5, 7, 11, 13}
|
|
|
|
s = s[1:4]
|
|
fmt.Println(s)
|
|
|
|
s = s[:2]
|
|
fmt.Println(s)
|
|
|
|
s = s[1:]
|
|
fmt.Println(s)
|
|
}
|
|
```
|
|
|
|
# Slice length and capacity
|
|
|
|
One can lookup slice length (length of the slice) and capacity (length
|
|
of the array the slice references)
|
|
|
|
``` go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
func main() {
|
|
s := []int{2, 3, 5, 7, 11, 13}
|
|
printSlice(s)
|
|
|
|
// Slice the slice to give it zero length.
|
|
s = s[:0]
|
|
printSlice(s)
|
|
|
|
// Extend its length.
|
|
s = s[:4]
|
|
printSlice(s)
|
|
|
|
// Drop its first two values.
|
|
s = s[2:]
|
|
printSlice(s)
|
|
}
|
|
|
|
func printSlice(s []int) {
|
|
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
|
|
}
|
|
```
|
|
|
|
# Nil slices
|
|
|
|
Empty slices are equal to `nil`. Maybe that's a good idea, maybe it
|
|
isn't. Typing this i'm too tired to give rational input to this
|
|
philosophical quagmire.
|
|
|
|
``` go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
func main() {
|
|
var s []int
|
|
fmt.Println(s, len(s), cap(s))
|
|
if s == nil {
|
|
fmt.Println("nil!")
|
|
}
|
|
}
|
|
```
|
|
|
|
# Make
|
|
|
|
Slices can be created with the `make` function, this way you can treat
|
|
them like arrays that we know and love.
|
|
|
|
``` go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
func main() {
|
|
a := make([]int, 5)
|
|
printSlice("a", a)
|
|
|
|
b := make([]int, 0, 5)
|
|
printSlice("b", b)
|
|
|
|
c := b[:2]
|
|
printSlice("c", c)
|
|
|
|
d := c[2:5]
|
|
printSlice("d", d)
|
|
}
|
|
|
|
func printSlice(s string, x []int) {
|
|
fmt.Printf("%s len=%d cap=%d %v\n",
|
|
s, len(x), cap(x), x)
|
|
}
|
|
```
|
|
|
|
# Append
|
|
|
|
New elements can be added to a slice with the
|
|
[append](https://golang.org/pkg/builtin/#append) function
|
|
|
|
``` go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
func main() {
|
|
var s []int
|
|
printSlice(s)
|
|
|
|
// append works on nil slices.
|
|
s = append(s, 0)
|
|
printSlice(s)
|
|
|
|
// The slice grows as needed.
|
|
s = append(s, 1)
|
|
printSlice(s)
|
|
|
|
// We can add more than one element at a time.
|
|
s = append(s, 2, 3, 4)
|
|
printSlice(s)
|
|
}
|
|
|
|
func printSlice(s []int) {
|
|
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
|
|
}
|
|
```
|
|
|
|
# Range
|
|
|
|
You can iterate over slices with `range`
|
|
|
|
``` go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
|
|
|
|
func main() {
|
|
for i, v := range pow {
|
|
fmt.Printf("2**%d = %d\n", i, v)
|
|
}
|
|
}
|
|
```
|
|
|
|
Index or value can be skipped by using `_`. In case you only want the
|
|
index, just omit the second variable entirely:
|
|
|
|
``` go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
func main() {
|
|
pow := make([]int, 10)
|
|
for i := range pow {
|
|
pow[i] = 1 << uint(i) // == 2**i
|
|
}
|
|
for _, value := range pow {
|
|
fmt.Printf("%d\n", value)
|
|
}
|
|
}
|
|
```
|