Slices 02-201
Issue with Implementing PrimeSieve() in Go
func PrimeSieve(n int) [n+1]bool {var isComposite [n+1]bool //ERROR!biggestPrime := 2for biggestPrime < n
for i:=2; i<=n/biggestPrime; i++ {isComposite[i+biggestPrime] = true
}biggestPrime++for biggestPrime<n &&isComposite[biggestPrime]{
biggestPrime++}
return isComposite}
Go only allows us to create an array of constant size.
var a []int// at this point a has the special value nil// and can’t be used as an arraya = make([]int, 10, 20)
0! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0!0! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10! 11! 12! 13! 14! 15! 16! 17! 18! 19!
Underlying array has size 20!
Length of this slice is 10!
A slice variable is declared by not specifying a size in []
Creates an array of size 20 with a slice of size 10 inside it.
Slices: Everything Arrays Should Be
Omitting the Third Parameter
var a []inta = make([]int, 10)// this is the same as make([]int, 10, 10)
We Can Still Change Items
var a []inta = make([]int, 10)a[3] = -18a[9] = 100a[10] = 1 //error: out of range
Passing a Variable as Slice Length
m := 100var b []stringb = make([]string, m) // this is OK!
Defining a Slice in One Line
m := 100b := make([]string, m) // this is OK!
String literals: a sequence of characters between “”
“Hi there”“😄”“1+㆔=4”“3.14159”
Integer literals: a sequence of digits 0…9
726402000734
bool (Boolean) literals: either true or false
truefalse
Unicode strings are supported.
Recall: Literals ... The Other Side of “=”
We can manually create slices (useful if you have a short list of data that may change):
Array and Slice Literals
var a = []float64{3.2, -30.1, 84.72, 62.0}var prime = []int{2,3,5,7,11}
var b = [3]float64{2.8, -30.1, 13.2}var odds = [4]int{1,3,5,7}
We can also use array literals (useful for a short list of data that is fixed):
Fixing PrimeSieve
func PrimeSieve(n int) []bool {isComposite := make([]bool, n+1) //Fixed!biggestPrime := 2for biggestPrime < n
for i:=2; i<=n/biggestPrime; i++ {isComposite[i+biggestPrime] = true
}biggestPrime++for biggestPrime<n && isComposite[biggestPrime]{
biggestPrime++}
return isComposite}
func Max(A [10000000]int) int { m := 0 for i := range A { if i == 0 || A[i] > m { m = A[i] } } return m}
func main() { var numbers [10000000]int
// fill numbers with random integers for i := range numbers { numbers[i] = rand.Int() }
fmt.Println(Max(numbers))}
A new array A is created and the contents from numbers is copied over (wasteful of memory).
Issue #2: Arrays Copied in Function Calls
Passing a Slice as an Argument
We can also pass a slice (of unknown length) as a function argument.
func Max(list []int) int {var m int = list[0]for i := range list {
if list[i] > m {m = list[i]
}}return m
}
Passing a Slice as an Argument
func Fudge1(list []int) {list[0] = 1
}
func Fudge2(list [100]int) {list[0] = 1
}
Passing a Slice as an Argument
func Fudge1(list []int) {list[0] = 1
}
Exercise: What is printed in main()?
func Fudge2(list [100]int) {list[0] = 1
}
func main() {list1 := make([]int, 100)var list2 [100]intFudge1(list1)Fudge2(list2)fmt.Println(list1[0], list2[0])
}
Passing a Slice as an Argument
func Fudge1(list []int) {list[0] = 1
}
Exercise: What is printed in main()?
func Fudge2(list [100]int) {list[0] = 1
}
func main() {list1 := make([]int, 100)var list2 [100]intFudge1(list1)Fudge2(list2)fmt.Println(list1[0], list2[0])
}
Answer: 1 0
Looping Over Both Indices and Elements
“range” also lets us loop over both the index and the elements of a slice.
func Max(list []int) int {var m intfor j, v := range list {
if j == 0 || v > m {m = v
}}return m
}
The Blank Identifier
func Sum(A []int) int { var result int for i, val := range A { result = result + val } return result}
Think: What is the issue here?
The Blank Identifier
func Sum(A []int) int { var result int for i, val := range A { result = result + val } return result}
Error! Variable i declared and never used.
The Blank Identifier
func Sum(A []int) int { var result int for i, val := range A { result = result + val } return result}
func Sum(A []int) int { var result int for _, val := range A { result = result + val } return result}
Error! Variable i declared and never used.
Blank identifier _ (single underscore) is useful when declaring a variable that is never used.
Recall: Substrings in Go
s := “Hi There!”fmt.Println(s[3:5]) // prints Thfmt.Println(s[1:]) // prints i There!fmt.Println(s[:4]) // prints Hi T
var str string = s[3:6]fmt.Println(str) // prints Thefmt.Println(str[0]) // prints T
H i T h e r e !0 1 2 3 4 5 6 7 8
“Subslicing” works in the same way.
s := make([]int, 10, 20)for i:=1; i<10; i++ {
s[i] = -i - 1}
array!
start! 0!end! 9!
-1! -2! -3! -4! -5! -6! -7! -8! -9! -10! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0!0! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10! 11! 12! 13! 14! 15! 16! 17! 18! 19!
Subslices: A Picture
s!
s := make([]int, 10, 20)for i:=1; i<10; i++ {
s[i] = -i - 1}var q []int = s[8:15]
array!
start! 0!end! 9!
array!
start! 8!end! 14!
-1! -2! -3! -4! -5! -6! -7! -8! -9! -10! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0!0! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10! 11! 12! 13! 14! 15! 16! 17! 18! 19!
Subslices: A Picture
s! q !
s := make([]int, 10, 20)for i:=1; i<10; i++ {
s[i] = -i - 1}var q []int = s[8:15]
array!
start! 0!end! 9!
array!
start! 8!end! 14!
-1! -2! -3! -4! -5! -6! -7! -8! -9! -10! 0! 0! 0! 0! 0! 0! 0! 0! 0! 0!0! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10! 11! 12! 13! 14! 15! 16! 17! 18! 19!
Subslices: A Picture
s! q !
len(q) == 7fmt.Println(q[0]) // -9fmt.Println(q[6]) // -15fmt.Println(q[15]) // ERRORs[8] == q[0]s[9] = 12 // now q[1] == 12 too!
Both slices refer to the same underlying array.
The append() and copy() Operations
s := make([]int, 10)s = append(s, 5)
0! 0! 0! 0! 0 0! 0! 0! 0 0! 50! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10
c := make([]int, 11)copy(c, s)
0! 0! 0! 0! 0 0! 0! 0! 0 0! 5!0! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10!
s!
c!