Slices 02-201
Issue with Implementing PrimeSieve() in Go func PrimeSieve(n int) [n+1]bool { var iscomposite [n+1]bool //ERROR! biggestprime := 2 for 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.
Slices: Everything Arrays Should Be A slice variable is declared by not specifying a size in [] var a []int // at this point a has the special value nil // and can t be used as an array a = make([]int, 10, 20) Creates an array of size 20 with a slice of size 10 inside it. 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! Length of this slice is 10! Underlying array has size 20!
Omitting the Third Parameter var a []int a = make([]int, 10) // this is the same as make([]int, 10, 10)
We Can Still Change Items var a []int a = make([]int, 10) a[3] = -18 a[9] = 100 a[10] = 1 //error: out of range
Passing a Variable as Slice Length m := 100 var b []string b = make([]string, m) // this is OK!
Defining a Slice in One Line m := 100 b := make([]string, m) // this is OK!
Recall: Literals... The Other Side of = Integer literals: a sequence of digits 0 9 72 6402 000734 String literals: a sequence of characters between Hi there 1+ =4 3.14159 Unicode strings are supported. bool (Boolean) literals: either true or false true false
Array and Slice Literals We can manually create slices (useful if you have a short list of data that may change): var a = []float64{3.2, -30.1, 84.72, 62.0 var prime = []int{2,3,5,7,11 We can also use array literals (useful for a short list of data that is fixed): var b = [3]float64{2.8, -30.1, 13.2 var odds = [4]int{1,3,5,7
Fixing PrimeSieve func PrimeSieve(n int) []bool { iscomposite := make([]bool, n+1) //Fixed! biggestprime := 2 for biggestprime < n for i:=2; i<=n/biggestprime; i++ { iscomposite[i+biggestprime] = true biggestprime++ for biggestprime<n && iscomposite[biggestprime]{ biggestprime++ return iscomposite
Issue #2: Arrays Copied in Function Calls 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).
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]int Fudge1(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 Answer: 1 0 func main() { list1 := make([]int, 100) var list2 [100]int Fudge1(list1) Fudge2(list2) fmt.println(list1[0], list2[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 int for 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 Error! Variable i declared and never used. func Sum(A []int) int { var result int for _, val := range A { result = result + val return result 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 Th fmt.println(s[1:]) // prints i There! fmt.println(s[:4]) // prints Hi T var str string = s[3:6] fmt.println(str) fmt.println(str[0]) // prints The // prints T H i T h e r e! 0 1 2 3 4 5 6 7 8 Subslicing works in the same way.
Subslices: A Picture s := make([]int, 10, 20) for i:=1; i<10; i++ { s[i] = -i - 1 s! 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 := make([]int, 10, 20) for i:=1; i<10; i++ { s[i] = -i - 1 var q []int = s[8:15] s! q! array! array! start! 0! start! 8! end! 9! 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 := make([]int, 10, 20) for i:=1; i<10; i++ { s[i] = -i - 1 var q []int = s[8:15] s! q! array! array! start! 0! start! 8! end! 9! 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! Both slices refer to the same underlying array. len(q) == 7 fmt.println(q[0]) // -9 fmt.println(q[6]) // -15 fmt.println(q[15]) // ERROR s[8] == q[0] s[9] = 12 // now q[1] == 12 too!
The append() and copy() Operations s := make([]int, 10) s = append(s, 5) 0! 0! 0! 0! 0 0! 0! 0! 0 0! 5 0! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10 s! 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! c!