add: slice internals backing array and slice header
This commit is contained in:
		| @@ -17,18 +17,9 @@ func main() { | |||||||
| 	// think of this as search results of a search engine. | 	// think of this as search results of a search engine. | ||||||
| 	// it could have been fetched from a database | 	// it could have been fetched from a database | ||||||
| 	items := []string{ | 	items := []string{ | ||||||
| 		"pacman", | 		"pacman", "mario", "tetris", "doom", | ||||||
| 		"mario", | 		"galaga", "frogger", "asteroids", "simcity", | ||||||
| 		"tetris", | 		"metroid", "defender", "rayman", "tempest", | ||||||
| 		"doom", |  | ||||||
| 		"galaga", |  | ||||||
| 		"frogger", |  | ||||||
| 		"asteroids", |  | ||||||
| 		"simcity", |  | ||||||
| 		"metroid", |  | ||||||
| 		"defender", |  | ||||||
| 		"rayman", |  | ||||||
| 		"tempest", |  | ||||||
| 		"ultima", | 		"ultima", | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								16-slices/09-slice-internals-2-slice-header/1-theory/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								16-slices/09-slice-internals-2-slice-header/1-theory/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  |  | ||||||
|  | 	s "github.com/inancgumus/prettyslice" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	// | ||||||
|  | 	// each int element is 4 bytes (on 64-bit) | ||||||
|  | 	// | ||||||
|  | 	// let's say the ages point to 1000th. | ||||||
|  | 	// ages[1:] will point to 1004th | ||||||
|  | 	// ages[2:] will point to 1008th and so on. | ||||||
|  | 	// | ||||||
|  | 	// they all will be looking at the same | ||||||
|  | 	// backing array. | ||||||
|  | 	// | ||||||
|  |  | ||||||
|  | 	ages := []int{35, 15, 25} | ||||||
|  | 	red, green := ages[0:1], ages[1:3] | ||||||
|  |  | ||||||
|  | 	s.Show("ages", ages) | ||||||
|  | 	s.Show("red", red) | ||||||
|  | 	s.Show("green", green) | ||||||
|  |  | ||||||
|  | 	fmt.Println(red[0]) | ||||||
|  | 	// fmt.Println(red[1]) // error | ||||||
|  | 	// fmt.Println(red[2]) // error | ||||||
|  |  | ||||||
|  | 	{ | ||||||
|  | 		var ages []int | ||||||
|  | 		s.Show("nil slice", ages) | ||||||
|  |  | ||||||
|  | 		// or just: | ||||||
|  | 		s.Show("nil slice", []int(nil)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -19,7 +19,7 @@ type collection []string // #2 | |||||||
| 
 | 
 | ||||||
| // go is pass by copy | // go is pass by copy | ||||||
| // only the slice header is copied: 3 integer fields (24 bytes) | // only the slice header is copied: 3 integer fields (24 bytes) | ||||||
| // think of passing an array with millions of elements. | // think of passing an array with millions of elements instead. | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
| 	// SliceHeader lives here: | 	// SliceHeader lives here: | ||||||
							
								
								
									
										60
									
								
								16-slices/exercises/16-internals-backing-array-fix/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								16-slices/exercises/16-internals-backing-array-fix/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"math/rand" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // --------------------------------------------------------- | ||||||
|  | // EXERCISE: Fix the backing array problem | ||||||
|  | // | ||||||
|  | //  You receive numbers from an API. After you're done working | ||||||
|  | //  with it, the API needs to continue using those numbers. | ||||||
|  | // | ||||||
|  | //  But your program changes the numbers (changes the API's slice). | ||||||
|  | // | ||||||
|  | //  Fix the program so that your program doesn't modify | ||||||
|  | //  the original numbers. | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // RESTRICTION | ||||||
|  | // | ||||||
|  | //  Fix your problem only in the designated area of the code below. | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // EXPECTED OUTPUT | ||||||
|  | // | ||||||
|  | //  Mine         : [-50 -100 -150] | ||||||
|  | //  Original nums: [56 89 15] | ||||||
|  | // | ||||||
|  | //  Note: Original nums may vary (they're random) | ||||||
|  | //        But your slice should look like the above (mine slice) | ||||||
|  | // | ||||||
|  | //        Yes, it should output only three numbers for the both slices! | ||||||
|  | // | ||||||
|  | // --------------------------------------------------------- | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	// API returns random numbers in an int slice | ||||||
|  | 	rand.Seed(time.Now().UnixNano()) | ||||||
|  | 	nums := rand.Perm(100) | ||||||
|  |  | ||||||
|  | 	// ---------------------------------------- | ||||||
|  | 	// RESTRICTIONS — ONLY ADD YOUR CODE HERE | ||||||
|  | 	// | ||||||
|  | 	mine := nums | ||||||
|  | 	// | ||||||
|  | 	// ---------------------------------------- | ||||||
|  |  | ||||||
|  | 	mine[0], mine[1], mine[2] = -50, -100, -150 | ||||||
|  | 	fmt.Println("Mine         :", mine) | ||||||
|  | 	fmt.Println("Original nums:", nums[:3]) | ||||||
|  | } | ||||||
| @@ -0,0 +1,35 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"math/rand" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	rand.Seed(time.Now().UnixNano()) | ||||||
|  | 	nums := rand.Perm(100) | ||||||
|  |  | ||||||
|  | 	// ---------------------------------------- | ||||||
|  | 	// breaks the connection: | ||||||
|  | 	// mine and nums now have different backing arrays | ||||||
|  |  | ||||||
|  | 	// verbose solution: | ||||||
|  | 	// var mine []int | ||||||
|  | 	// mine = append(mine, nums[:3]...) | ||||||
|  |  | ||||||
|  | 	// better solution (almost the same thing): | ||||||
|  | 	mine := append([]int(nil), nums[:3]...) | ||||||
|  | 	// ---------------------------------------- | ||||||
|  |  | ||||||
|  | 	mine[0], mine[1], mine[2] = -50, -100, -150 | ||||||
|  | 	fmt.Println("Mine         :", mine) | ||||||
|  | 	fmt.Println("Original nums:", nums[:3]) | ||||||
|  | } | ||||||
							
								
								
									
										52
									
								
								16-slices/exercises/17-internals-backing-array-sort/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								16-slices/exercises/17-internals-backing-array-sort/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // --------------------------------------------------------- | ||||||
|  | // EXERCISE: Sort the backing array | ||||||
|  | // | ||||||
|  | //  1. Sort only the middle 3 items. | ||||||
|  | // | ||||||
|  | //  2. All the slices should see your change. | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // RESTRICTION | ||||||
|  | // | ||||||
|  | //  Do not sort manually. Sort by slicing then by using the sort package. | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // EXPECTED OUTPUT | ||||||
|  | // | ||||||
|  | //  Original: [pacman mario tetris doom galaga frogger asteroids simcity metroid defender rayman tempest ultima] | ||||||
|  | // | ||||||
|  | // Sorted  : [pacman mario tetris doom galaga asteroids frogger simcity metroid defender rayman tempest ultima] | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // HINT: | ||||||
|  | // | ||||||
|  | //   Middle items are         : [frogger asteroids simcity] | ||||||
|  | // | ||||||
|  | //   After sorting they become: [asteroids frogger simcity] | ||||||
|  | // | ||||||
|  | // --------------------------------------------------------- | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	items := []string{ | ||||||
|  | 		"pacman", "mario", "tetris", "doom", "galaga", "frogger", | ||||||
|  | 		"asteroids", "simcity", "metroid", "defender", "rayman", | ||||||
|  | 		"tempest", "ultima", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Println("Original:", items) | ||||||
|  | 	fmt.Println() | ||||||
|  | 	fmt.Println("Sorted  :", items) | ||||||
|  | } | ||||||
| @@ -0,0 +1,33 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"sort" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	items := []string{ | ||||||
|  | 		"pacman", "mario", "tetris", "doom", "galaga", "frogger", | ||||||
|  | 		"asteroids", "simcity", "metroid", "defender", "rayman", | ||||||
|  | 		"tempest", "ultima", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Println("Original:", items) | ||||||
|  |  | ||||||
|  | 	mid := len(items) / 2 | ||||||
|  | 	smid := items[mid-1 : mid+2] | ||||||
|  |  | ||||||
|  | 	// sorting the smid will affect the items | ||||||
|  | 	// as well. their backing array is the same. | ||||||
|  | 	sort.Strings(smid) | ||||||
|  |  | ||||||
|  | 	fmt.Println() | ||||||
|  | 	fmt.Println("Sorted  :", items) | ||||||
|  | } | ||||||
							
								
								
									
										115
									
								
								16-slices/exercises/18-internals-slice-header/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								16-slices/exercises/18-internals-slice-header/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"runtime" | ||||||
|  | 	"runtime/debug" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // --------------------------------------------------------- | ||||||
|  | // EXERCISE: Observe the memory allocations | ||||||
|  | // | ||||||
|  | //  In this exercise, your goal is to observe the memory allocation | ||||||
|  | //  differences between arrays and slices. | ||||||
|  | // | ||||||
|  | //  You will create, assign arrays and slices then you will print | ||||||
|  | //  the memory usage of your program on each step. | ||||||
|  | // | ||||||
|  | //  Please follow the instructions inside the code. | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // EXPECTED OUTPUT | ||||||
|  | // | ||||||
|  | //  Note that, your memory usage numbers may vary. These are on my | ||||||
|  | //  own system. However, the size of the arrays and slices should be | ||||||
|  | //  the same on your own system as well (if you're on 64-bit machine). | ||||||
|  | // | ||||||
|  | // | ||||||
|  | //  <<< initial memory usage >>> | ||||||
|  | //          > Memory Usage: 104 KB | ||||||
|  | //  <<< after declaring an array >>> | ||||||
|  | //          > Memory Usage: 78235 KB | ||||||
|  | //  <<< after copying the array >>> | ||||||
|  | //          > Memory Usage: 156365 KB | ||||||
|  | //  <<< inside passArray >>> | ||||||
|  | //          > Memory Usage: 234495 KB | ||||||
|  | //  <<< after slicings >>> | ||||||
|  | //          > Memory Usage: 234497 KB | ||||||
|  | //  <<< inside passSlice >>> | ||||||
|  | //          > Memory Usage: 234497 KB | ||||||
|  | // | ||||||
|  | //  Array's size : 80000000 bytes. | ||||||
|  | //  Array2's size: 80000000 bytes. | ||||||
|  | //  Slice1's size: 24 bytes. | ||||||
|  | //  Slice2's size: 24 bytes. | ||||||
|  | //  Slice3's size: 24 bytes. | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // HINTS | ||||||
|  | // | ||||||
|  | //  I've declared a few function to help you. | ||||||
|  | // | ||||||
|  | //    report function prints the memory usage. | ||||||
|  | //    Just call it with a message that matches to the expected output. | ||||||
|  | // | ||||||
|  | //    passArray function accepts a [size]int array, so you can pass it | ||||||
|  | //    your array. It automatically prints the memory usage. | ||||||
|  | // | ||||||
|  | //    passSlice function accepts an int slice, so you can pass it | ||||||
|  | //    your one of your slices. It automatically prints the memory usage. | ||||||
|  | // | ||||||
|  | // --------------------------------------------------------- | ||||||
|  |  | ||||||
|  | const size = 1e7 | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	// stops the gc: prevents cleaning up the memory | ||||||
|  | 	debug.SetGCPercent(-1) | ||||||
|  |  | ||||||
|  | 	// run the program to see what this prints | ||||||
|  | 	report("initial memory usage") | ||||||
|  |  | ||||||
|  | 	// 1. allocate an array with 10 million int elements | ||||||
|  | 	//    this array's size is equal to ~80MB | ||||||
|  | 	//    hint: use the `size` constant | ||||||
|  | 	// | ||||||
|  | 	// 2. print the memory usage | ||||||
|  |  | ||||||
|  | 	// 3. copy the array to a new array (just assign) | ||||||
|  | 	// 4. print the memory usage | ||||||
|  |  | ||||||
|  | 	// 5. pass the array to passArray function | ||||||
|  |  | ||||||
|  | 	// 6. convert the array to a slice (by slicing) | ||||||
|  | 	// 7. slice only the first 1000 elements of the array | ||||||
|  | 	// 8. slice only the elements of the array between 1000 and 10000 | ||||||
|  | 	// 9. print the memory usage | ||||||
|  |  | ||||||
|  | 	// 10. pass the one of the slices to passSlice function | ||||||
|  |  | ||||||
|  | 	// 11. print the sizes of the arrays and slices | ||||||
|  | 	//     hint: use the unsafe.Sizeof function | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // observe that passing an array affects the memory usage dramatically | ||||||
|  | // | ||||||
|  | // passes [size]int array — about 80MB! | ||||||
|  | func passArray(items [size]int) { | ||||||
|  | 	items[0] = 100 | ||||||
|  | 	report("inside passArray") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // observe that passing a slice doesn't affect the memory usage | ||||||
|  | // | ||||||
|  | // only passes 24-bytes of slice header | ||||||
|  | func passSlice(items []int) { | ||||||
|  | 	items[0] = 100 | ||||||
|  | 	report("inside passSlice") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func report(msg string) { | ||||||
|  | 	var m runtime.MemStats | ||||||
|  | 	runtime.ReadMemStats(&m) | ||||||
|  | 	fmt.Printf("<<< %s >>>\n", msg) | ||||||
|  | 	fmt.Printf("\t> Memory Usage: %v KB\n", m.Alloc/1024) | ||||||
|  | } | ||||||
| @@ -0,0 +1,62 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"runtime" | ||||||
|  | 	"runtime/debug" | ||||||
|  | 	"unsafe" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const size = 1e7 | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	// stops the gc: prevents cleaning up the memory | ||||||
|  | 	debug.SetGCPercent(-1) | ||||||
|  |  | ||||||
|  | 	report("initial memory usage") | ||||||
|  |  | ||||||
|  | 	var array [size]int | ||||||
|  | 	report("after declaring an array") | ||||||
|  |  | ||||||
|  | 	array2 := array | ||||||
|  | 	report("after copying the array") | ||||||
|  |  | ||||||
|  | 	passArray(array) | ||||||
|  |  | ||||||
|  | 	slice1 := array[:] | ||||||
|  | 	slice2 := array[1e3:] | ||||||
|  | 	slice3 := array[1e3:1e4] | ||||||
|  | 	report("after slicings") | ||||||
|  |  | ||||||
|  | 	passSlice(slice3) | ||||||
|  |  | ||||||
|  | 	fmt.Println() | ||||||
|  | 	fmt.Printf("Array's size : %d bytes.\n", unsafe.Sizeof(array)) | ||||||
|  | 	fmt.Printf("Array2's size: %d bytes.\n", unsafe.Sizeof(array2)) | ||||||
|  | 	fmt.Printf("Slice1's size: %d bytes.\n", unsafe.Sizeof(slice1)) | ||||||
|  | 	fmt.Printf("Slice2's size: %d bytes.\n", unsafe.Sizeof(slice2)) | ||||||
|  | 	fmt.Printf("Slice3's size: %d bytes.\n", unsafe.Sizeof(slice3)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func passArray(items [size]int) { | ||||||
|  | 	items[0] = 100 | ||||||
|  | 	report("inside passArray") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func passSlice(items []int) { | ||||||
|  | 	report("inside passSlice") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func report(msg string) { | ||||||
|  | 	var m runtime.MemStats | ||||||
|  | 	runtime.ReadMemStats(&m) | ||||||
|  | 	fmt.Printf("<<< %s >>>\n", msg) | ||||||
|  | 	fmt.Printf("\t> Memory Usage: %v KB\n", m.Alloc/1024) | ||||||
|  | } | ||||||
| @@ -42,3 +42,13 @@ These are warm-up exercises that will reinforce your knowledge of slices. | |||||||
| 2. **[Slicing by arguments](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/14-slicing-by-args)** | 2. **[Slicing by arguments](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/14-slicing-by-args)** | ||||||
|  |  | ||||||
| 3. **[Slicing the Housing Prices](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/15-slicing-housing-prices)** | 3. **[Slicing the Housing Prices](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/15-slicing-housing-prices)** | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ## Exercises Level IV - Internals | ||||||
|  |  | ||||||
|  | 1. **[Fix the backing array problems](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/16-internals-backing-array-fix)** | ||||||
|  |  | ||||||
|  | 2. **[Sort the backing array](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/17-internals-backing-array-sort)** | ||||||
|  |  | ||||||
|  | 3. **[Observe the memory allocations](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/18-internals-slice-header)** | ||||||
|   | |||||||
							
								
								
									
										131
									
								
								16-slices/questions/4-backing-array.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								16-slices/questions/4-backing-array.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | |||||||
|  | # Backing Array Quiz | ||||||
|  |  | ||||||
|  | ## Where does a slice store its elements? | ||||||
|  | 1. In the slice value | ||||||
|  | 2. In a global backing array that is shared by all the slices | ||||||
|  | 3. In a backing array that is specific to a slice | ||||||
|  | 4. In a backing array that the slice references *CORRECT* | ||||||
|  |  | ||||||
|  | > **1:** A slice value doesn't store any elements. It's just a simple data structure. | ||||||
|  | >  | ||||||
|  | > **2:** There is not a global backing array. | ||||||
|  | >  | ||||||
|  | > **3:** A backing array can be shared among slices. It may not be specific to a slice. | ||||||
|  | >  | ||||||
|  | > **4:** Yep! A slice stores its elements in a backing that the slice references (or points to). | ||||||
|  | >  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## When you slice a slice, what value does it return? | ||||||
|  | ```go | ||||||
|  | // example: | ||||||
|  | s := []string{"i'm", "a", "slice"} | ||||||
|  | s[2:] // <-- slicing | ||||||
|  | ``` | ||||||
|  | 1. It returns a new slice value with a new backing array | ||||||
|  | 2. It returns the existing slice value with a new backing array | ||||||
|  | 3. It returns a new slice value with the same backing array *CORRECT* | ||||||
|  |  | ||||||
|  | > **3:** Yes! Slicing returns a new slice that references to some segment of the same backing array. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Why is slicing and indexing a slice efficient? | ||||||
|  | 1. Slices are fast | ||||||
|  | 2. Backing arrays are contiguous in memory *CORRECT* | ||||||
|  | 3. Go uses clever algorithms | ||||||
|  |  | ||||||
|  | > **2:** Yes. A slice's backing array is contiguous in memory. So, accessing an element of a slice is very fast. Go can look at a specific memory location to find an element's value very fast. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Which one is the backing array of "slice2"? | ||||||
|  | ```go | ||||||
|  | arr := [...]int{1, 2, 3} | ||||||
|  | slice1 := arr[2:3] | ||||||
|  | slice2 := slice1[:1] | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 1. arr *CORRECT* | ||||||
|  | 2. slice1 | ||||||
|  | 3. slice2 | ||||||
|  | 4. A hidden backing array | ||||||
|  |  | ||||||
|  | > **1:** Yes! When a slice is created by slicing an array, that array becomes the backing array of that slice. | ||||||
|  | >  | ||||||
|  | > **4:** Nope. That only happens when a slice doesn't being created from an array. | ||||||
|  | > | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Which one is the backing array of "slice"? | ||||||
|  | ```go | ||||||
|  | arr := [...]int{1, 2, 3} | ||||||
|  | slice := []int{1, 2, 3} | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 1. arr | ||||||
|  | 2. slice1 | ||||||
|  | 3. slice2 | ||||||
|  | 4. A hidden backing array *CORRECT* | ||||||
|  |  | ||||||
|  | > **1:** Nope, the slice hasn't created by slicing an array. | ||||||
|  | >  | ||||||
|  | > **4:** Yes! A slice literal always creates a new hidden array. | ||||||
|  | > | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Which answer is correct for the following slices? | ||||||
|  | ```go | ||||||
|  | slice1 := []int{1, 2, 3} | ||||||
|  | slice2 := []int{1, 2, 3} | ||||||
|  | ``` | ||||||
|  | 1. Their backing array is the same. | ||||||
|  | 2. Their backing arrays are different. *CORRECT* | ||||||
|  | 3. They don't have any backing arrays. | ||||||
|  |  | ||||||
|  | > **2:** That's right. A slice literal always creates a new backing array. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Which answer is correct for the following slices? | ||||||
|  | ```go | ||||||
|  | slice1 := []int{1, 2, 3} | ||||||
|  | slice2 := []int{1, 2, 3} | ||||||
|  | slice3 := slice1[:] | ||||||
|  | slice4 := slice2[:] | ||||||
|  | ``` | ||||||
|  | 1. slice1 and slice2 have the same backing arrays. | ||||||
|  | 2. slice1 and slice3 have the same backing arrays. *CORRECT* | ||||||
|  | 3. slice1 and slice4 have the same backing arrays. | ||||||
|  | 4. slice3 and slice4 have the same backing arrays. | ||||||
|  |  | ||||||
|  | > **2:** Yep! A slice that is being created by slicing shares the same backing with the sliced slice. Here, slice3 is being created from slice1. That is also true for slice2 and slice4. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## What does the backing array of the nums slice look like? | ||||||
|  | ```go | ||||||
|  | nums := []int{9, 7, 5, 3, 1} | ||||||
|  | nums = nums[:1] | ||||||
|  | 	 | ||||||
|  | fmt.Println(nums) // prints: [9] | ||||||
|  | ``` | ||||||
|  | 1. [9 7 5 3 1] *CORRECT* | ||||||
|  | 2. [7 5 3 1] | ||||||
|  | 3. [9] | ||||||
|  | 4. [] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## What does this code print? | ||||||
|  | ```go | ||||||
|  | arr   := [...]int{9, 7, 5, 3, 1} | ||||||
|  | nums  := arr[2:] | ||||||
|  | nums2 := nums[1:] | ||||||
|  |  | ||||||
|  | arr[2]++ | ||||||
|  | nums[1]  -= arr[4] - 4 | ||||||
|  | nums2[1] += 5 | ||||||
|  |  | ||||||
|  | fmt.Println(nums) | ||||||
|  | ``` | ||||||
|  | 1. [5 3 1] | ||||||
|  | 2. [6 6 6] *CORRECT* | ||||||
|  | 3. [9 7 5] | ||||||
|  |  | ||||||
|  | > **2:** Yes! Because the backing array of `nums` and `nums2` is the same: `arr`. See the explanation here: https://play.golang.org/p/xTy0W0S_8PN | ||||||
							
								
								
									
										90
									
								
								16-slices/questions/5-slice-header.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								16-slices/questions/5-slice-header.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | |||||||
|  | # Slice Header Quiz | ||||||
|  |  | ||||||
|  | ## What is a slice header? | ||||||
|  | 1. The first element of a slice value | ||||||
|  | 2. The first element of the backing array | ||||||
|  | 3. A tiny data structure that describes all or some part of a backing array *CORRECT* | ||||||
|  | 4. A data structure that contains the elements of a slice | ||||||
|  |  | ||||||
|  | > **3:** Yes! It's just a tiny data structure with three numeric fields. | ||||||
|  | >  | ||||||
|  | > **4:** A slice doesn't contain any elements on its own. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## What are the fields of a slice value? | ||||||
|  | 1. Pointer, length, and capacity *CORRECT* | ||||||
|  | 2. Length and capacity | ||||||
|  | 3. Only a pointer | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Which slice value does the following slice header describe? | ||||||
|  | SLICE HEADER: | ||||||
|  | + Pointer : 100th | ||||||
|  | + Length  : 5 | ||||||
|  | + Capacity: 10 | ||||||
|  |  | ||||||
|  | Assume that the backing array is this one: | ||||||
|  | ```go | ||||||
|  | var array [10]string | ||||||
|  | ``` | ||||||
|  | 1. array[5:] | ||||||
|  | 2. array[:5] *CORRECT* | ||||||
|  | 3. array[3:] | ||||||
|  | 4. array[100:] | ||||||
|  |  | ||||||
|  | > **1**: This slice's capacity is 5, it can only see the elements beginning with the 6th element. | ||||||
|  | >  | ||||||
|  | > **2**: That's right. `array[:5]` returns a slice with the first 5 elements of the `array` (len is 5), but there are 5 more elements in the backing array of that slice, so in total its capacity is 10. | ||||||
|  | >  | ||||||
|  | > **3**: This slice's capacity is 7, it can only see the elements beginning with the 4th element. | ||||||
|  | >  | ||||||
|  | > **4**: This is an error. The backing array doesn't have 100 elements. | ||||||
|  | >  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Which one is the slice header of the following slice? | ||||||
|  | ```go | ||||||
|  | var tasks []string | ||||||
|  | ``` | ||||||
|  | 1. Pointer: 0, Length: 0, Capacity: 0 *CORRECT* | ||||||
|  | 2. Pointer: 10, Length: 5, Capacity: 10 | ||||||
|  | 3. Pointer: 0, Length: 1, Capacity: 1 | ||||||
|  |  | ||||||
|  | > **1:** A nil slice doesn't have backing array, so all the fields are equal to zero. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## What is the total memory usage of this code? | ||||||
|  | ```go | ||||||
|  | var array [1000]int64 | ||||||
|  |  | ||||||
|  | array2 := array | ||||||
|  | slice := array2[:] | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 1. 1024 bytes | ||||||
|  | 2. 2024 bytes | ||||||
|  | 3. 3000 bytes | ||||||
|  | 4. 16024 bytes *CORRECT* | ||||||
|  |  | ||||||
|  | > **4:** `array` is 1000 x int64 (8 bytes) = 8000 bytes. Assigning an array copies all its elements, so `array2` adds additional 8000 bytes. A slice doesn't store anything on its own. Here, it's being created from array2, so it doesn't allocate a backing array as well. A slice header's size is 24 bytes. So in total: This program allocates 16024 bytes. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## What value does this code pass to the sort.Ints function? | ||||||
|  | ```go | ||||||
|  | nums := []int{9, 7, 5, 3, 1} | ||||||
|  | sort.Ints(nums) | ||||||
|  | ``` | ||||||
|  | 1. [9 7 5 3 1] — All the values of the nums slice | ||||||
|  | 2. A pointer to the backing array of the nums slice | ||||||
|  | 3. A pointer, length and capacity as three different arguments | ||||||
|  | 4. The slice header that is stored in the nums variable *CORRECT* | ||||||
|  |  | ||||||
|  | > **1:** No, a slice value doesn't contain any elements. So it cannot pass the elements. | ||||||
|  | >  | ||||||
|  | > **2:** Sorry but not only that. | ||||||
|  | >  | ||||||
|  | > **3:** Nope. Remember, they are packed in a tiny data structure called the ....? | ||||||
|  | >  | ||||||
|  | > **4:** Yep! A slice value is a slice header (pointer, length and capacity). A slice variable stores the slice header. | ||||||
|  | >  | ||||||
|  |  | ||||||
| @@ -5,3 +5,5 @@ | |||||||
| * [Appending](2-appending.md) | * [Appending](2-appending.md) | ||||||
|  |  | ||||||
| * [Slicing](3-slicing.md) | * [Slicing](3-slicing.md) | ||||||
|  |  | ||||||
|  | * [Backing Array](4-backing-array.md) | ||||||
| @@ -1,21 +0,0 @@ | |||||||
| // For more tutorials: https://blog.learngoprogramming.com |  | ||||||
| // |  | ||||||
| // Copyright © 2018 Inanc Gumus |  | ||||||
| // Learn Go Programming Course |  | ||||||
| // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ |  | ||||||
| // |  | ||||||
|  |  | ||||||
| package main |  | ||||||
|  |  | ||||||
| import s "github.com/inancgumus/prettyslice" |  | ||||||
|  |  | ||||||
| func main() { |  | ||||||
| 	ages := []int{35, 15, 25} |  | ||||||
| 	first, last := ages[0:1], ages[1:3] |  | ||||||
|  |  | ||||||
| 	s.Show("ages", ages) |  | ||||||
| 	s.Show("first", first) |  | ||||||
| 	s.Show("last", last) |  | ||||||
|  |  | ||||||
| 	s.Show("nil slice", []int(nil)) |  | ||||||
| } |  | ||||||
		Reference in New Issue
	
	Block a user