├── README.md └── docs ├── 01-getting-started └── 01-introduction-to-go.md ├── 02-data-types-and-variables ├── 01-static-vs-dynamic-typed-languages.md ├── 02-number-boolean-and-string.md ├── 03-variables.md ├── 04-data-types-and-variables.md └── 05-constants.md ├── 03-operators-and-flow-control ├── 01-comparison-operators.md ├── 02-arithmetic-operators.md ├── 03-logical-operators.md ├── 04-assignment-operators.md ├── 05-bitwise-operators.md ├── 06-if-else-and-elseif-statements.md ├── 07-switch-statement.md └── 08-looping-with-for.md ├── 04-arrays-slices-and-maps ├── 01-arrays.md ├── 02-slices.md ├── 03-maps.md └── 04-arrays-slices-and-maps.md ├── 05-using-functions.md ├── 01-function-syntax.md ├── 02-return-types-multiple-named-variadic.md ├── 03-recursive-functions.md ├── 04-anonymous-functions.md ├── 05-high-order-functions.md └── 06-functions.md ├── 06-pointers ├── 01-pointers.md └── 02-pointers-in-functions.md ├── 07-struct-methods-and-interfaces ├── 01-struct.md ├── 02-struct-and-methods.md └── 03-interfaces.md └── 08-additional-content └── 01-how-do-slices-really-work.md /README.md: -------------------------------------------------------------------------------- 1 | # golang 2 | 3 | This repo contains all lab walkthroughs for the [golang](https://kodekloud.com/courses/golang/) course. 4 | 5 | For the Advanced golang solutions, go [here](https://github.com/kodekloudhub/advanced-golang). 6 | 7 | Note: 8 | 9 | Due to differences in formatting ordered lists between github and the labs, please read multiple choice selections in the solutions as follows: 10 | 11 | * 1. A 12 | 1. B 13 | 1. C 14 | 1. D 15 | 16 | 17 | * 01 - Getting Started 18 | * [Lab: Introduction to Go](./docs/01-getting-started/01-introduction-to-go.md) 19 | * 02 - Data Types and Variables 20 | * [Lab: Static vs Dynamic Typed Languages](./docs/02-data-types-and-variables/01-static-vs-dynamic-typed-languages.md) 21 | * [Lab: Numbers, Boolean and String](./docs/02-data-types-and-variables/02-number-boolean-and-string.md) 22 | * [Lab: Variables](./docs/02-data-types-and-variables/03-variables.md) 23 | * [Lab: Data types and Variables](./docs/02-data-types-and-variables/04-data-types-and-variables.md) 24 | * [Lab: Constants](./docs/02-data-types-and-variables/05-constants.md) 25 | * 03 - Operators and Flow Control 26 | * [Lab: Comparison Operators](./docs/03-operators-and-flow-control/01-comparison-operators.md) 27 | * [Lab: Arithmetic Operators](./docs/03-operators-and-flow-control/02-arithmetic-operators.md) 28 | * [Lab: Logical Operators](./docs/03-operators-and-flow-control/03-logical-operators.md) 29 | * [Lab: Assignment Operators](./docs/03-operators-and-flow-control/04-assignment-operators.md) 30 | * [Lab: Bitwise Operators](./docs/03-operators-and-flow-control/05-bitwise-operators.md) 31 | * [Lab: if-else and else if statements](./docs/03-operators-and-flow-control/06-if-else-and-elseif-statements.md) 32 | * [Lab: Switch Statement](./docs/03-operators-and-flow-control/07-switch-statement.md) 33 | * [Lab: Looping with for](./docs/03-operators-and-flow-control/08-looping-with-for.md) 34 | * 04 - Arrays, Slices and Maps 35 | * [Lab: Arrays](./docs/04-arrays-slices-and-maps/01-arrays.md) 36 | * [Lab: Slices](./docs/04-arrays-slices-and-maps/02-slices.md) 37 | * [Lab: Maps](./docs/04-arrays-slices-and-maps/03-maps.md) 38 | * [Lab: Arrays, Slices and Maps](./docs/04-arrays-slices-and-maps/04-arrays-slices-and-maps.md) 39 | * 05 - Using Functions 40 | * [Lab: Function Syntax](./docs/05-using-functions.md/01-function-syntax.md) 41 | * [Lab: Return Types - Multiple, Named, Variadic](./docs/05-using-functions.md/02-return-types-multiple-named-variadic.md) 42 | * [Lab: Recursive Functions](./docs/05-using-functions.md/03-recursive-functions.md) 43 | * [Lab: Anonymous Functions](./docs/05-using-functions.md/04-anonymous-functions.md) 44 | * [Lab: High Order Functions](./docs/05-using-functions.md/05-high-order-functions.md) 45 | * [Lab: Functions](./docs/05-using-functions.md/06-functions.md) 46 | * 06 - Pointers 47 | * [Lab: Pointers](./docs/06-pointers/01-pointers.md) 48 | * [Lab: Pointers in Functions](./docs/06-pointers/02-pointers-in-functions.md) 49 | * 07 - Struct, Methods and Interfaces 50 | * [Lab: Struct](./docs/07-struct-methods-and-interfaces/01-struct.md) 51 | * [Lab: Struct and Methods](./docs/07-struct-methods-and-interfaces/02-struct-and-methods.md) 52 | * [Lab: Interfaces](./docs/07-struct-methods-and-interfaces/03-interfaces.md) 53 | 54 | # Bonus Content 55 | 56 | * [How do slices really work?](./docs/08-additional-content/01-how-do-slices-really-work.md) -------------------------------------------------------------------------------- /docs/01-getting-started/01-introduction-to-go.md: -------------------------------------------------------------------------------- 1 | # Lab: Introduction to Go 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-introduction-to-go/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | Where was the Go programming language designed ? 9 | 10 | * VMware 11 | * Facebook 12 | * Google 13 | * Microsoft 14 | 15 |
16 | Reveal 17 | 18 | > Google 19 | 20 |
21 |
22 | 23 | 1.
24 | Go was created to support the following 25 | 26 | 1. The ease of programming of an interpreted, dynamically typed language. 27 | 1. For creating web pages easily. 28 | 1. Provide the efficiency and safety of a statically typed, compiled language. 29 | 1. Aimed to be modern, with support for networked and multicore computing. 30 | 31 |
32 | Reveal 33 | 34 | > A, C, D 35 | 36 | Although Go is *not* dynamically typed or interpreted, the language was created with simplicity in mind to make it feel like using a language like Python which is these things. 37 | 38 | It's not for creating web *pages*. That's HTML and JavaScript. 39 | 40 | Compiled languages with static types provide safety - many bugs are caught by the compiler before you even get to run the program. Static typing provides efficiency because dynamic typing requires much more work behind the scenes (runs slower as a result). 41 | 42 | Go has support built into the language itself for multicore computing such as "channels". You will learn about these in the Advanced Golang course. It also has great package support for networking - it's simple to construct API servers. 43 | 44 |
45 | 46 |
47 | 48 | 1.
49 | Go is a... 50 | 51 | * compiled language 52 | * interpreted language 53 | 54 |
55 | Reveal 56 | 57 | > compiled language 58 | 59 |
60 |
61 | 62 | 1.
63 | What is a package in go? 64 | 65 | 1. a file that ends with `.mod` extension. 66 | 1. a file that ends with `.go` extension 67 | 1. a collection of files that live in the same directory and have the same package statement at the beginning. 68 | 1. Set of core packages to enhance and extend the language. 69 | 70 |
71 | Reveal 72 | 73 | > C 74 | 75 |
76 |
77 | 78 | 1.
79 | In a Go program, where are packages declared ? 80 | 81 | * At the start of the program 82 | * After the import staetment 83 | * At the end of the program 84 | * Anywhere in the code. 85 | 86 |
87 | Reveal 88 | 89 | > At the start of the program 90 | 91 | The first line of every `.go` file that is not a blank line or a comment must be a `package` statement to declare the package that the code belongs to. 92 | 93 |
94 |
95 | 96 | 1.
97 | Choose the correct format of importing a package in Go: 98 | 99 | If we wanted to import the `fmt` package, which is the correct syntax? 100 | 101 | * `import fmt` 102 | * `import (fmt)` 103 | * `import "fmt"` 104 | * `"import fmt"` 105 | 106 |
107 | Reveal 108 | 109 | > `import "fmt"` 110 | 111 | `import` is a keyword so must not be enclosed within quotes. The name of the package must be quoted. 112 | 113 |
114 |
115 | 116 | 1.
117 | What is the entry point in a Go program? 118 | 119 | * The function that's declared last 120 | * The `main` function 121 | * Function imported by `fmt` package 122 | * The function that's declared first 123 | 124 |
125 | Reveal 126 | 127 | > The `main` function 128 | 129 | The go runtime looks for a function called `main` and calls it. That's how the program starts. This is taken from the venerable C language! 130 | 131 |
132 | 133 |
134 | 135 | 1.
136 | Which package consists of main() function ? 137 | 138 | * independent of package name 139 | * package `main` 140 | * we can create our own main function, no package needs to be imported 141 | * package `greetings` 142 | 143 |
144 | Reveal 145 | 146 | > package `main` 147 | 148 | By convention, you create the `main` package first, and put the `main()` function in it: 149 | 150 | ```go 151 | package main 152 | 153 | // Imports go here - if you need any 154 | 155 | func main() { 156 | // your program starts here 157 | } 158 | ``` 159 | 160 |
161 |
162 | 163 | 1.
164 | Our program began with package main, what would the files in the fmt package begin with? 165 | 166 | * `package os` 167 | * `package fmt` 168 | * `pacakge object` 169 | * `package main` 170 | 171 |
172 | Reveal 173 | 174 | > `package fmt` 175 | 176 | `fmt` is a package, which is meant to be imported by other programs. Here's a snippet of one of the files from this package: 177 | 178 | ```go 179 | package fmt 180 | 181 | import ( 182 | "internal/fmtsort" 183 | "io" 184 | "os" 185 | "reflect" 186 | "strconv" 187 | "sync" 188 | "unicode/utf8" 189 | ) 190 | 191 | // Some lines removed for brevity 192 | 193 | // Printf formats according to a format specifier and writes to standard output. 194 | // It returns the number of bytes written and any write error encountered. 195 | func Printf(format string, a ...any) (n int, err error) { 196 | return Fprintf(os.Stdout, format, a...) 197 | } 198 | 199 | ``` 200 | 201 |
202 |
203 | 204 | 1.
205 | Choose the correct syntax to write a comment in Go 206 | 207 | 1. ```python 208 | # this is a comment 209 | ``` 210 | 211 | 1. ```go 212 | // this is a comment 213 | ``` 214 | 215 | 1. ```go 216 | /* 217 | this is 218 | a multiline 219 | comment 220 | */ 221 | ``` 222 | 223 | 1. ```python 224 | """ 225 | this is 226 | a multiline 227 | comment 228 | """ 229 | 230 |
231 | Reveal 232 | 233 | > B, C 234 | 235 | The other two commenting styles are those of Python. 236 | 237 |
238 |
239 | 240 | 1.
241 | Now let's run some go commands using the terminal. Open an new terminal and identify the version of go installed. 242 | 243 | In the VSCode terminal window, run the following: 244 | 245 | ``` 246 | go version 247 | ``` 248 | 249 | Select the appropriate answer. 250 | 251 | 1.
252 | Which of the following commands is not valid? 253 | 254 | If unsure, run `go help` and check out the commands and their uses. 255 | 256 | * go version 257 | * go run 258 | * go compile 259 | * go generate 260 | 261 |
262 | Reveal 263 | 264 | > go compile 265 | 266 | This is not valid, because the command to compile without running is `go build`. 267 | 268 |
269 |
270 | 271 | 1.
272 | A simple go program has been created for you at the location /root/code/simple-project. However, there is an error in the code. 273 | 274 | Identify and fix the problem. 275 | 276 | 1. In the explorer pane, click on `simple-project` to reveal `main.go` 277 | 1. Click on `main.go` to load it into the editor. 278 | 279 | Review the answer to question 6 to know the issue, then edit the code so it is correct. 280 | 281 |
282 | Reveal 283 | 284 | > Packages imported with the `import` statement must have the package name in double-quotes. 285 | 286 | Fix the import statement thus: 287 | 288 | ```go 289 | import "fmt" 290 | ``` 291 | 292 |
293 |
294 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /docs/02-data-types-and-variables/01-static-vs-dynamic-typed-languages.md: -------------------------------------------------------------------------------- 1 | # Lab: Static vs Dynamic Typed Languages 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-introduction-to-go/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | Which of the following languages are statically typed? 9 | 10 | 1. Java 11 | 2. C 12 | 3. C++ 13 | 4. Python 14 | 15 |
16 | Reveal 17 | 18 | > A, B, C 19 | 20 |
21 |
22 | 23 | 1.
24 | Which of the following languages are dynamically typed? 25 | 26 | 1. C++ 27 | 2. Python 28 | 3. Javascript 29 | 4. PHP 30 | 31 |
32 | Reveal 33 | 34 | > B, C, D 35 | 36 |
37 |
38 | 39 | 1.
40 | Choose the correct statements... 41 | 42 | 1. Type checking process occurs at compile time for static typed languages. 43 | 1. Type checking process occurs at runtime for static typed languages. 44 | 1. Type checking process occurs at compile time for runtime typed languages. 45 | 1. Type checking process occurs at runtime for dynamic typed languages. 46 | 47 |
48 | Reveal 49 | 50 | > A, D 51 | 52 |
53 |
54 | 55 | 1.
56 | In dynamic typing, a variable is allowed to change its data type... 57 | 58 | * Depends on the data type 59 | * True 60 | * False 61 | * Only if it is an integer 62 | 63 |
64 | Reveal 65 | 66 | > True 67 | 68 |
69 |
70 | 71 | 1.
72 | In static typing, a variable is allowed to change its data type... 73 | 74 | * Depends on the data type 75 | * True 76 | * False 77 | * Only if it is an integer 78 | 79 |
80 | Reveal 81 | 82 | > False 83 | 84 |
85 |
86 | 87 | 1.
88 | A sample go program is stored under /root/code/simple-project. Inspect it.
What is the data type assigned to the variable called title?
89 | 90 | You can run this program from the integrated terminal like so 91 | 92 | ```bash 93 | cd simple-project 94 | go run main.go 95 | ``` 96 | 97 | * `float` 98 | * `int` 99 | * `string` 100 | * `Sir` 101 | 102 |
103 | Reveal 104 | 105 | > `string` 106 | 107 | Examine line 7 of the code. 108 | 109 | ```go 110 | title := "Sir" 111 | ```` 112 | 113 | Recall that when `:=` is used to create a variable, the type of the new variable is inferred from what follows `:=`.
`"Sir"` is a string constant, therefore the variable `title` will be of type `string`. 114 | 115 |
116 |
117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/02-data-types-and-variables/02-number-boolean-and-string.md: -------------------------------------------------------------------------------- 1 | # Lab: Numbers, Boolean and String 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-numbers-boolean-and-string/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | Which of these can be considered as Boolean Values in Golang 9 | 10 | * `1, 0` 11 | * `1.0, 0` 12 | * `true, false` 13 | * `"xyz, ""` 14 | 15 |
16 | Reveal 17 | 18 | > `true, false` 19 | 20 | The remaining answers would be values of the following types 21 | 22 | * `int` 23 | * `float` (either of the float types would be valid here) 24 | * `string` 25 | 26 |
27 |
28 | 29 | 1.
30 | Choose the correct keyword(s) for declaring a Float in Golang 31 | 32 | 1. `float32` 33 | 2. `float64` 34 | 3. `float` 35 | 4. `floating` 36 | 37 |
38 | Reveal 39 | 40 | > A< B> 41 | 42 | Golang has two float types: 43 | 44 | * `float32`, known as [single precision](https://en.wikipedia.org/wiki/Single-precision_floating-point_format) stores floating point values of 7 significant figures with a range of approx. ±10±38 45 | * `float32`, known as [double precision](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) stores floating point values of 15 significant figures with a range of approx. ±10±308 46 | 47 | The other two answers are not valid Go types. 48 | 49 |
50 |
51 | 52 | 1.
53 | Choose the datatype(s) supported for numbers in Golang 54 | 55 | 1. `float64` 56 | 1. `floating` 57 | 1. `int` 58 | 1. `int32` 59 | 60 |
61 | Reveal 62 | 63 | > A, C, D 64 | 65 | `floating` is not a valid Go type. 66 | 67 |
68 |
69 | 70 | 1.
71 | Choose the correct keyword(s) for declaring a Booleans in Golang 72 | 73 | * `boolv` 74 | * `boolean` 75 | * `boolf` 76 | * `bool` 77 | 78 |
79 | Reveal 80 | 81 | > `bool` 82 | 83 |
84 |
85 | 86 | 1.
87 | Which of the following literals come under String 88 | 89 | 1. `"hello"` 90 | 1. `"operators"` 91 | 1. `45.99` 92 | 1. `"45.99"` 93 | 94 |
95 | Reveal 96 | 97 | > A, B, D 98 | 99 | If a value is enclosed in double-quotes (`""`), it is *always* string. 100 | 101 |
102 |
103 | 104 | -------------------------------------------------------------------------------- /docs/02-data-types-and-variables/03-variables.md: -------------------------------------------------------------------------------- 1 | # Lab: Variables 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-variables-10/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | What would be the valid statement for initialising a variable: 9 | 10 | Note that these answers may be in a different order each time you load the lab. 11 | 12 | * `var name = "Lia"` 13 | * `var name string = "Lia"` 14 | * `var string name = "Lia"` 15 | * `var string name = 98.00` 16 | 17 |
18 | Reveal 19 | 20 | > `var name string = "Lia"` 21 | 22 | All others are syntax errors. 23 | 24 |
25 |
26 | 27 | 1.
28 | Select all the correct statements for variable initialisation 29 | 30 | 1. `var name string = "Lia"` 31 | 1. `name := "Lia"` 32 | 1. `var s, t string = "Lia", "Harry"` 33 | 1. `var b bool = "false"` 34 | 35 |
36 | Reveal 37 | 38 | > A, B, C 39 | 40 | The final decalration is incorrect because `"false"` is a string, not a boolean. 41 | 42 |
43 |
44 | 45 | 1.
46 | Select the statements that would print and then introduce a new line in the output: 47 | 48 | 1. `fmt.Print(name)` 49 | 1. `fmt.Print("Hey there \n")` 50 | 1. `fmt.Println("Hey there")` 51 | 1. `fmt.Printf(name)` 52 | 53 |
54 | Reveal 55 | 56 | > B, C 57 | 58 | Know that `fmt.Print` and `fmt.Printf` do not automatically emit a newline; `fmt.Println` does. 59 | 60 | Despite the above statement, 2 emits a newline because it includes the special character `\n` which is the newline character. 61 | 62 |
63 |
64 | 65 | 1.
66 | Consider the following code snippet and select the correct output: 67 | 68 | For this, make use of the code editor. Create a new file e.g. `test.go`. Right click in explorer window to create the file, then paste the given code block into it. 69 | 70 | Run this code from the integrated terminal, and observe the output to find the answer. 71 | 72 | ``` 73 | go run test.go 74 | ``` 75 | 76 |
77 | Reveal 78 | 79 | > D 80 | 81 | Understand what the format specifiers are doing in the `Printf` statements, and what was learned in the previous question: 82 | 83 | * `%.2f` is printing radius to 2 decimal places. 84 | * `%.1f` is printing PI to 1 decimal place. 85 | * `%f` is printing area to maximum precision of `float64`. Since the answer is exact at 8 significant figures, that is what's printed. 86 | * There is no newline before `Thank You` because the previous `fmt.Printf` did not emit one. 87 | 88 |
89 |
90 | 91 | 1.
92 | What is the correct format specifier for printing a string with quotes 93 | 94 | Note that these answers may be in a different order each time you load the lab. 95 | 96 | * `%v` 97 | * `%s` 98 | * `%q` 99 | * `%vv` 100 | 101 |
102 | Reveal 103 | 104 | > `%q` 105 | 106 | `%s` also prints strings, but does not include quotes. 107 | 108 |
109 |
110 | 111 | 1.
112 | Among the following code snippets - select the correct ways of initializing variables 113 | 114 | 1. ```go 115 | var name := "Priyanka" 116 | ``` 117 | 118 | 1. ```go 119 | var s,t string,int = "Priyanka", 100 120 | ``` 121 | 122 | 1. ```go 123 | var ( 124 | s string = "Priyanka" 125 | i int = 100 126 | ) 127 | ``` 128 | 129 | 1. ```go 130 | var i,j int = 100, 200 131 | ``` 132 | 133 |
134 | Reveal 135 | 136 | > C, D 137 | 138 | * You can't use `:=` in a `var` declaration 139 | * You can't declare two separate types in a single line `var` declaration 140 | 141 |
142 |
143 | 144 | 1.
145 | Select the correct statement... 146 | 147 | 1. Inner blocks can access variables of outer blocks. 148 | 1. Outer blocks can access variables within inner blocks. 149 | 1. Outer blocks cannot access variables within inner blocks. 150 | 1. Inner blocks can not access variables of outer blocks. 151 | 152 | 153 |
154 | Reveal 155 | 156 | > A, C 157 | 158 |
159 |
160 | 161 | 1.
162 | From the following code snippet, identify the local and global variable 163 | 164 | ```go 165 | package main 166 | 167 | var a string = "foo" 168 | 169 | func main() { 170 | var b string = "bar" 171 | { 172 | var c string = "loreum" 173 | } 174 | } 175 | ``` 176 | 177 | 1. `a`, `b` - global, `c` - local 178 | 1. `a`, `b`, `c` - local 179 | 1. `a`, `b`, `c` - global 180 | 1. `a` - global, `b`, `c` - local 181 | 182 |
183 | Reveal 184 | 185 | > D 186 | 187 | Global variables are defined with `var` statements outside of any `func`. 188 | 189 |
190 |
191 | 192 | 1.
193 | From the following code snippet - which line will cause error 194 | 195 | ```go 196 | 1. package main 197 | 2. 198 | 3. import "fmt" 199 | 4. 200 | 5. var a string = "foo" 201 | 6. 202 | 7. func main() { 203 | 8. var b string = "bar" 204 | 9. fmt.Println(a) 205 | 10. fmt.Println(b) 206 | 11. fmt.Println(c) 207 | 12. { 208 | 13. var c string = "loreum" 209 | 14. fmt.Println(a) 210 | 15. fmt.Println(b) 211 | 16. fmt.Println(c) 212 | 17. } 213 | 18. } 214 | ``` 215 |
216 | Reveal 217 | 218 | > Line 11 219 | 220 | Variable `c` is declared in an inner block. Line 11 is trying to use `c` from an outer block, which as we discovered in Q7 is illegal. 221 | 222 |
223 |
224 | 225 | 1.
226 | What is the zero value for the following variables 227 | 228 | ```go 229 | var name string 230 | var b bool 231 | var f float64 232 | ``` 233 | 234 | 1. ```go 235 | "" 236 | true 237 | 1.0 238 | ``` 239 | 1. ```go 240 | " " 241 | false 242 | 1.0 243 | ``` 244 | 1. ```go 245 | "" 246 | false 247 | 0.00 248 | ``` 249 | 1. ```go 250 | "" 251 | true 252 | 0.0 253 | ``` 254 |
255 | Reveal 256 | 257 | > C 258 | 259 | Don't be fooled by the number of decimal places on the zero value - it's still zero and still a `float64` for which the default is zero. That rules out the first two answers. 260 | 261 | The default for a boolean is always `false`, so that rules out the first and last answer. 262 | 263 | The default for a string is not a string containing one space character, so that rules out the second answer. 264 | 265 | This leaves only the third answer. 266 |
267 |
268 | 269 | -------------------------------------------------------------------------------- /docs/02-data-types-and-variables/04-data-types-and-variables.md: -------------------------------------------------------------------------------- 1 | # Lab: Data types and Variables 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-data-types-and-variables/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | Which of the following methods is used to take input from user? 9 | 10 | 1. `fmt.Scanf` 11 | 1. `fmt.Printf` 12 | 1. `fmt.Scan` 13 | 1. `fmt.Println` 14 | 15 |
16 | Reveal 17 | 18 | > `fmt.Scanf` 19 | 20 | Any `Print` function outputs to the console, rather than inputs anything. 21 | 22 | Actually both `Scan` and `Scanf` can read user input, but the latter is more versatile. 23 | 24 |
25 |
26 | 27 | 1.
28 | What does the Scanf function return? 29 | 30 | 1. It returns the number of arguments that the function writes to 31 | 1. It returns a boolean variable denoting if the function was successful or not 32 | 1. It returns the error thrown during the execution of the program 33 | 1. It does not return anything. 34 | 35 |
36 | Reveal 37 | 38 | > A, C 39 | 40 | `Scanf` is an example of a function that returns more than one value. Many functions in Go return a value and an error. If the error is `nil` then the other return value is the actual value you want and is valid. 41 | 42 | The wording of answer 3 is a little misleading. It is actually the error rasied during execution of `Scanf` itself, if an error occurred. A likely error is if you expected to scan a number and text was entered. 43 | 44 |
45 |
46 | 47 | 1.
48 | From the following code snippets - select the correct one that takes in multiple inputs and is syntactically correct 49 | 50 | 1. ```go 51 | var name string 52 | var b bool 53 | 54 | fmt.Scanf("%s", &name) 55 | fmt.Scanf("%t", &b) 56 | ``` 57 | 58 | 59 | 1. ```go 60 | var name string 61 | var b bool 62 | 63 | fmt.Scanf("%t", name) 64 | fmt.Scanf("t", b) 65 | ``` 66 | 67 | 1. ```go 68 | var name string 69 | var b bool 70 | 71 | fmt.Scanf("%s %t", &name, &b) 72 | ``` 73 | 74 | 1. ```go 75 | var name string 76 | var b bool 77 | 78 | fmt.Scanf("%d %t", name, b) 79 | ``` 80 | 81 |
82 | Reveal 83 | 84 | > A, C 85 | 86 | The format specifier for string is `%s` and for bool is `%t`. Thus B and D are incorrect due to incorrect (`%d`) or invalid (`t`) format specifiers. 87 | 88 | We must always pass the address of a variable we want `Scanf` to write to, i.e use `&` prefix. This also rules out B and D. 89 | 90 | A is correct because it scans a string (`%s`) to a string var (`&name`), then in the second statement does the same with a boolean var. 91 | 92 | C is correct as it scans a string and a boolean separated by a space into corresponding string and boolean variables. 93 | 94 |
95 |
96 | 97 | 1.
98 | Select the correct code snippet for determining type of variable 99 | 100 | 1. ```go 101 | var grades int = 42 102 | fmt.Printf("variable grades = %v is of type %v \n", grades, grades) 103 | ``` 104 | 105 | 1. ```go 106 | var grades int = 42 107 | fmt.Printf("variable grades = %v is of type %t \n", grades, grades) 108 | ``` 109 | 110 | 1. ```go 111 | var grades int = 42 112 | fmt.Printf("variable grades = %v is of type %T \n", grades, grades) 113 | ``` 114 | 115 | 1. ```go 116 | var grades int = 42 117 | fmt.Printf("variable grades = %v is of type %v \n", grades, type(grades)) 118 | ``` 119 | 120 |
121 | Reveal 122 | 123 | > C 124 | 125 | Know that `%T` is the correct format specifier for printing the type of a varaible. 126 | 127 | `type()` is not a valid built-in function. 128 | 129 | `%v` prints the "default" format of the variable associated with it, so for an integer it's the same as `%d`. 130 | 131 |
132 |
133 | 134 | 1.
135 | The function TypeOf() - used for determining data type of a variable belongs to which package 136 | 137 |
138 | Reveal 139 | 140 | > `reflect` 141 | 142 | Determining runtime type of a variable is a reflection operation. 143 | 144 |
145 |
146 | 147 | 1.
148 | We can use reflect.TypeOf() to determine type of a 149 | 150 | * A variable 151 | * A literal 152 | * A constant 153 | * All of the above 154 | 155 |
156 | Reveal 157 | 158 | > All of the above 159 | 160 |
161 |
162 | 163 | 1.
164 | What is Type casting 165 | 166 | * The process of intialising a variable of a certain data type with a value 167 | * The process of declaring a variable with a datatype 168 | * The process of converting any datatype to string 169 | * The process of converting one datatype to another 170 | 171 |
172 | Reveal 173 | 174 | > The process of converting one datatype to another 175 | 176 | Note that you cannot cast dissimilar types. You can't directly cast a number to a string or vice-versa (though there are library functions that perform this conversion). You can cast a numeric type to a different numeric type (e.g. int to float) 177 | 178 |
179 |
180 | 181 | 1.
182 | Select the correct statement to convert an integer to string 183 | 184 | 1. ```go 185 | var i int = 70 186 | str := strconv.Atoi(i) 187 | fmt.Println(str) 188 | ``` 189 | 190 | 1. ```go 191 | var i int = 70 192 | str := fmt.Atoi(i) 193 | fmt.Println(str) 194 | ``` 195 | 196 | 1. ```go 197 | var i int = 70 198 | str := strconv.Itoa(i) 199 | fmt.Println(str) 200 | ``` 201 | 202 | 1. ```go 203 | var i int = 70 204 | str := fmt.Itoa(i) 205 | fmt.Println(str) 206 | ``` 207 | 208 |
209 | Reveal 210 | 211 | > C 212 | 213 | Know that string conversion functions are found in `strconv` package. 214 | 215 | Know that `Itoa` is so-named as it means "Integer to ASCII" 216 | 217 |
218 |
219 | 220 | 1.
221 | The package and function used for converting a string to integer is... 222 | 223 | * `fmt.toInteger()` 224 | * `strconv.Itoa()` 225 | * `fmt.Itoa()` 226 | * `strconv.Atoi()` 227 | 228 |
229 | Reveal 230 | 231 | > `strconv.Atoi()` 232 | 233 | Following on from the previous question, we know that string conversions are found in `strconv` package. It logically follows that the name of the function is the opposite of what was the answer to the previous question. 234 | 235 |
236 |
237 | 238 | 1.
239 | Select the correct ways to convert an integer to float: 240 | 241 | 1. ```go 242 | var i int = 88 243 | f := float32(i) 244 | ``` 245 | 246 | 1. ```go 247 | var i int = 88 248 | f := float64(i) 249 | ``` 250 | 251 | 1. ```go 252 | var i int = 88 253 | f := float(i) 254 | ``` 255 | 256 | 1. ```go 257 | var i int = 88 258 | f := float34(i) 259 | ``` 260 | 261 |
262 | Reveal 263 | 264 | > A, B 265 | 266 | Remember, there are two float types: `float32` and `float64` 267 | 268 |
269 |
270 | 271 | -------------------------------------------------------------------------------- /docs/02-data-types-and-variables/05-constants.md: -------------------------------------------------------------------------------- 1 | # Lab: Constants 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-constants/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | A constant is initialised using the keyword: 9 | 10 | * `var` 11 | * `fixed_var` 12 | * `const` 13 | * `constant` 14 | 15 |
16 | Reveal 17 | 18 | > `const` 19 | 20 |
21 |
22 | 23 | 1.
24 | Select the valid statements for declaring and initialising a constant 25 | 26 | 1. `const c int = "mouse"` 27 | 1. `const c int = 90` 28 | 1. `const c = 90` 29 | 1. `const c int = 90.00` 30 | 31 |
32 | Reveal 33 | 34 | > B, C 35 | 36 | A and D are type mismatches. 37 | 38 |
39 |
40 | 41 | 1.
42 | Select the correct statements 43 | 44 | 1. ```go 45 | const c int = 70 46 | ``` 47 | 48 | 1. ```go 49 | const c int 50 | c = 70 51 | ``` 52 | 53 | 1. ```go 54 | var c int 55 | c = 70 56 | ``` 57 | 58 | 1. ```go 59 | var c = 90 60 | ``` 61 | 62 |
63 | Reveal 64 | 65 | > A, C, D 66 | 67 | B is incorrect because a `const` must be assigned a value when it is declared, not in a separate statement. 68 | 69 |
70 |
71 | 72 | 1.
73 | Can you use shorthand declaration for declaring constants (:=) 74 | 75 | * No 76 | * Yes 77 | * Optional 78 | * None of the above 79 | 80 |
81 | Reveal 82 | 83 | > No 84 | 85 |
86 |
87 | 88 | 1.
89 | Which of the following statement will throw an error 90 | 91 | 1. ```go 92 | const name = "Harry" 93 | fmt.Print(name) 94 | ``` 95 | 96 | 1. ```go 97 | var name = "Harry" 98 | fmt.Print(name) 99 | ``` 100 | 101 | 1. ```go 102 | const name = "Harry" 103 | name = "Snape" 104 | fmt.Print(name) 105 | ``` 106 | 107 | 1. ```go 108 | var name string = "Harry" 109 | fmt.Print(name) 110 | ``` 111 | 112 |
113 | Reveal 114 | 115 | > C 116 | 117 | `const` is by definition constant. This means that once declared, it cannot be reassigned. 118 | 119 |
120 |
121 | 122 | -------------------------------------------------------------------------------- /docs/03-operators-and-flow-control/01-comparison-operators.md: -------------------------------------------------------------------------------- 1 | # Lab: Comparison Operators 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-comparison-operators/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | See also [Comparison Operators](https://go.dev/ref/spec#Comparison_operators) in the Go manual. 8 | 9 | 1.
10 | What would be the output of the following comparison - 11 | 12 | ```go 13 | var a, b string = "Cat", "cat" 14 | fmt.Println(a == b) 15 | ``` 16 | 17 | * Error 18 | * False 19 | * True 20 | * 0 21 | 22 |
23 | Reveal 24 | 25 | > False 26 | 27 | "Cat" does not equal "cat". Difference in capitalisation. 28 | 29 |
30 |
31 | 32 | 1.
33 | What would be the output of the following comparison - 34 | 35 | ```go 36 | var a string = "cat" 37 | var b int = 12 38 | fmt.Println(a == b) 39 | ``` 40 | 41 | * Error 42 | * 1 43 | * False 44 | * True 45 | 46 |
47 | Reveal 48 | 49 | > Error 50 | 51 | The program would not compile due to strict type checking performed by the compiler. You cannot compare `int` with `string`. 52 | 53 |
54 |
55 | 56 | 1.
57 | What would be the output of the following comparison - 58 | 59 | ```go 60 | var a int = 12 61 | var b int = 12 62 | fmt.Println(a != b) 63 | ``` 64 | 65 | * True 66 | * 1 67 | * Error 68 | * False 69 | 70 |
71 | Reveal 72 | 73 | > False 74 | 75 | The values of `a` and `b` are equal, therefore `!=` will be false. 76 | 77 |
78 |
79 | 80 | 1.
81 | What would be the output of the following comparisons - 82 | 83 | ```go 84 | func main() { 85 | var a int = 12 86 | var b int = 12 87 | fmt.Println(a <= b) 88 | 89 | a = 20 90 | fmt.Println(a <= b) 91 | 92 | b = 100 93 | fmt.Println(a <= b) 94 | 95 | c := 0 96 | fmt.Println(a <= c) 97 | } 98 | ``` 99 | 100 | * false
false
true
true 101 | * true
true
false
false 102 | * true
false
true
false 103 | * true
true
true
true 104 | 105 |
106 | Reveal 107 | 108 | > true
false
true
false 109 | 110 | Let's break it down: 111 | 112 | * At the first comparison, `a` = 12 and `b` = 12. 12 less than or equal to 12 is `true` (because they're equal). 113 | * At the second comparison, `a` is now 20 and `b` is still 12. 20 less than or equal to 12 is `false`. 114 | * At the third comparison, `a` is still 20 and `b` is now 100. 20 less than or equal to 100 is `true`. 115 | * At the final comparison, `a` is still 20 and new variable `c` is zero. 20 less than or equal to 0 is `false`. 116 | 117 |
118 |
119 | 120 | 1.
121 | Which operator can you use to validate if two values are not equal 122 | 123 | * `<=` 124 | * `!=` 125 | * `>=` 126 | * `<` 127 | 128 |
129 | Reveal 130 | 131 | > `!=` 132 | 133 | As for the others: 134 | 135 | * `<=` - Less than or equal to 136 | * `>=` - Greater than or equal to 137 | * `<` - Less than 138 | 139 |
140 |
141 | 142 | -------------------------------------------------------------------------------- /docs/03-operators-and-flow-control/02-arithmetic-operators.md: -------------------------------------------------------------------------------- 1 | # Lab: Arithmetic Operators 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-arithmetic-operators/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | See also [Arithmetic Operators](https://go.dev/ref/spec#Arithmetic_operators) in the Go manual. 8 | 9 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 10 | 11 |
12 | Running the code fragments 13 | 14 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 15 | 1. Paste the question code snippet into the editor pane 16 | 1. Open the terminal window and execute `go run test.go` 17 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 18 | 19 |
20 | 21 | ### Questions 22 | 23 | 1.
24 | What would be the output of the following code - 25 | 26 | ```go 27 | package main 28 | 29 | import "fmt" 30 | 31 | func main() { 32 | var a string = "one" 33 | var b int = 2 34 | fmt.Print(a + b) 35 | } 36 | ``` 37 | 38 | * Error 39 | * 2one 40 | * 3 41 | * one2 42 | 43 |
44 | Reveal 45 | 46 | > Error 47 | 48 | The program would not compile due to strict type checking performed by the compiler. You cannot add `int` with `string`. 49 | 50 |
51 |
52 | 53 | 1.
54 | What would be the output of the following code - 55 | 56 | ```go 57 | package main 58 | 59 | import "fmt" 60 | 61 | func main() { 62 | var a float64 = 5.9 63 | var b int = 2 64 | fmt.Print(a + b) 65 | } 66 | ``` 67 | 68 | * Error 69 | * 7.9 70 | * 7 71 | * 7.0 72 | 73 |
74 | Reveal 75 | 76 | > Error 77 | 78 | The program would not compile due to strict type checking performed by the compiler. Whilst both varaibles are numeric types, the compiler will not do implict type casts. You could fix it with an *explicit* type cast 79 | 80 | ```go 81 | fmt.Print(a + float64(b)) 82 | ``` 83 | 84 | ...then the answer would be 7.9 85 | 86 |
87 |
88 | 89 | 1.
90 | What would be the output of the following code - 91 | 92 | ```go 93 | package main 94 | 95 | import "fmt" 96 | 97 | func main() { 98 | var a float64 = 5.9 99 | a++ 100 | fmt.Print(a) 101 | } 102 | ``` 103 | 104 | * 5 105 | * 7.0 106 | * 6 107 | * 6.9 108 | 109 |
110 | Reveal 111 | 112 | > 6.9 113 | 114 | `++` is the increment operator. It adds 1 to any numeric variable. `a++` is equivalent to `a = a + 1` 115 | 116 |
117 |
118 | 119 | 1.
120 | What would be the output of the following code - 121 | 122 | ```go 123 | package main 124 | 125 | import "fmt" 126 | 127 | func main() { 128 | var a int = 10 129 | a-- 130 | fmt.Print(a) 131 | } 132 | ``` 133 | 134 | * 10 135 | * 9 136 | * 11 137 | * Error 138 | 139 |
140 | Reveal 141 | 142 | > 9 143 | 144 | `--` is the decrement operator. It subtracts 1 from any numeric variable. `a--` is equivalent to `a = a - 1` 145 | 146 |
147 |
148 | 149 | 1.
150 | What would be the output of the following code - 151 | 152 | ```go 153 | package main 154 | 155 | import "fmt" 156 | 157 | func main() { 158 | var a, b float64 = 24.4, 3.0 159 | fmt.Println(a / b) 160 | fmt.Println(int(a) % int(b)) 161 | } 162 | ``` 163 | 164 | * 8.133333333333333
0 165 | * 9.001333333333333
0 166 | * 8.00
0.11 167 | * 8.2
ERROR 168 | 169 |
170 | Reveal 171 | 172 | > 8.133333333333333
0 173 | 174 | The first operation is a straight division of two floats, so it will produce a float result. 175 | 176 | In the second operation, the floats are first casted to ints so the values become `24` and `3`. Then a modulo division is performed `%`. Modulo yields the *remainder* when the value on the left is divided by the value on the right. Remember from elementary level maths - 24 divided by 3 = 8 *remainder 0*. 177 |
178 |
179 | 180 | -------------------------------------------------------------------------------- /docs/03-operators-and-flow-control/03-logical-operators.md: -------------------------------------------------------------------------------- 1 | # Lab: Logical Operators 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-logical-operators/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | See also [Logical Operators](https://go.dev/ref/spec#Logical_operators) in the Go manual. 8 | 9 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 10 | 11 |
12 | Running the code fragments 13 | 14 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 15 | 1. Paste the question code snippet into the editor pane 16 | 1. Open the terminal window and execute `go run test.go` 17 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 18 | 19 |
20 | 21 | ### Questions 22 | 23 | 1.
24 | What would be the output for the following program: 25 | 26 | ```go 27 | package main 28 | 29 | import "fmt" 30 | 31 | func main() { 32 | var a, b bool = true, false 33 | fmt.Println(a && b) 34 | fmt.Println(a || b) 35 | } 36 | ``` 37 | 38 | * false
true 39 | * false
false 40 | * true
true 41 | * true
false 42 | 43 |
44 | Reveal 45 | 46 | > false
true 47 | 48 | `&&` is the AND operator. `||` is the OR operator. As will be seen later, `!` is the NOT operator. 49 | 50 | Refer logic truth table 51 | 52 | | a | b | a AND b | a OR b | a XOR b |NOT a | NOT b | 53 | |-------|-------|---------|--------|---------|------|-------| 54 | | false | false | false | false | false |true | true | 55 | | true | false | false | true | true |false | true | 56 | | false | true | false | true | true |true | false | 57 | | true | true | true | true | false |false | false | 58 | 59 | It should be noted that Go does not provide a logical XOR (exclusive-OR) operator where many other languages do, however XOR for two `bool` variables can be expressed like this: `(a != b)`. 60 |
61 |
62 | 63 | 1.
64 | What would be the output for the following program: 65 | 66 | ```go 67 | package main 68 | 69 | import "fmt" 70 | 71 | func main() { 72 | var a, b bool = false, false 73 | fmt.Println(a && b) 74 | fmt.Println(a || b) 75 | } 76 | ``` 77 | 78 | * false
true 79 | * false
false 80 | * true
true 81 | * true
false 82 | 83 |
84 | Reveal 85 | 86 | > false
false 87 | 88 | Refer boolean truth table in the answer to Q1 above 89 | 90 |
91 |
92 | 93 | 1.
94 | What would be the output for the following program: 95 | 96 | ```go 97 | package main 98 | 99 | import "fmt" 100 | 101 | func main() { 102 | var a, b bool = false, true 103 | fmt.Println(!a) 104 | fmt.Println(b) 105 | } 106 | ``` 107 | 108 | * false
true 109 | * false
false 110 | * true
true 111 | * true
false 112 | 113 |
114 | Reveal 115 | 116 | > true
true 117 | 118 | Refer boolean truth table in the answer to Q1 above 119 | 120 | In the first `Println` we have applied the logical NOT (`!`) operator to the value of `a`. NOT false = true. 121 | 122 |
123 |
124 | 125 | 1.
126 | What would be the output for the following program: 127 | 128 | ```go 129 | package main 130 | 131 | import "fmt" 132 | 133 | func main() { 134 | var a bool = false 135 | result := 10 > 50 136 | fmt.Println(!(a && result)) 137 | } 138 | ``` 139 | 140 | * false 141 | * error 142 | * 1 143 | * true 144 | 145 |
146 | Reveal 147 | 148 | > true 149 | 150 | Refer boolean truth table in the answer to Q1 above 151 | 152 | Let's break it down: 153 | 154 | * `result := 10 > 50`. This creates `result` as a `bool` variable, holding the value of `10 > 50` which is `false`. 155 | * Next, the bracketed expression is evaluated `(a && result)`. `a` is `false`, `result` is `false` therefore this evaluates to `false`. 156 | * Finally, NOT is applied to the result of the previous evaluation, therefore answer is `true`. 157 | 158 |
159 |
160 | 161 | 1.
162 | What would be the output for the following program: 163 | 164 | ```go 165 | package main 166 | 167 | import "fmt" 168 | 169 | func main() { 170 | var a bool = true 171 | result := 10 > 50 172 | fmt.Println(!(a || result)) 173 | } 174 | ``` 175 | 176 | * false 177 | * error 178 | * 1 179 | * true 180 | 181 |
182 | Reveal 183 | 184 | > true 185 | 186 | Refer boolean truth table in the answer to Q1 above 187 | 188 | Let's break it down: 189 | 190 | * `result := 10 > 50`. This creates `result` as a `bool` variable, holding the value of `10 > 50` which is `false`. 191 | * Next, the bracketed expression is evaluated `(a || result)`. `a` is `true`, `result` is `false` therefore this evaluates to `true`. 192 | * Finally, NOT is applied to the result of the previous evaluation, therefore answer is `false`. 193 | 194 |
195 |
196 | 197 | -------------------------------------------------------------------------------- /docs/03-operators-and-flow-control/04-assignment-operators.md: -------------------------------------------------------------------------------- 1 | # Lab: Assignment Operators 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-logical-operators/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | See also [Assignment](https://go.dev/ref/spec#Assignment_statements) in the Go manual. 8 | 9 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 10 | 11 |
12 | Running the code fragments 13 | 14 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 15 | 1. Paste the question code snippet into the editor pane 16 | 1. Open the terminal window and execute `go run test.go` 17 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 18 | 19 |
20 | 21 | ### Questions 22 | 23 | 1.
24 | What would be the output for the following program: 25 | 26 | ```go 27 | package main 28 | 29 | import "fmt" 30 | 31 | func main() { 32 | var x, y string = "foo", "bar" 33 | x += y 34 | fmt.Println(x) 35 | } 36 | ``` 37 | 38 | * foobar 39 | * foo 40 | * error 41 | * bar 42 | 43 |
44 | Reveal 45 | 46 | > foobar 47 | 48 | `+=` is "add and assign", and is equivalent to `x = x + y`. When you add two strings, the result is the concatenation of the strings. 49 | 50 |
51 |
52 | 53 | 1.
54 | What would be the output for the following program: 55 | 56 | ```go 57 | package main 58 | 59 | import "fmt" 60 | 61 | func main() { 62 | var x, y int = 27, 7 63 | x /= y 64 | fmt.Println(x) 65 | } 66 | ``` 67 | 68 | * 6 69 | * 3 70 | * error 71 | * 6.00 72 | 73 |
74 | Reveal 75 | 76 | > 3 77 | 78 | `/=` is "divide and assign", and is equivalent to `x = x / y`. Since we have two integers, then an integer division is performed and the remainder is discarded: `27 / 7 = 3 r6` 79 | 80 |
81 |
82 | 83 | 1.
84 | What would be the output for the following program: 85 | 86 | ```go 87 | package main 88 | 89 | import "fmt" 90 | 91 | func main() { 92 | var x, y float64 = 27.9, 7.0 93 | x -= y 94 | fmt.Println(x) 95 | x += y 96 | fmt.Println(x) 97 | } 98 | ``` 99 | 100 | * 27.9
20.9 101 | * 20.9
27.9 102 | * 20.9
7.9 103 | * 27.9
9.0 104 | 105 |
106 | Reveal 107 | 108 | > 20.9
27.9 109 | 110 | * `x -= y` ... x = 27.9 - 7.0 = 20.9, then 111 | * `x += y` ... x = 20.9 + 7.0 = 27.9 112 | 113 |
114 |
115 | 116 | 1.
117 | What would be the output for the following program: 118 | 119 | ```go 120 | package main 121 | 122 | import "fmt" 123 | 124 | func main() { 125 | var x, y int = 100,9 126 | x /= y 127 | fmt.Println(x) 128 | x %= y 129 | fmt.Println(x) 130 | } 131 | ``` 132 | 133 | * 2
2 134 | * 11
2 135 | * 2
11 136 | * 11
11 137 | 138 |
139 | Reveal 140 | 141 | > 11
2 142 | 143 | * `x /= y` ... x = 100 / 9 = 11. Remember this is an integer division so the remainder is discarded, then 144 | * `x %= y` ... x = 11 % 9 = 2. `x` is now 11 from the previous division assignment. Remainder of 11 divided by 2 is 2. 145 | 146 |
147 |
148 | 149 | 1.
150 | Which of these operator assigns the remainder of the division x 151 | 152 | * `/=` 153 | * `*=` 154 | * `%=` 155 | * `\=` 156 | 157 |
158 | Reveal 159 | 160 | > `%=` 161 | 162 | This is the modulo (remainder) assignment operator. 163 | 164 | * `/=` is divide assign 165 | * `*=` is multiply assign 166 | * `\=` is a syntax error and won't compile. 167 | 168 |
169 |
170 | 171 | -------------------------------------------------------------------------------- /docs/03-operators-and-flow-control/05-bitwise-operators.md: -------------------------------------------------------------------------------- 1 | # Lab: Bitwise Operators 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-arithmetic-operators/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | See also [Arithmetic Operators](https://go.dev/ref/spec#Arithmetic_operators) in the Go manual. Bitwise operators are considered arithmetic. 8 | 9 | Refer to the following logic truth table to help with understanding the answers 10 | 11 | | a | b | a AND b | a OR b | a XOR b |NOT a | NOT b | 12 | |-------|-------|---------|--------|---------|------|-------| 13 | | false | false | false | false | false |true | true | 14 | | true | false | false | true | true |false | true | 15 | | false | true | false | true | true |true | false | 16 | | true | true | true | true | false |false | false | 17 | 18 | 19 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 20 | 21 |
22 | Running the code fragments 23 | 24 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 25 | 1. Paste the question code snippet into the editor pane 26 | 1. Open the terminal window and execute `go run test.go` 27 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 28 | 29 |
30 | 31 | ### Questions 32 | 33 | 34 | 1.
35 | Select the correct statements: 36 | 37 | 1. bitwise AND takes two numbers and does OR on every bit of two numbers. 38 | 1. bitwise OR takes two numbers and does OR on every bit of two numbers. 39 | 1. bitwise AND takes two numbers and does AND on every bit of two numbers. 40 | 1. bitwise OR takes two numbers and does AND on every bit of two numbers. 41 | 42 |
43 | Reveal 44 | 45 | > B, C 46 | 47 | A and D are nonsense! 48 | 49 |
50 |
51 | 52 | 1.
53 | Find the output of the following program: 54 | 55 | ```go 56 | package main 57 | 58 | import "fmt" 59 | 60 | func main() { 61 | var x, y int = 100,90 62 | fmt.Println(x & y) 63 | fmt.Println(x | y) 64 | } 65 | ``` 66 | 67 | * 90
100 68 | * 64
126 69 | * 0
109 70 | * 64
96 71 | 72 |
73 | Reveal 74 | 75 | > 64
126 76 | 77 | To understand how this works, we must first convert both numbers to binary, then apply logic truth table to each column of digits. In binary, `true` is `1` and `false` is 0. Convert the binary result back to decimal. 78 | 79 | ``` 80 | 01100100 (100) 81 | & 01011010 ( 90) 82 | -------- 83 | 01000000 ( 64) 84 | 85 | 01100100 (100) 86 | | 01011010 ( 90) 87 | -------- 88 | 01111110 (126) 89 | ``` 90 | 91 |
92 |
93 | 94 | 1.
95 | Select the correct statements 96 | 97 | 1. The result of XOR is 0 when the two bits are same. 98 | 1. The result of XOR is 1 when the two bits are opposite. 99 | 1. The result of XOR is 0 when the two bits are opposite. 100 | 1. The result of XOR is 1 when the two bits are same. 101 | 102 | 103 |
104 | Reveal 105 | 106 | > A, B 107 | 108 | Refer to above truth table. 109 | 110 |
111 |
112 | 113 | 1.
114 | Find the output of the following program: 115 | 116 | ```go 117 | package main 118 | 119 | import "fmt" 120 | 121 | func main() { 122 | var x, y int = 100,90 123 | fmt.Println((x+y) >> 2) 124 | } 125 | ``` 126 | 127 | * 47 128 | * 90 129 | * 83 130 | * 56 131 | 132 |
133 | Reveal 134 | 135 | > 47 136 | 137 | `>>` is the bitwise shift right operator. The number of places to shift by in this case is 2. To understand how this works requires a few steps 138 | 139 | 1. Do the addition `x+y` and get the result. 100 + 90 = 190 140 | 2. Convert this result to binary: `10111110` 141 | 3. Now shift right by two columns. Anything that "falls off the end" is discarded. Zeros come in from the left. 142 | 143 | ``` 144 | Shift 1: `01011111` 145 | Shift 2: `00101111` 146 | ``` 147 | 4. Convert this binary result back to decimal: `00101111` = `47` 148 | 149 |
150 |
151 | 152 | 1.
153 | Find the output of the following program: 154 | 155 | ```go 156 | package main 157 | 158 | import "fmt" 159 | 160 | func main() { 161 | var x, y int = 100,90 162 | fmt.Println(!(((x+y) >> 2 ) == 47)) 163 | } 164 | ``` 165 | 166 | * 47 167 | * error 168 | * true 169 | * false 170 | 171 |
172 | Reveal 173 | 174 | > false 175 | 176 | There's a lot going on here! To understand how this works requires a few steps. The order we evaluate this expression is determined by the bracketing. We can also tell that the result must be boolean `true` or `false`, as the final evaluation will be a logical NOT of a boolean comparision using `==` so that rules out `47` as being a correct answer. There are no syntax errors or anything that would cause a runtime error (like division by zero), so `error` is also not the correct answer. 177 | 178 | We have to start on the inside and work out. 179 | 180 | 1. The first part is `((x+y) >> 2)` which we did in the previous question, and the result is `47`. 181 | 2. The next part is `(((x+y) >> 2 ) == 47)`, i.e. `47 == 47` which is `true` 182 | 4. Finally `!(((x+y) >> 2 ) == 47)`, i.e. `NOT (47 == 47)`, which is `false` and is therefore the answer to this question. 183 | 184 |
185 |
186 | 187 | -------------------------------------------------------------------------------- /docs/03-operators-and-flow-control/06-if-else-and-elseif-statements.md: -------------------------------------------------------------------------------- 1 | # Lab: if-else and else if statements 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-if-else-and-else-if-statements//) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | See also [Assignment](https://go.dev/ref/spec#Assignment_statements) in the Go manual. 8 | 9 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 10 | 11 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 12 | 13 |
14 | Running the code fragments 15 | 16 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 17 | 1. Paste the question code snippet into the editor pane 18 | 1. Open the terminal window and execute `go run test.go` 19 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 20 | 21 |
22 | 23 | ### Questions 24 | 25 | 1.
26 | What would be the output for the following program: 27 | 28 | ```go 29 | package main 30 | 31 | import "fmt" 32 | 33 | func main() { 34 | var a, b string = "kolkata", "Kolkata" 35 | if a == b { 36 | fmt.Println("strings are equal") 37 | } else { 38 | fmt.Println("strings are not equal") 39 | } 40 | fmt.Println("thank you!") 41 | } 42 | ``` 43 | 44 | * strings are equal 45 | * strings are equal
thank you! 46 | * Error 47 | * strings are not equal
thank you! 48 | 49 |
50 | Reveal 51 | 52 | > strings are not equal
thank you! 53 | 54 | Strings are not equal because there is a difference in capitalisation, so the `if` test is `false`, and the `else` block is executed. 55 | 56 | There's no error as the syntax is correct and it will compile. 57 | 58 | `thank you!` is always printed, as it's not inside of an if-else construct. 59 | 60 |
61 |
62 | 63 | 1.
64 | What would be the output for the following program: 65 | 66 | ```go 67 | package main 68 | 69 | import "fmt" 70 | 71 | func main() { 72 | var a, b string = "kolkata", "kolkata" 73 | if a == b { 74 | fmt.Println("strings are equal") 75 | } 76 | else { 77 | fmt.Println("strings are not equal") 78 | } 79 | fmt.Println("thank you!") 80 | } 81 | ``` 82 | 83 | * strings are equal 84 | * strings are equal
thank you! 85 | * Error 86 | * strings are not equal
thank you! 87 | 88 |
89 | Reveal 90 | 91 | > Error 92 | 93 | There is a syntax error in this code, so it will not compile. Go is strict about the placement of braces. 94 | 95 | ```go 96 | } 97 | else { 98 | ``` 99 | 100 | should be 101 | 102 | ```go 103 | } else { 104 | ``` 105 | 106 |
107 |
108 | 109 | 1.
110 | What would be the output for the following program: 111 | 112 | ```go 113 | package main 114 | 115 | import "fmt" 116 | 117 | func main() { 118 | var a, b string = "foo", "bar" 119 | if a+b == "foo" { 120 | fmt.Println("foo") 121 | } else if a+b == "bar" { 122 | fmt.Println("bar") 123 | } else if a+b == "foobar" { 124 | fmt.Println("foobar") 125 | } else { 126 | fmt.Println("None matched") 127 | } 128 | fmt.Println("thank you!") 129 | } 130 | ``` 131 | 132 | * foo
thank you! 133 | * bar
thank you! 134 | * None matched
thank you! 135 | * foobar
thank you! 136 | 137 | 138 |
139 | Reveal 140 | 141 | > foobar
thank you! 142 | 143 | 1. First, evaluate what is `a+b`. Addtion of strings concatenates them, so we get `foobar` 144 | 1. Now look at the if-else if statements. Which one matches `foobar`? This is the branch the program will follow. 145 | 146 | `thank you!` is always printed, as it's not inside of an if-else construct. 147 | 148 |
149 |
150 | 151 | 1.
152 | What would be the output for the following program: 153 | 154 | ```go 155 | package main 156 | 157 | import "fmt" 158 | 159 | func main() { 160 | var a, b string = "foo", "bar" 161 | if a+b == "foo" { 162 | fmt.Println("foo") 163 | } else if a+b == "foobar" { 164 | fmt.Println("bar") 165 | } else if a+b == "foobar" { 166 | fmt.Println("foobar") 167 | } else { 168 | fmt.Println("None matched") 169 | } 170 | fmt.Println("thank you!") 171 | 172 | } 173 | ``` 174 | 175 | * None matched
thank you! 176 | * bar
thank you! 177 | * foobar
thank you! 178 | * foo
thank you! 179 | 180 |
181 | Reveal 182 | 183 | > bar
thank you! 184 | 185 | This one has a gotcha! Note this bit 186 | 187 | ```go 188 | } else if a+b == "foobar" { 189 | fmt.Println("bar") 190 | } else if a+b == "foobar" { 191 | fmt.Println("foobar") 192 | } ... 193 | ``` 194 | 195 | `a+b` is indeeed `foobar` and it matches both of the above. Go will choose the first match and ignore any others that match, therefore the output is `bar` and not `foobar` 196 | 197 |
198 |
199 | 200 | 1.
201 | Can we use if block independently, without else-if and else blocks? 202 | 203 | 1. No, we need at least one else block. 204 | 1. else-if is optional, but if block would raise error without else block. 205 | 1. Yes, we can write if block without any of the other blocks. 206 | 1. We need at least one if, one else-if and one else block for program to compile successfully. 207 | 208 | 209 | * false
true 210 | 211 |
212 | Reveal 213 | 214 | > C 215 | 216 | Just like speech. You don't always need to say "else" or "else if" after if. 217 | 218 |
219 |
220 | 221 | -------------------------------------------------------------------------------- /docs/03-operators-and-flow-control/07-switch-statement.md: -------------------------------------------------------------------------------- 1 | # Lab: Switch Statement 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-switch-statement/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 8 | 9 |
10 | Running the code fragments 11 | 12 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 13 | 1. Paste the question code snippet into the editor pane 14 | 1. Open the terminal window and execute `go run test.go` 15 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 16 | 17 |
18 | 19 | Note that switch statements are nothing more than a shorthand way of writing if - else if - else if - else, where `default` is the final `else` 20 | 21 | ### Questions 22 | 23 | 1.
24 | What would be the output of the following program - 25 | 26 | ```go 27 | package main 28 | 29 | import "fmt" 30 | 31 | func main() { 32 | var a, b = 100, 5 33 | switch { 34 | case a/b == 10: 35 | fmt.Println("10") 36 | case a/b == 20: 37 | fmt.Println("20") 38 | case a/b == 10: 39 | fmt.Println("30") 40 | default: 41 | fmt.Println("default") 42 | } 43 | 44 | } 45 | ``` 46 | 47 | * 30 48 | * 40 49 | * 10 50 | * 20 51 | 52 |
53 | Reveal 54 | 55 | > 20 56 | 57 | 1. Work out `a/b`. `100/5 = 20` 58 | 2. Examine the case statements for the one that matches the above evaluation. 59 | 60 | 61 |
62 |
63 | 64 | 1.
65 | What would be the output of the following program - 66 | 67 | ```go 68 | package main 69 | 70 | import "fmt" 71 | 72 | func main() { 73 | day := "sunday" 74 | switch day { 75 | case "monday": 76 | fmt.Println("monday") 77 | case "tuesday": 78 | fmt.Println("tuesday") 79 | case "wednesday": 80 | fmt.Println("wednesday") 81 | case "thursday": 82 | fmt.Println("thursday") 83 | case "friday": 84 | fmt.Println("friday") 85 | case "saturday", "sunday": 86 | fmt.Println("weekend") 87 | default: 88 | fmt.Println("default") 89 | } 90 | } 91 | ``` 92 | 93 | * friday
sunday 94 | * weekend
default 95 | * weekend 96 | * saturday
weekend 97 | 98 |
99 | Reveal 100 | 101 | > weekend 102 | 103 | * It will switch on the value of `day` which is `sunday` 104 | * It will match on the final case, which is checking for `saturday` *or* `sunday` 105 | * No `default` case will be selected, as we already have a match. 106 | 107 |
108 |
109 | 110 | 1.
111 | What would be the output of the following program - 112 | 113 | ```go 114 | package main 115 | 116 | import "fmt" 117 | 118 | func main() { 119 | day := "wednesday" 120 | switch day { 121 | case "monday": 122 | fmt.Println("monday") 123 | case "tuesday": 124 | fmt.Println("tuesday") 125 | case "wednesday": 126 | fmt.Println("wednesday") 127 | fallthrough 128 | case "thursday": 129 | fmt.Println("thursday") 130 | fallthrough 131 | case "friday": 132 | fmt.Println("friday") 133 | case "saturday", "sunday": 134 | fmt.Println("weekend") 135 | default: 136 | fmt.Println("default") 137 | } 138 | } 139 | ``` 140 | 141 | * wednesday
thursday 142 | * wednesday
thursday
friday
default 143 | * wednesday
thursday
friday 144 | * wednesday
friday
default 145 | 146 |
147 | Reveal 148 | 149 | > wednesday
thursday
friday 150 | 151 | * It will switch on the value of `day` which is `wednesday` 152 | * It will match `case "wednesday"` 153 | * It then encounters `fallthrough`, which means run the code in the `case` that follows *irrespective* of whether the case condition matches, thus `thursday` is printed. Similar for `friday`, but there's no `fallthrough` in friday's case, so `default` is not printed. 154 | 155 |
156 |
157 | 158 | 1.
159 | What would be the output of the following program - 160 | 161 | ```go 162 | package main 163 | 164 | import "fmt" 165 | 166 | func main() { 167 | var a, b = 100, 5 168 | switch a { 169 | case a/b == 10: 170 | fmt.Println("10") 171 | case a/b == 20: 172 | fmt.Println("20") 173 | case a/b == 10: 174 | fmt.Println("30") 175 | default: 176 | fmt.Println("default") 177 | } 178 | } 179 | ``` 180 | 181 | * 30 182 | * Error 183 | * 10 184 | * 20 185 | 186 |
187 | Reveal 188 | 189 | > Error 190 | 191 | At first glance this looks like Q1, but there is a subtle difference! This time it's not an unbounded switch, it is switching on the value of `a`, and `a` is an `int`. 192 | 193 | The comparisons for the cases are all boolean which can't be tested against the integer switch variable `a`, so you will get a compilation error. 194 | 195 |
196 |
197 | 198 | 1.
199 | What would be the output of the following program - 200 | 201 | Note: When using switch with conditionals - we don't specify expression after switch. This is what the error was in the last question. 202 | 203 | ```go 204 | package main 205 | 206 | import "fmt" 207 | 208 | func main() { 209 | var i, j = 10, 50 210 | 211 | switch { 212 | case i+j == 60: 213 | fmt.Println("equal to 60") 214 | case i+j <= 60: 215 | fmt.Println("less than or equal to 60") 216 | fallthrough 217 | default: 218 | fmt.Println("greater than 60") 219 | } 220 | } 221 | ``` 222 | 223 | * less than or equal to 60
greater than 60 224 | * equal to 60 225 | * less than or equal to 60
equal to 60 226 | * less than or equal to 60
greater than 60 227 | 228 |
229 | Reveal 230 | 231 | > equal to 60 232 | 233 | 1. Evaluate `i+j` - 10+50 = 60 234 | 1. The first case matches, so `equal to 60` is printed. 235 | 1. There is no `fallthrough` on this case, so the switch is complete and no other case is considered. 236 | 237 |
238 |
239 | 240 | -------------------------------------------------------------------------------- /docs/03-operators-and-flow-control/08-looping-with-for.md: -------------------------------------------------------------------------------- 1 | # Lab: Looping with For 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-switch-statement/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 8 | 9 |
10 | Running the code fragments 11 | 12 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 13 | 1. Paste the question code snippet into the editor pane 14 | 1. Open the terminal window and execute `go run test.go` 15 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 16 | 17 |
18 | 19 | ### Questions 20 | 21 | 1.
22 | What would be the output of the following program - 23 | 24 | ```go 25 | package main 26 | 27 | import "fmt" 28 | 29 | func main() { 30 | for { 31 | fmt.Println("Hello World!") 32 | } 33 | } 34 | ``` 35 | 36 | * Infinite loop 37 | * Syntax error 38 | * Hello World! 39 | * No output 40 | 41 |
42 | Reveal 43 | 44 | > Infinite loop 45 | 46 | * Yes, it will print "Hello World!", but it will print it an infinite number of times, or until you forcibly stop to program with `CTRL-C`. 47 | * It is infinite because the `for` has no condition with which to exit. 48 | 49 |
50 |
51 | 52 | 1.
53 | What would be the output of the following program - 54 | 55 | ```go 56 | package main 57 | 58 | import "fmt" 59 | 60 | func main() { 61 | i := 3 62 | for i > 10 { 63 | fmt.Println(i * 2) 64 | i += 1 65 | } 66 | } 67 | ``` 68 | 69 | * No output 70 | * Syntax error 71 | * 3
4
5
6
7
8
9 72 | * 6
8
10
12
14
16
18 73 | 74 |
75 | Reveal 76 | 77 | > No output 78 | 79 | The loop condition is "i is greater than 10". `i` is 3 when the program reaches `for`, thus the conditon is false and the body of the loop is not executed. 80 | 81 |
82 |
83 | 84 | 1.
85 | What would be the output of the following program - 86 | 87 | ```go 88 | package main 89 | 90 | import "fmt" 91 | 92 | func main() { 93 | i := 5 94 | j := 0 95 | for j < 5 { 96 | fmt.Println(i * 2) 97 | j += 1 98 | } 99 | } 100 | ``` 101 | 102 | * Syntax error 103 | * Infinite loop 104 | * 10
10
10
10
10 105 | * 0
2
4
6
8 106 | 107 |
108 | Reveal 109 | 110 | > 10
10
10
10
10 111 | 112 | * At the entry to the loop, `j` is initially zero. This satisfies the loop condition so the loop content is executed. 113 | * `i` is `5`, and remains `5` for the duration of the program. This means the `Println` will *always* print `10`. 114 | * Each time round the loop, `j` is incremented, therefore after the fifth execution of the loop, `j` will now be `5` and the loop condition will be `false`, so the loop exits. 115 | 116 |
117 |
118 | 119 | 1.
120 | What would be the output of the following program - 121 | 122 | ```go 123 | package main 124 | 125 | import "fmt" 126 | 127 | func main() { 128 | for i := 0; i <= 5; i++ { 129 | fmt.Println(i * i) 130 | if i == 3 { 131 | continue 132 | } 133 | } 134 | } 135 | ``` 136 | 137 | * 0
1
4 138 | * Error 139 | * 0
1
4
16
25 140 | * 0
1
4
9
16
25 141 | 142 | 143 |
144 | Reveal 145 | 146 | > 0
1
4
9
16
25 147 | 148 | This is a program to print squares of numbers from zero to 5 inclusive - and that's what it does - it prints all of them! 149 | 150 | This is a red herring 151 | 152 | ```go 153 | if i == 3 { 154 | continue 155 | } 156 | ``` 157 | 158 | The `continue` statement directs the program to go directly back to the `for` without executing any further code within the `for`'s block. However there is nothing following the `continue` so the net effect is not to change the flow of the program, i.e nothing is missed out. 159 | 160 |
161 |
162 | 163 | 164 | 1.
165 | What would be the output of the following program - 166 | 167 | ```go 168 | package main 169 | 170 | import "fmt" 171 | 172 | func main() { 173 | for i := 0; i <= 5; i++ { 174 | if i == 3 { 175 | break 176 | } 177 | fmt.Println(i * i) 178 | } 179 | } 180 | ``` 181 | 182 | * 0
1
4 183 | * Error 184 | * 0
1
4
9 185 | * 0
1
4
9
16
25 186 | 187 | 188 |
189 | Reveal 190 | 191 | > 0
1
4
9 192 | 193 | This is very similar to the previous question - it's still a program to print squares, however the for loop finishes early due to the `break` statement when `i` is 3. 194 | 195 | It has already printed the square of 3, thus the output gets as far as 9. But then `i == 3` is `true` and the `break` within the `if` block is executed. `break` moves control to whatever follows the `}` of the for loop - in this case the end of the program. 196 | 197 |
198 |
199 | -------------------------------------------------------------------------------- /docs/04-arrays-slices-and-maps/01-arrays.md: -------------------------------------------------------------------------------- 1 | # Lab: Arrays 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-arrays/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 8 | 9 |
10 | Running the code fragments 11 | 12 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 13 | 1. Paste the question code snippet into the editor pane 14 | 1. Open the terminal window and execute `go run test.go` 15 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 16 | 17 |
18 | 19 | ### Questions 20 | 21 | 22 | 1.
23 | Select the correct statement(s) for initialising an array. 24 | 25 | 1. `var arr [5]string := [5]string {}` 26 | 1. `var arr [5]string = [5]string {}` 27 | 1. `arr := [5]string {}` 28 | 1. `var arr := […]string {}` 29 | 30 |
31 | Reveal 32 | 33 | > B, C 34 | 35 | We can rule out A and D immediately, since you canot use `:=` in any `var` statement. 36 | 37 |
38 |
39 | 40 | 1.
41 | What is the length and capacity of [1, 2, 3, 4] 42 | 43 | * Length = 4, capacity = 6 44 | * Length = 4, capacity = 10 45 | * Length = Capacity = 4 46 | * Length = 4, capacity = 3 47 | 48 |
49 | Reveal 50 | 51 | > Length = Capacity = 4 52 | 53 | With no further information about how the list was allocated, then we can assume that both length and capacity are equal to the number of elements in the list. 54 | 55 |
56 |
57 | 58 | 1.
59 | What would be the output of the following program: 60 | 61 | ```go 62 | package main 63 | 64 | import "fmt" 65 | 66 | func main() { 67 | arr := [...]string{1, 2, 3, 4, 5} 68 | fmt.Println(arr) 69 | } 70 | ``` 71 | 72 | * `[]` 73 | * Error 74 | * `[1 2 3 4 5]` 75 | * `["1", "2", "3", "4", "5"]` 76 | 77 |
78 | Reveal 79 | 80 | > Error 81 | 82 | The program would not compile. You cannot initialize a `string` array with integer values. 83 | 84 |
85 |
86 | 87 | 1.
88 | What would be the output of the following program: 89 | 90 | ```go 91 | package main 92 | 93 | import "fmt" 94 | 95 | func main() { 96 | arr := [5]bool{true, true, true, true} 97 | for i := 0; i < len(arr); i++ { 98 | if arr[i] { 99 | fmt.Println(i) 100 | } 101 | } 102 | } 103 | ``` 104 | 105 | * 0
1
2
3 106 | * 0 1 2 3 4 107 | * 0
1
2
3
4 108 | * Error 109 | 110 |
111 | Reveal 112 | 113 | > 0
1
2
3 114 | 115 | * An array large enough for 5 `bool` values has been created. 116 | * Values of `true` have been provided for the first 4 array elements - this means that the remaining one element in the array (`arr[4]`) will have the default value for `bool` which is `false`. So the array looks like this 117 | 118 | | 0 | 1 | 2 | 3 | 4 | 119 | |------|------|------|------|-------| 120 | | true | true | true | true | false | 121 | 122 | * The `for` loop will iterate across all five values in the array, counting from zero to 4 inclusive. 123 | * Since `arr[4]` contains `false`, only numbers as far as 3 will be printed. 124 | 125 |
126 |
127 | 128 | 1.
129 | What would be the output of the following program: 130 | 131 | ```go 132 | package main 133 | 134 | import "fmt" 135 | 136 | func main() { 137 | arr := [5]bool{true, true} 138 | fmt.Println(arr) 139 | } 140 | ``` 141 | 142 | * [true true false false true] 143 | * [true true] 144 | * [true true false false false] 145 | * [true true true true true] 146 | 147 |
148 | Reveal 149 | 150 | > [true true false false false] 151 | 152 | Again, this is about knowing that the default value of the array's type will be used to intialize the elements of the array for which explict values have not been provded. This is a 5 element array, and values have only been provided for the first two elements. It looks like this: 153 | 154 | | 0 | 1 | 2 | 3 | 4 | 155 | |------|------|-------|-------|-------| 156 | | true | true | false | false | false | 157 | 158 | 159 |
160 |
161 | 162 | 1.
163 | What would be the output of the following program: 164 | 165 | ```go 166 | package main 167 | 168 | import "fmt" 169 | 170 | func main() { 171 | arr := [4]int{10, 20, 30, 50, 90} 172 | fmt.Println(arr) 173 | } 174 | ``` 175 | 176 | * [10 20 30 40 50 177 | * [10 20 30 40 0] 178 | * [10 20 30 40] 179 | * Error 180 | 181 |
182 | Reveal 183 | 184 | > Error 185 | 186 | * An array large enough for 4 values has been declared. 187 | * The initializer is passing 5 values. This is an error as the values won't fit, so the program will not compile. 188 | 189 |
190 |
191 | 192 | 1.
193 | What would be the output of the following program: 194 | 195 | ```go 196 | package main 197 | 198 | import "fmt" 199 | 200 | func main() { 201 | arr := [10]int{10, 20, 30, 50} 202 | fmt.Println(arr) 203 | fmt.Println(len(arr)) 204 | } 205 | ``` 206 | 207 | * [10 20 30 50] 208 | * [10 20 30 50 0 0 0 0 0 0]
4 209 | * [10 20 30 50 0 0 0 0 0 0]
10 210 | * [10 20 30 50]
10 211 | 212 |
213 | Reveal 214 | 215 | > [10 20 30 50 0 0 0 0 0 0]
10 216 | 217 | * The array has been declared to have 10 elements - this means `len(arr)` is 10. 218 | * It has been initialized with 4 values, therefore the remaining 6 values will have the default value for `int` which is zero. It looks like this 219 | 220 | | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 221 | |----|----|----|----|---|---|---|---|---|---| 222 | | 10 | 20 | 30 | 50 | 0 | 0 | 0 | 0 | 0 | 0 | 223 | 224 | 225 |
226 |
227 | 228 | 1.
229 | What would be the output of the following program: 230 | 231 | ```go 232 | package main 233 | 234 | import "fmt" 235 | 236 | func main() { 237 | arr := [10]int{10, 20, 30, 50} 238 | fmt.Println(arr[0]) 239 | fmt.Println(arr[2]) 240 | fmt.Println(arr[4]) 241 | fmt.Println(arr[8]) 242 | fmt.Println(arr[10]) 243 | } 244 | ``` 245 | 246 | * Error 247 | * 10 30 0 0 0
10 248 | * 10
30
0
0
nil 249 | * 10
30
0
0
0 250 | 251 |
252 | Reveal 253 | 254 | > Error 255 | 256 | * Remember that array indexes start at zero, not 1. 257 | * The array has been declared to have 10 elements. These will be `arr[0]` thru `arr[9]` 258 | * `arr[10]` is trying to access the 11th element which doesn't exist, therefore the program will not compile. 259 | 260 |
261 |
262 | 263 | 1.
264 | What would be the output of the following program: 265 | 266 | ```go 267 | package main 268 | 269 | import "fmt" 270 | 271 | func main() { 272 | arr := [5]string{"a", "b", "c"} 273 | for index, element := range arr { 274 | fmt.Println(index, "->", element) 275 | } 276 | } 277 | ``` 278 | 279 | * 0 -> a
1 -> b
2 -> c
3 -> d
4 -> e 280 | * 0 -> a
1 -> b
2 -> c
3 ->
4 -> 281 | * 0 -> a
1 -> b
2 -> c
3 -> 3
4 -> 4 282 | * Error 283 | 284 |
285 | Reveal 286 | 287 | > 0 -> a
1 -> b
2 -> c
3 ->
4 -> 288 | 289 | * We have a 5 element string array, for which only the first 3 values have been initialized. The remaining 2 values will have the default value for `string`, which is an empty string (`""`) It looks like this 290 | 291 | | 0 | 1 | 2 | 3 | 4 | 292 | |---|---|---|---|---| 293 | | a | b | c | | | 294 | 295 | * The range keyword returns the index and value for each element in the array. 296 | * Thus 3 and 4 print as they do, because their values are empty. 297 | 298 |
299 |
300 | 301 | 1.
302 | What would be the output of the following program: 303 | 304 | ```go 305 | package main 306 | 307 | import "fmt" 308 | 309 | func main() { 310 | arr := [5][2]string{{"a"}, {"b"}, {"c"}} 311 | fmt.Println(arr[0][0]) 312 | fmt.Println(arr[1][1]) 313 | fmt.Println(arr[2][0]) 314 | } 315 | ``` 316 | 317 | * a

c 318 | * a
b
c 319 | * a
c

320 | * Error 321 | 322 |
323 | Reveal 324 | 325 | > a

c 326 | 327 | Here we have a two dimensional array, 5 wide and 2 deep. And there are default values everywhere! Let's visualize this data structure. It's like an Excel spreadsheet! 328 | 329 | | | 0 | 1 | 2 | 3 | 4 | 330 | |---|---|---|---|---|---| 331 | | 0 | a | b | c | | | 332 | | 1 | | | | | | 333 | 334 | Given `arr[x][y]`, look up `x` as the column number and `y` as the row number. 335 | 336 | Thus `arr[0][0]` is `a`, `arr[1][1]` is empty, `arr[2][0]` is `c`. 337 | 338 |
339 |
340 | 341 | -------------------------------------------------------------------------------- /docs/04-arrays-slices-and-maps/02-slices.md: -------------------------------------------------------------------------------- 1 | # Lab: Slices 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-slices/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 8 | 9 |
10 | Running the code fragments 11 | 12 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 13 | 1. Paste the question code snippet into the editor pane 14 | 1. Open the terminal window and execute `go run test.go` 15 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 16 | 17 |
18 | 19 | Before we start, a frequently asked question on Slack and the forums is about slice capacity when a slice grows: "I thought that the capacity always doubles when a slice grows". The answer to that is *usually*, not *always*. It depends on the length of the intial slice, how much data is being appended, and how big the capacity is at the time it is grown. If it always doubled, you could run out of memory very quickly! The code for growing a slice is [here](https://github.com/golang/go/blob/master/src/runtime/slice.go#L157), but it's very complicated! 20 | 21 | ### Questions 22 | 23 | 1.
24 | What would be the output of the following program: 25 | 26 | ```go 27 | package main 28 | 29 | import "fmt" 30 | 31 | func main() { 32 | arr := []int{-1, -2} 33 | for _, value := range arr { 34 | fmt.Println(value) 35 | } 36 | } 37 | ``` 38 | 39 | * -1
-2
0
0
0 40 | * -1
-2 41 | * [-1, -2] 42 | * [-1 -2] 43 | 44 |
45 | Reveal 46 | 47 | > -1
-2 48 | 49 | * Know that slices are variable length arrays. When you declare a slice with initial values as has been done in this program, its length is equal to the number of values it was initialized with, so that rules out more than 2 values being printed. 50 | * The `Println` is printing individual values, not the whole slice, so that eliminates anything with `[]` 51 | 52 |
53 |
54 | 55 | 1.
56 | What would be the length and capacity of the slice here. 57 | 58 | ```go 59 | arr := [5]string{"a", "b", "c", "d", "e"} 60 | slice := arr[:4] 61 | ``` 62 | 63 | * Length: 5, Capacity: 5 64 | * Length: 4, Capacity: 5 65 | * Length: 5, Capacity: 4 66 | * Length: 4, Capacity: 4 67 | 68 |
69 | Reveal 70 | 71 | > Length: 4, Capacity: 5 72 | 73 | * `arr[:4]` creates a new *slice* using the first 4 elements of `arr`. `arr` can be an array (as it is here), or another slice. 74 | * The length of the new slice is equal to the number of elements copied. The capacity is equal to the capacity of `arr`. For arrays (like `arr`), capacity is always equal to length. 75 | * Importantly, the new slice is actually a "view" of the source data. A copy is not made of the original array; the slice is referencing the same memory as the original array, and is why the capacities are equal - as will be seen in the next question! 76 | 77 |
78 |
79 | 80 | 1.
81 | What would be the output of the following program: 82 | 83 | ```go 84 | package main 85 | 86 | import "fmt" 87 | 88 | func main() { 89 | arr := [5]string{"a", "b", "c", "d", "e"} 90 | slice := arr[:4] 91 | fmt.Println(arr) 92 | fmt.Println(slice) 93 | slice[1] = "x" 94 | fmt.Println(arr) 95 | fmt.Println(slice) 96 | } 97 | ``` 98 | 99 | * [a b c d e]
[a b c d]
[a b c d e]
[a x c d] 100 | * [a b c d e]
[b c d]
[a x c d e]
[x c d] 101 | * [a b c d e]
[a b c d]
[a x c d e]
[a x c d] 102 | * [a b c d e]
[a b c d]
[a b x d e]
[a b x d] 103 | 104 |
105 | Reveal 106 | 107 | > [a b c d e]
[a b c d]
[a x c d e]
[a x c d] 108 | 109 | * The first two `Println` are showing the contents of `arr` and `slice` 110 | * Now we set the second element of `slice` to be `x`. 111 | * Print the array and the slice again - but wait! The second value in the array has also been updated! Why? This is due to the explanation given in the last question. 112 | 113 |
114 |
115 | 116 | 1.
117 | Follow the given steps, and select the correct output 118 | 119 | 1. create an integer array of size 5 with values [10, 20, 90, 70, 60] 120 | 1. create a slice referencing the above array to contain elements from index 0, 1, 2 121 | 1. change the element at index 2 of slice to 900 122 | 1. print the array 123 | 1. print the slice 124 | 125 | Output is? 126 | 127 | * [10 20 900 70 60]
[10 20 900] 128 | * [10 20 90 70 60]
[10 20 90] 129 | * [10 20 90 70 60]
[10 20 900 70 60] 130 | * [10 20 90 70 60]
[10 20 900] 131 | 132 |
133 | Reveal 134 | 135 | > [10 20 900 70 60]
[10 20 900] 136 | 137 | Let's write a program to verify this 138 | 139 | ```go 140 | package main 141 | 142 | import "fmt" 143 | 144 | func main() { 145 | // create an integer array of size 5 with values [10, 20, 90, 70, 60] 146 | arr := [5]int{10, 20, 90, 70, 60} 147 | // create a slice referencing the above array to contain elements from index 0, 1, 2 148 | slice := arr[:3] 149 | // change the element at index 2 of slice to 900 150 | slice[2] = 900 151 | // print the array 152 | fmt.Println(arr) 153 | // print the slice 154 | fmt.Println(slice) 155 | } 156 | ``` 157 | 158 | As in the previous question, the slice is a view of the underlying array so changing a value in the slice also changes the corresponding value in the array. 159 | 160 |
161 |
162 | 163 | 1.
164 | What would be the output of the following program: 165 | 166 | ```go 167 | package main 168 | 169 | import "fmt" 170 | 171 | func main() { 172 | arr := [5]int{10, 20, 90, 70, 60} 173 | slice := arr[:3] 174 | fmt.Println(cap(slice)) 175 | new_slice := append(slice, 100, 200) 176 | fmt.Println(cap(new_slice)) 177 | } 178 | ``` 179 | 180 | * 5
5 181 | * 5
10 182 | * 5
7 183 | * 10
10 184 | 185 |
186 | Reveal 187 | 188 | > 5
5 189 | 190 | * The capacity of the slice begins as 5 since we are overlaying the `[5]int` array. 191 | * Appending two more values isn't going to exceed the capacity of 5 192 | 193 |
194 |
195 | 196 | 1.
197 | What would be the output of the following program: 198 | 199 | ```go 200 | package main 201 | 202 | import "fmt" 203 | 204 | func main() { 205 | arr := [5]int{10, 20, 90, 70, 60} 206 | slice := arr[:3] 207 | fmt.Println(cap(slice)) 208 | 209 | slice_2 := make([]int, 5, 20) 210 | new_slice := append(slice, slice_2...) 211 | fmt.Println(cap(new_slice)) 212 | } 213 | ``` 214 | 215 | * 5
5 216 | * 3
23 217 | * 5
25 218 | * 5
10 219 | 220 |
221 | Reveal 222 | 223 | > 5
10 224 | 225 | 1. `slice` has a length of 3 and a capacity of 5 226 | 2. We create a new slice of length 5 and capacty 20, then append it to `slice` 227 | 3. Now the length and capacity of `slice` are exceeded so the runtime reallocates a new slice and copies any data from the original slice to it. 228 | 4. The length of the new slice is the sum of the `len()` of `slice` and `slice_2`: 3 + 5 = 8. 229 | 5. The capacity therefore needs to be increased, and a capacity increase is *usually* a doubling: 5 * 2 = 10 230 | 6. The capacity of `slice_2` is not considered by the slice reallocation code. 231 | 232 | 233 |
234 |
235 | 236 | 1.
237 | What would be the output of the following program: 238 | 239 | ```go 240 | package main 241 | 242 | import "fmt" 243 | 244 | func main() { 245 | arr := [5]int{10, 20, 90, 70, 60} 246 | slice := append(arr[:2], arr[3:]) 247 | fmt.Println(slice) 248 | } 249 | ``` 250 | 251 | * Error 252 | * [10 20 90 70 60] 253 | * [10 90 70 60] 254 | * [10, 20, 70, 60] 255 | 256 |
257 | Reveal 258 | 259 | > Error 260 | 261 | You might think the the output shuld be `[10 90 70 60]`. It would be if there wasn't a syntax error in the code. To append a slice to a slice, it requires the `...` syntax, as in the previous question. 262 | 263 |
264 |
265 | 266 | 1.
267 | What would be the output of the following program: 268 | 269 | ```go 270 | package main 271 | 272 | import "fmt" 273 | 274 | func main() { 275 | arr := []int{10, 20, 90, 70, 60} 276 | slice := make([]int, 10) 277 | num := copy(slice, arr) 278 | fmt.Println(slice) 279 | fmt.Println(num) 280 | } 281 | ``` 282 | 283 | * [10 20 90 70 60 0 0 0 0 0]
10 284 | * [10 20 90 70 60]
5 285 | * [10 20 90 70 60 0 0 0 0 0]
5 286 | * Error 287 | 288 |
289 | Reveal 290 | 291 | > [10 20 90 70 60 0 0 0 0 0]
5 292 | 293 | * We start with an array of length 5 294 | * We allocate a slice with length 10 295 | * We then copy the array into the slice and collect the number of items copied in `n` 296 | * 5 items were copied from `arr` into `slice`, which went into the first 5 elements of `slice`. `slice`'s length is still 10, so those elements contain the default value of `int` - zero. 297 | 298 |
299 |
300 | 301 | 1.
302 | What would be the output of the following program: 303 | 304 | ```go 305 | package main 306 | 307 | import "fmt" 308 | 309 | func main() { 310 | arr := []int{10, 20, 90, 70, 60} 311 | slice := make([]int, 10) 312 | copy(slice, arr) 313 | slice[1] = 1000 314 | fmt.Println(arr) 315 | fmt.Println(slice) 316 | } 317 | ``` 318 | 319 | * [10 20 90 70 60]
[10 1000 90 70 60] 320 | * [10 1000 90 70 60]
[10 1000 90 70 60 0 0 0 0 0] 321 | * [10 1000 90 70 60 0 0 0 0 0]
[10 1000 90 70 60 0 0 0 0 0] 322 | * [10 20 90 70 60]
[10 1000 90 70 60 0 0 0 0 0] 323 | 324 |
325 | Reveal 326 | 327 | > [10 20 90 70 60]
[10 1000 90 70 60 0 0 0 0 0] 328 | 329 | * As with the previous question we create an array, a slice and copy the array into the slice. 330 | * Set the second element of the slice to 1000, then print the array and the slice. 331 | * Because we created a *new* slice with `make`, it is completely unrelated to the array, so setting a value in the slice has no effect on the array. 332 | 333 |
334 |
335 | 336 | 1.
337 | What would be the output of the following program: 338 | 339 | ```go 340 | package main 341 | 342 | import "fmt" 343 | 344 | func main() { 345 | arr := [10]int{10, 20} 346 | slice := arr[2:8] 347 | fmt.Println(len(slice)) 348 | fmt.Println(cap(slice)) 349 | } 350 | ``` 351 | 352 | * 10
10 353 | * 6
8 354 | * 6
10 355 | * 6
6 356 | 357 |
358 | Reveal 359 | 360 | > 6
8 361 | 362 | * Make a 10 element array with the first two elements set to 10 and 20 (the remaining 8 will be zero) 363 | * Make a slice over the array starting at index 2 for 6 elements (start at element 2, up to but not including element 8). 364 | * `len(slice)` is 6 because we included 6 elements 365 | * `cap(slice)` is 8 because the slice shares the same memory as the array. The capacity is calculated as length of the array `arr` (10) minus the start index of the slice (2), therefore 8. 366 | 367 |
368 |
369 | 370 | -------------------------------------------------------------------------------- /docs/04-arrays-slices-and-maps/03-maps.md: -------------------------------------------------------------------------------- 1 | # Lab: Maps 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-maps/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 8 | 9 |
10 | Running the code fragments 11 | 12 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 13 | 1. Paste the question code snippet into the editor pane 14 | 1. Open the terminal window and execute `go run test.go` 15 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 16 | 17 |
18 | 19 | ### Questions 20 | 21 | 22 | 1.
23 | What would be the output of the following program: 24 | 25 | ```go 26 | package main 27 | 28 | import "fmt" 29 | 30 | func main() { 31 | var ascii_codes map[string]int 32 | ascii_codes["A"] = 65 33 | fmt.Println(ascii_codes) 34 | } 35 | ``` 36 | 37 | * A => 65 38 | * map[] 39 | * map[A:65] 40 | * Error 41 | 42 |
43 | Reveal 44 | 45 | > Error 46 | 47 | The program will compile and run, however it will panic because the map is `nil` and can't be assigned to. 48 | 49 |
50 |
51 | 52 | 1.
53 | What would be the output of the following program: 54 | 55 | ```go 56 | package main 57 | 58 | import "fmt" 59 | 60 | func main() { 61 | ascii_codes := map[string]string{} 62 | ascii_codes["A"] = 65 63 | fmt.Println(ascii_codes) 64 | } 65 | ``` 66 | 67 | * A => 65 68 | * map[] 69 | * map[A:65] 70 | * Error 71 | 72 |
73 | Reveal 74 | 75 | > Error 76 | 77 | This time the program will fail to compile. Compile time type checking spots that we are trying to add an integer value to a map that expects string values. 78 | 79 |
80 |
81 | 82 | 1.
83 | What would be the output of the following program: 84 | 85 | ```go 86 | package main 87 | 88 | import "fmt" 89 | 90 | func main() { 91 | ascii_codes := map[string]int{} 92 | ascii_codes["A"] = 65 93 | _, found := ascii_codes["B"] 94 | if found { 95 | fmt.Println("key B was not found") 96 | } 97 | } 98 | ``` 99 | 100 | * No output 101 | * A => 65 102 | * key B was not found 103 | * Error 104 | 105 |
106 | Reveal 107 | 108 | > No output 109 | 110 | * Key B was indeed not found, therefore the variable `found` is `false`. The logic to get to the `Println` requires `found` to be true. 111 | 112 | Note that this is a contrived example. In reality such code would be a developer bug! 113 | 114 |
115 |
116 | 117 | 1.
118 | Follow the given steps and select the correct output 119 | 120 | Let's write the program according to the specification in the question 121 | 122 | ```go 123 | package main 124 | 125 | import "fmt" 126 | 127 | func main() { 128 | // create a map using make() function with key data type as string, and value data type as int. 129 | ascii_codes := make(map[string]int) 130 | // Add the give key-value pairs 131 | ascii_codes["A"] = 65 132 | ascii_codes["F"] = 70 133 | ascii_codes["K"] = 75 134 | // Delete the key "F" 135 | delete(ascii_codes, "F") 136 | // Print the map 137 | fmt.Println(ascii_codes) 138 | } 139 | ``` 140 | 141 | What is the correct output? 142 | 143 | * Error 144 | * A => 65 145 | * A => 65
B => 75 146 | * map[A:65 K:75] 147 | 148 |
149 | Reveal 150 | 151 | > map[A:65 K:75] 152 | 153 | This format is how `Println` prints maps. We have deleted the "F" entry, so only have the two other values. 154 | 155 |
156 |
157 | 158 | 1.
159 | Follow the given steps and select the correct output: 160 | 161 | ```go 162 | package main 163 | 164 | import "fmt" 165 | 166 | func main() { 167 | ascii_codes := make(map[string]int) 168 | ascii_codes["A"] = 65 169 | ascii_codes["F"] = 70 170 | ascii_codes["K"] = 75 171 | fmt.Println(ascii_codes) 172 | 173 | ascii_codes = make(map[string]int) 174 | ascii_codes["U"] = 85 175 | fmt.Println(ascii_codes) 176 | } 177 | ``` 178 | 179 | * map[A:65 F:70 K:75 U:85] 180 | * map[A:65 F:70 K:75]
map[U:85] 181 | * map[A:65 F:70 K:75]
map[A:65 F:70 K:75 U:85] 182 | * Runtime Error 183 | 184 |
185 | Reveal 186 | 187 | > map[A:65 F:70 K:75]
map[U:85] 188 | 189 | * A map with 3 entries is created then printed. 190 | * Then the variable `ascii_codes` is overwritten with a *new* map that has the single entry for `U`. The original map is discarded. 191 | 192 |
193 |
194 | 195 | 1.
196 | Follow the given steps and select the correct output: 197 | 198 | ```go 199 | package main 200 | 201 | import "fmt" 202 | 203 | func main() { 204 | ascii_codes := make(map[string]int, 10) 205 | ascii_codes["A"] = 65 206 | ascii_codes["F"] = 70 207 | ascii_codes["K"] = 75 208 | fmt.Println(len(ascii_codes)) 209 | ascii_codes = make(map[string]int) 210 | ascii_codes["U"] = 85 211 | fmt.Println(len(ascii_codes)) 212 | } 213 | ``` 214 | * 3
4 215 | * 3
1 216 | * Runtime Error 217 | * 3
3 218 | 219 |
220 | Reveal 221 | 222 | > 3
1 223 | 224 | * The second argument to `make` for maps is *initial capacity*, not length. Because only 3 values are added, `len()` returns 3. 225 | * The map is recreated and one entry added to it, so the second call to `len()` yields 1. 226 |
227 |
228 | -------------------------------------------------------------------------------- /docs/04-arrays-slices-and-maps/04-arrays-slices-and-maps.md: -------------------------------------------------------------------------------- 1 | # Lab: Arrays, Slices and Maps 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-arrays-slices-and-maps/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | All the code fragments in this lab are complete mini-programs, so you can paste them into the editor and run them to see the results: 8 | 9 |
10 | Running the code fragments 11 | 12 | 1. Right click in Explorer pane to create a new file, e.g. `test.go` 13 | 1. Paste the question code snippet into the editor pane 14 | 1. Open the terminal window and execute `go run test.go` 15 | 1. Re-use your `test.go` file by replacing the content with that of the next question. 16 | 17 |
18 | 19 | ### Questions 20 | 21 | 1.
22 | What would be the output of the following program: 23 | 24 | ```go 25 | package main 26 | 27 | import "fmt" 28 | 29 | func main() { 30 | arr := [5]string{"one", "two", "three"} 31 | slice := arr[:3] 32 | my_map := make(map[int]string) 33 | for i, el := range slice { 34 | my_map[i+1] = el 35 | } 36 | fmt.Println(my_map) 37 | } 38 | ``` 39 | 40 | * map[1:one 2:two 3:three] 41 | * Syntax Error 42 | * map["1":one "2":two "3":three] 43 | * 1 => one
2 => two 44 | 45 |
46 | Reveal 47 | 48 | > map[1:one 2:two 3:three] 49 | 50 | There's no syntax error in this program, so that answer is eliminated. The program flows like this: 51 | 52 | 1. Create an array of 5 strings. Set values for the first 3 53 | 1. Create a slice over the first 3 elements of the array 54 | 1. Make a new map with integer keys and string values (eliminates answer `map["1":one "2":two "3":three]`). 55 | 1. Use `for` to iterate the slice, getting index in `i` and value in `el` 56 | 1. Add a map entry with key of `i+1` and value taken from the slice at position `i`. This will result in keys of 1, 2, 3 and corresponding values of one, two, three 57 | 1. Print the map 58 | 59 | 60 |
61 |
62 | 63 | 1.
64 | What would be the output of the following program: 65 | 66 | ```go 67 | package main 68 | 69 | import "fmt" 70 | 71 | func main() { 72 | arr := [5]int{} 73 | my_map := make(map[string]int) 74 | my_map["A"] = 65 75 | my_map["B"] = 66 76 | i := 0 77 | for _, value := range my_map { 78 | arr[i] = value 79 | i += 1 80 | } 81 | fmt.Println(arr) 82 | } 83 | ``` 84 | 85 | * [A B ] 86 | * [65 66 0 0 0] 87 | * Runtime Error 88 | * [65 66 67 0 0] 89 | 90 |
91 | Reveal 92 | 93 | > [65 66 0 0 0] 94 | 95 | The program flows like this: 96 | 97 | 1. Create an array of 5 ints. Recall that all 5 elements in the array will be initialized with the default value of int - zero. 98 | 1. Make a new map with string keys and int values. 99 | 1. Create two keys A and B with corresponding values 1 and 2 in the map. 100 | 1. Set index variable `i` to zero. 101 | 1. Use `for` to iterate the map values only. The keys are ignored with `_`. 102 | 1. Set the array element at index `i` with the value received from the map. 103 | 1. Increment `i` ready for next array element. 104 | 1. Print the array. 105 | 106 | We can eliminate `Runtime Error` as an answer as the only place that could occur is in the `for` loop if we exceeded the size of the array. The `for` loop will iterate 2 map elements. The array will fit 5 values. 107 | 108 | The two values from the map will be stored in the first two elements of the array, yielding the given answer. 109 | 110 |
111 |
112 | 113 | 1.
114 | What would be the output of the following program: 115 | 116 | ```go 117 | package main 118 | 119 | import "fmt" 120 | 121 | func main() { 122 | arr := [5]int{10, 20, 30, 90, 100} 123 | new_slice := append(arr[:3], arr[4:]...) 124 | fmt.Print(new_slice) 125 | } 126 | ``` 127 | 128 | * [10 20 90 100] 129 | * [10 20 30 90] 130 | * [10 20 30 100] 131 | * [10, 20, 30, 90, 100] 132 | 133 |
134 | Reveal 135 | 136 | > [10 20 30 100] 137 | 138 | The program flows like this: 139 | 140 | 1. Create an array of 5 ints, all with initial values 141 | 1. Create a new slice by taking the first 3 elements of `arr` (10, 20, 30) and appending the rest of `arr` from element 4 to the end (100). 142 | 1. Print the slice, yielding the given answer. 143 | 144 |
145 |
146 | 147 | 1.
148 | What would be the output of the following program: 149 | 150 | ```go 151 | package main 152 | 153 | import "fmt" 154 | 155 | func main() { 156 | my_map := make([int]int) 157 | my_map[2] = 4 158 | my_map[4] = 16 159 | my_map[8] = 64 160 | delete(my_map, 4) 161 | fmt.Print(my_map) 162 | } 163 | ``` 164 | 165 | * map[2:4 4:16] 166 | * map[2:4 8:64] 167 | * map[8:64 4:16] 168 | * Error 169 | 170 |
171 | Reveal 172 | 173 | > Error 174 | 175 | The program will not compile because `make([int]int)` is a syntax error. Should have been `make(map[int]int)`. 176 | 177 |
178 |
179 | 180 | 1.
181 | What would be the output of the following program: 182 | 183 | ```go 184 | package main 185 | 186 | import "fmt" 187 | 188 | func main() { 189 | arr := [10]string{"a", "b", "c"} 190 | hashmap := make(map[string]int) 191 | my_slice := arr[:] 192 | fmt.Println(len(my_slice)) 193 | fmt.Println(cap(my_slice)) 194 | fmt.Println(len(hashmap)) 195 | } 196 | ``` 197 | 198 | * 3
10
1 199 | * 1
10
1 200 | * Error 201 | * 10
10
0 202 | 203 |
204 | Reveal 205 | 206 | > 10
10
0 207 | 208 | The program flows like this: 209 | 210 | 1. Create an array of 10 strings with values for the first 3. The remaining 7 elements will have the default value for string with is the empty string. 211 | 1. Make a new map with string keys and integer values. 212 | 1. Make a slice over `arr`. Note that `[:]` means include *all* elements, in this case 10. 213 | 1. Print len of `my_slice` - will be 10 as noted in the point above. 214 | 1. Print cap of `my_slice` - will also be 10 as we included the whole array. 215 | 1. Print len of `hashmap` - will be zero because we added no map entries. 216 | 217 |
218 |
219 | 220 | -------------------------------------------------------------------------------- /docs/05-using-functions.md/01-function-syntax.md: -------------------------------------------------------------------------------- 1 | # Lab: Function Syntax 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-function-syntax/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | Define a function with following specs, and choose the correct definition 9 | 10 | * Name of function: `returnCube` 11 | * Input parameters: `int` 12 | * Output parameters: `int` 13 | * The function calculates the cube of `n` (`n*n*n`) 14 | 15 | Is it - 16 | 17 | * ``` 18 | func returnCube(n) int { 19 | return n*n*n 20 | } 21 | ``` 22 | * ``` 23 | func returnCube(int) int { 24 | return n*n*n 25 | } 26 | ``` 27 | * ``` 28 | func returnCube(n int) int { 29 | return n*n*n 30 | } 31 | ``` 32 | * ``` 33 | funct returnCube(n int) int { 34 | return n*n*n 35 | } 36 | ``` 37 | 38 | 39 |
40 | Reveal 41 | 42 | ``` 43 | func returnCube(n int) int { 44 | return n*n*n 45 | } 46 | ``` 47 | 48 | Function syntax is as follows 49 | 50 | 1. keyword `func` (not `funct`) 51 | 1. input parameters surrounded with brackets `()`, or empty brackets if no input parameters. 52 | 1. Each input parameter is variable name followed by type, e.g. `n int`. 53 | 1. After `)` is the *type* of what we want to return (if anything), in this case `int` 54 | 1. Lastly `{` to begin the function body. 55 | 56 | Then we have the code of the function followed by `}` to close it off 57 |
58 |
59 | 60 | 1.
61 | What would be the output of the following program: (add package declarations and import statements as needed) 62 | 63 | ```go 64 | func returnCube(n int) int { 65 | return n*n*n 66 | } 67 | 68 | func main() { 69 | returnCube(5) 70 | } 71 | ``` 72 | 73 | * no output 74 | * error 75 | * 5 125 76 | * 125 77 | 78 |
79 | Reveal 80 | 81 | > no output 82 | 83 | Why? Becuase we are not doing anything with the value we get from `returnCube`, certainly not printing it! 84 | 85 | Note that to try this program, you would have to include `package main` as the first line. 86 | 87 |
88 |
89 | 90 | 1.
91 | Select valid function declarations from the below options. 92 | 93 | 1. `func 3doSomething(n int) int` 94 | 1. `func doSomething(a int, b int) int` 95 | 1. `func doSomething(n int) int` 96 | 1. `func do Something(n int) int` 97 | 98 |
99 | Reveal 100 | 101 | > B. C 102 | 103 | * A is incorrect because an identifier (function name, variable name etc.) cannot start with a digit. 104 | * D is incorrect because an identifier cannot contain whitespace. 105 | 106 |
107 |
108 | 109 | 1.
110 | Choose the correct function declaration of function printDetails so the following code can be executed successfully in main function. 111 | 112 | ```go 113 | var s string 114 | s = printDetails("Joe") 115 | fmt.Print(s) 116 | ``` 117 | and gives the following output 118 | 119 | ``` 120 | Joe 121 | 1 122 | ``` 123 | 124 | * `func printDetails(s string) int` 125 | * `func print_Details(s string) string` 126 | * `func printDetails(s int) string` 127 | * `func printDetails(s string) string` 128 | 129 |
130 | Reveal 131 | 132 | > `func printDetails(s string) string` 133 | 134 | To answer this, you do not need to be concerned about the actual output other then realizing that it must be a string. What you do need to be concerned about is selecting the correct function *signature* from the four options. 135 | 136 | * `func printDetails(s string) int` - is incorrect as it returns an `int`. Not possible to get the required output with an int return type. 137 | * `func print_Details(s string) string` - is incorrect because the function is named incorrectly. 138 | * `func printDetails(s int) string` - returns the correct type, but is incorrect because its input is `int` - can't pass `Joe` as an int parameter. 139 | 140 |
141 |
142 | 143 | 1.
144 | What would be the output of the following program: 145 | 146 | ```go 147 | func printDetails(s string) { 148 | fmt.Println(s) 149 | } 150 | 151 | func main() { 152 | x := printDetails("Joe") 153 | fmt.Print(x) 154 | } 155 | ``` 156 | 157 | * error 158 | * empty string 159 | * nil 160 | * 0 161 | 162 |
163 | Reveal 164 | 165 | > error 166 | 167 | The program will not compile due to this 168 | 169 | `x := printDetails("Joe")` 170 | 171 | Look at `printDetails` function. Does it return anything? No, so you can't assign a variable from the result of a call to this function. 172 | 173 |
174 |
175 | 176 | -------------------------------------------------------------------------------- /docs/05-using-functions.md/02-return-types-multiple-named-variadic.md: -------------------------------------------------------------------------------- 1 | # Lab: Function Syntax 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-return-types-multiple-named-variadic/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | What would be the output of the following program: 9 | 10 | ```go 11 | func doSomething(int, int) int { 12 | return "2" 13 | } 14 | 15 | func main() { 16 | fmt.Println(doSomething(1, 2)) 17 | } 18 | ``` 19 | 20 | * 1 2
1 21 | * error 22 | * "2" 23 | * 2 24 | 25 |
26 | Reveal 27 | 28 | > error 29 | 30 | The program would not complile. The function return type is `int` therefore it cannot return the string `"2"` 31 | 32 |
33 |
34 | 35 | 1.
36 | What would be the output of the following program: 37 | 38 | ```go 39 | func calcSquare(numbers []int) []int { 40 | squares := []int{} 41 | for _, v := range numbers { 42 | squares = append(squares, v*v) 43 | } 44 | return squares 45 | 46 | } 47 | 48 | func main() { 49 | nums := [3]int{10, 20, 15} 50 | fmt.Println(calcSquare(nums[:])) 51 | } 52 | ``` 53 | 54 | * [10 20 15] 55 | * [100 400 900] 56 | * Error 57 | * [100 400 225] 58 | 59 |
60 | Reveal 61 | 62 | > [100 400 225] 63 | 64 | * The function accepts an `int` slice and returns an `int` slice 65 | * `nums[:]` is the correct way to pass the array `nums` to the function as a slice 66 | * The `for` loop in the function builds a slice of the squares of the values in the input slice 67 | * The return value of the function is printed 68 | 69 |
70 |
71 | 72 | 1.
73 | What would be the output of the following program: 74 | 75 | ```go 76 | func calcSquare(numbers []int) ([]int, bool) { 77 | squares := []int{} 78 | for _, v := range numbers { 79 | squares = append(squares, v*v) 80 | } 81 | return squares, true 82 | 83 | } 84 | 85 | func main() { 86 | nums := [3]int{10, 20, 15} 87 | fmt.Println(calcSquare(nums[:])) 88 | } 89 | ``` 90 | 91 | * [100 400 225] true 92 | * [100 400 225] 93 | * [10 20 15] 94 | * Error 95 | 96 | 97 |
98 | Reveal 99 | 100 | > [100 400 225] true 101 | 102 | This is almost the same as the previous question. The difference is that the function has two return values: `[]int` and `bool` 103 | 104 | `squares` and `true` are returned by the function, and are printed. 105 | 106 |
107 |
108 | 109 | 1.
110 | What would be the output of the following program: 111 | 112 | ```go 113 | func printStrings(s string, names ...string) { 114 | fmt.Println(s) 115 | for _, value := range names { 116 | fmt.Printf("%s, ", value) 117 | } 118 | 119 | } 120 | 121 | func main() { 122 | printStrings("Hey there", "Joe", "Monica", "Gunther") 123 | } 124 | ``` 125 | 126 | * Hey there
Joe, Monica, Gunther 127 | * Hey there, Joe, Monica, Gunther, 128 | * Hey there
Joe,
Monica,
Gunther, 129 | * Hey there
Joe, Monica, Gunther, 130 | 131 |
132 | Reveal 133 | 134 | > Hey there
Joe, Monica, Gunther, 135 | 136 | * The function `printStrings` has two argumentsL: `s` and `names` 137 | * `s` will get the first string passed to the function call (i.e. `Hey there`) 138 | * `names` is variadic so will be represented as a slice of strings, and gets everything that follows `Hey there` 139 | * The value of `s` is printed on its own line 140 | * The remaining values are printed on the same line with a comma following each. 141 | 142 |
143 |
144 | 145 | 1.
146 | What would be the output of the following program: 147 | 148 | ```go 149 | func printStrings(names ...string) (names_c []string) { 150 | names_c := []string {} 151 | for _, value := range names { 152 | names_c = append(names_c, strings.ToUpper(value)) 153 | } 154 | return 155 | } 156 | 157 | func main() { 158 | result := printStrings("Joe", "Monica", "Gunther") 159 | fmt.Println(result) 160 | } 161 | ``` 162 | 163 | * No output 164 | * [JOE MONICA GUNTHER] 165 | * Error 166 | * Joe, Monica, Gunther, 167 | 168 |
169 | Reveal 170 | 171 | > Error 172 | 173 | This is a tricky one to spot! 174 | 175 | Firstly note that to be able to try to run this program we need an additional import! `import "strings"` is required for `strings.ToUpper` 176 | 177 | Now you've put `package main` and imported `"strings"` and `"fmt"`, there is still a compilation error, which is why the answer is "Error". 178 | 179 | The message `no new variables on left side of :=` means that you are trying to create a new variable using the name of a vairable that already exists. It's complaining about `names_c`. Why? Because the function uses a *named* return type: `(names_c string)`. This means that the variable `names_c` is already declared within the scope of the function, and why it ends with `return` and not `return names_c`. 180 | 181 | To fix the compilation error we would change the line
`names_c := []string {}`
to
`names_c = []string {}` - try it! 182 | 183 |
184 |
185 | 186 | -------------------------------------------------------------------------------- /docs/05-using-functions.md/03-recursive-functions.md: -------------------------------------------------------------------------------- 1 | # Lab: Recursive Functions 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-recursive-functions/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | What is the most appropriate definition for recursion? 9 | 10 | 1. A function that calls another function. 11 | 1. A function that calls another execution instance of the same function. 12 | 1. An in-built method for solving base cases related problems. 13 | 1. A variadic function that calls another variadic function. 14 | 15 |
16 | Reveal 17 | 18 | > B 19 | 20 | Also known as "a function that calls itself" 21 | 22 |
23 |
24 | 25 | 1.
26 | Complete the missing line (to calculate the factorial of a number) 27 | 28 | ```go 29 | func fact(n int) int { 30 | if n == 0 { 31 | return 1 32 | } 33 | return ______ 34 | } 35 | ``` 36 | 37 |
38 | Reveal 39 | 40 | > `n * fact(n-1)` 41 | 42 | Calculating a factorial is a classic use case for recursion. 43 | 44 | ``` 45 | n! = n * (n-1) * (n-2) * (n-3) * ... * 3 * 2 * 1 46 | = n * (n-1)! 47 | ``` 48 | 49 | In mathematics, the factorial of a non-negative integer `n`, denoted by `n!`, is the product of all positive integers less than or equal to `n`. The factorial of `n` also equals the product of `n` with the next smaller factorial. This fact is what makes the calculation suitable for a recursive function. 50 | 51 |
52 |
53 | 54 | 1.
55 | What would be the output of the following program: 56 | 57 | ```go 58 | func print(n int) { 59 | if n == 0 { 60 | return 61 | } 62 | fmt.Print(n) 63 | print(n - 1) 64 | } 65 | 66 | func main() { 67 | print(5) 68 | } 69 | ``` 70 | 71 | * 5 4 3 2 1 72 | * 54321 73 | * 12345 74 | * 1 2 3 4 5 75 | 76 |
77 | Reveal 78 | 79 | > 54321 80 | 81 | * `main()` begins by calling `print()` with `5`. 82 | * In the `print()` function, `n` starts as `5`, so that is printed first. This eliminates two possible answers. 83 | * Then `print` calls itself, with `n-1`, i.e. 4. Here is the recursion. 84 | * `print` will keep doing this until `n == 0`, which will be after `1` has been printed. Then it will return all the way up and the program will end. 85 | * `fmt.Print` will not emit a space after printing an integer, so that leaves only the given answer. 86 | ` 87 |
88 |
89 | 90 | 1.
91 | What would be the output of the following program: 92 | 93 | ```go 94 | func print(n int) { 95 | if n == 0 { 96 | return 97 | } 98 | print(n - 1) 99 | fmt.Print(n) 100 | } 101 | 102 | func main() { 103 | print(5) 104 | } 105 | ``` 106 | 107 | * 5 4 3 2 1 108 | * 54321 109 | * 12345 110 | * 1 2 3 4 5 111 | 112 |
113 | Reveal 114 | 115 | > 12345 116 | 117 | This is subtly different from the previous question! Firstly for the same reason ias the previous question, we can rule out the answers that have spaces between the numbers. 118 | 119 | What's different? This time round it recurses all the way down until the function bottoms out (`n == 0`), then as it returns up the stack it prints the output. At maximum recursion it makes the fisrt return, then it starts printing where `n == 1` and returns and so on, so the numbers are printed in ascending order as we return up the stack. 120 | 121 |
122 |
123 | 124 | 1.
125 | Select the correct base case for function printSquares - 126 | 127 | for input n -> prints squares for n, n-1, n-2, ... -5 128 | 129 | Example: Input: n=2 Output: 4, 1, 0, 1, 4, 9, 16, 25 130 | 131 | ```go 132 | func print(n int) { 133 | // base case 134 | fmt.Printf("%d ", n*n) 135 | print(n - 1) 136 | } 137 | 138 | func main() { 139 | print(2) 140 | } 141 | ``` 142 | 143 | Replace `// base case` with which of the following: 144 | 145 | * ```go 146 | if n == 5 { 147 | return 148 | } 149 | ``` 150 | * ```go 151 | if n == -5 { 152 | return 153 | } 154 | ``` 155 | * ```go 156 | if n == 0 { 157 | return 158 | } 159 | ``` 160 | * ```go 161 | if n == -6 { 162 | return 163 | } 164 | ``` 165 | 166 |
167 | Reveal 168 | 169 | ```go 170 | if n == -6 { 171 | return 172 | } 173 | ``` 174 | 175 | * The specification requires to print the squares of numbers from the starting value down to *and including* `-5` 176 | * The `print()` function prints the square first, then calls itself with the next smaller number 177 | * Therefore to get -52 printed, it will then call itself with -6, so this is what must be tested for to bottom out the recursion and return. 178 | 179 |
180 |
181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /docs/05-using-functions.md/04-anonymous-functions.md: -------------------------------------------------------------------------------- 1 | # Lab: Anonymous Functions 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-anonymous-functions/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 8 | 1.
9 | What is the most appropriate definition for recursion? 10 | 11 | 1. ```go 12 | var my_func := (func(s string) {fmt.Println("Hey there,", s)}) 13 | ``` 14 | 1. ```go 15 | var (my_func = func(s string) {fmt.Println("Hey there,", s)}) 16 | ``` 17 | 1. ```go 18 | func main() { 19 | var ( 20 | my_func = func(s string) { fmt.Println("Hey there,", s) } 21 | ) 22 | my_func("Joe") 23 | } 24 | ``` 25 | 1. ```go 26 | var my_func func := (func(s string) {fmt.Println("Hey there,", s)}) 27 | ``` 28 | 29 |
30 | Reveal 31 | 32 | > B, C 33 | 34 | Quite simply, you can never use `:=` with a `var` statement, leaving only two possible answers. 35 | 36 |
37 |
38 | 39 | 1.
40 | What would be the output of the following program: 41 | 42 | ```go 43 | package main 44 | 45 | import ( 46 | "fmt" 47 | "strings" 48 | ) 49 | 50 | func main() { 51 | x := func(s string) string { 52 | return strings.ToUpper(s) 53 | } 54 | fmt.Printf("%T \n", x) 55 | fmt.Println(x("Joe")) 56 | } 57 | ``` 58 | 59 | * func(string) string
joe 60 | * func(string) string
JOE 61 | * string
Joe 62 | * func(string)
JOE 63 | 64 |
65 | Reveal 66 | 67 | > func(string) string
JOE 68 | 69 | * Declare a variable `x` as an anonymous function that takes a `string`, returns a `string` with a body that returns the uppercase of what ever is passed as the argument. 70 | * Print the type of variable `x`, which will yield the function signature. A signature comprises: 71 | 1. `func` 72 | 1. `(` 73 | 1. List of argument *types* (if any) 74 | 1. `)` 75 | 1. Return type(s) (if any) - the return types being a bracketed list if there is more then one. 76 | * Print the invocation of the function via `x`, passing "Joe" as an argument. This is returned as "JOE" which gets printed. 77 | 78 |
79 |
80 | 81 | 1.
82 | What would be the output of the following program: 83 | 84 | ```go 85 | package main 86 | 87 | import ( 88 | "fmt" 89 | "strings" 90 | ) 91 | 92 | func main() { 93 | x := func(s string) { 94 | fmt.Println(strings.ToLower(s)) 95 | } 96 | fmt.Printf("%T \n", x) 97 | x("RacheL") 98 | } 99 | ``` 100 | 101 | * func(string)
rachel 102 | * func(string) string
RACHEL 103 | * func(string) string
rachel 104 | * func(string)
Rachel 105 | 106 |
107 | Reveal 108 | 109 | > func(string)
rachel 110 | 111 | Very similar to the previous question, however 112 | 113 | * Variable `x` is assigned the anonymous function 114 | * The function handles the printing itself, therefore does not return anything, thus the signature that is printed is only `func(string)` 115 | * The function is lowercasing the value it is given. 116 | 117 |
118 |
119 | 120 | 1.
121 | What would be the output of the following program: 122 | 123 | ```go 124 | package main 125 | 126 | import ( 127 | "fmt" 128 | "strings" 129 | ) 130 | 131 | func main() { 132 | x := func(s string) { 133 | fmt.Println(strings.ToLower(s)) 134 | }("RacheL") 135 | fmt.Printf("%T \n", x) 136 | } 137 | ``` 138 | 139 | * func(string)
Rachel 140 | * Error 141 | * func(string) string
rachel 142 | * func(string)
rachel 143 | 144 |
145 | Reveal 146 | 147 | > Error 148 | 149 | * The compiler detects an attempt to call the function during assignment of an anonymous function to a variable :- `}("RacheL)`. This is illegal so the program fails to compile. 150 | 151 |
152 |
153 | 154 | 1.
155 | What would be the output of the following program: 156 | 157 | Add package and import statements as needed 158 | 159 | ```go 160 | var ( 161 | cube = func(i int) string { 162 | c := i * i * i 163 | return strconv.Itoa(c) 164 | } 165 | ) 166 | 167 | func main() { 168 | x := cube(8) 169 | fmt.Printf("%T %v", x, x) 170 | } 171 | ``` 172 | 173 | * func(i int) string
512 174 | * int 512 175 | * func(i int) int string
512 176 | * string 512 177 | 178 |
179 | Reveal 180 | 181 | > string 512 182 | 183 | Note the use of `strconv.Itoa`. To build this program requires the additional import of `"strconv"`. Recall from earlier labs that `Itoa` converts an integer to its string representation. 184 | 185 | * `cube` is declared as a package variable that holds an anonymous function that takes `int` and returns `string` 186 | * The function computes the cube of `i`, converts that to a string and returns it. 187 | * In `main()` variable `x` is assigned the value returned by calling `cube` with 8. 188 | * Finally print the type and value of `x`. `x` is the value returned by `cube`, not `cube` itself, therefore its type is `string`. The value of `x` is the string "512" so that's just printed. It's all on the same line since it's a single `Printf` with no newline character in it. 189 | 190 |
191 |
192 | 193 | -------------------------------------------------------------------------------- /docs/05-using-functions.md/05-high-order-functions.md: -------------------------------------------------------------------------------- 1 | # Lab: High Order Function 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-high-order-functions/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | Select the correct statement(s) for high order functions 9 | 10 | 1. Function that receives a function as an argument. 11 | 1. Function that contains a function. 12 | 1. Function that returns another function. 13 | 1. Function that calls another function. 14 | 15 |
16 | Reveal 17 | 18 | > A. C 19 | 20 | These two answers correctly define a high order function. 21 | 22 |
23 |
24 | 25 | 1.
26 | What would be the output of the following program? 27 | 28 | ```go 29 | package main 30 | 31 | import "fmt" 32 | 33 | func addHundred(x int) int { 34 | return x + 100 35 | } 36 | func partialSum(x ...int) func() { 37 | sum := 0 38 | for _, value := range x { 39 | sum += value 40 | } 41 | return func() { 42 | fmt.Println(addHundred(sum)) 43 | } 44 | } 45 | func main() { 46 | partial := partialSum(1, 2, 3, 4, 5) 47 | partial() 48 | } 49 | ``` 50 | 51 | * 110 52 | * 15 53 | * Error 54 | * 115 55 | 56 |
57 | Reveal 58 | 59 | > 115 60 | 61 | * The function `partialSum` adds together the values of the integers it receives and stores them in `sum`. 62 | * It then returns an anonymous function that prints the value of `sum` plus 100 (via call to `addHundred`). 63 | * Recall that the body of this anonymous function is an inner scope with respect to `partialSum` meaning it can use the variable `sum`. 64 | * The variable `partial` is assigned the result of the call to `partialSum`. Its value is the anonymous function returned by `partialSum`. 65 | * Finally the anonymous function is executed via the variable `partial` by applying the call operator `()` - i.e. `partial()` and the result is printed. 66 | 67 |
68 |
69 | 70 | 1.
71 | What would be the output of the following program? 72 | 73 | ```go 74 | package main 75 | 76 | func addHundred(x int) int { 77 | return x + 100 78 | } 79 | func partialSum(x ...int) func() int { 80 | sum := 0 81 | for _, value := range x { 82 | sum += value 83 | } 84 | return func() int { 85 | return addHundred(sum) 86 | } 87 | } 88 | func main() { 89 | partial := partialSum(1, 2, 3) 90 | partial() 91 | } 92 | ``` 93 | 94 | * 106 95 | * no output 96 | * Error 97 | * 115 98 | 99 |
100 | Reveal 101 | 102 | > No output 103 | 104 | Quite simply there is no `fmt.Println` so nothing will be printed. 105 | 106 | This is a minor variation on the previous question. The caculated result would indeed be `106`, but since the `fmt.Println` has been removed from the returned anonymous function, there is no output. 107 | 108 |
109 |
110 | 111 | 1.
112 | What would be the output of the following program? 113 | 114 | ```go 115 | package main 116 | 117 | import "fmt" 118 | 119 | func addHundred(x int) int { 120 | return x + 100 121 | } 122 | func partialSum(add100 func(x int) int, x ...int) int { 123 | sum := 0 124 | for _, value := range x { 125 | sum += value 126 | } 127 | return add100(sum) 128 | 129 | } 130 | func main() { 131 | partial := partialSum(addHundred, 1, 2, 3) 132 | fmt.Println(partial) 133 | } 134 | ``` 135 | 136 | * 6 137 | * 115 138 | * 106 139 | * error 140 | 141 |
142 | Reveal 143 | 144 | > 106 145 | 146 | Yet another variation on the theme, however this time... 147 | 148 | * The `addHundred` function is being passed as the first argument to `partialSum`, then the list of integers to sum. 149 | * `partialSum` sums the integers, then calls the `addHundred` function and returns its result. 150 | * `main()` assigns that value to `partial` (whose type will now be `int`), and prints it. 151 | 152 |
153 |
154 | 155 | 1.
156 | What would be the output of the following program? 157 | 158 | ```go 159 | package main 160 | 161 | import "fmt" 162 | 163 | func addHundred(x int) { 164 | fmt.Println(x + 100) 165 | } 166 | func partialSum(add100 func(x int), x ...int) int { 167 | sum := 0 168 | for _, value := range x { 169 | sum += value 170 | } 171 | add100(sum) 172 | return 0 173 | } 174 | func main() { 175 | partial := partialSum(addHundred, 1, 2, 3) 176 | fmt.Println(partial) 177 | } 178 | ``` 179 | 180 | * Error 181 | * 106
0 182 | * 115
1 183 | * 115
0 184 | 185 |
186 | Reveal 187 | 188 | > 106
0 189 | 190 | Similar to the previous question, however this time... 191 | 192 | * `addHundred` does the printing of the result of the sum. 193 | * `partialSum` simply returns zero 194 | * `main()` assigns that value to `partial` (whose type will now be `int`), and prints it (zero). 195 | 196 |
197 |
198 | 199 | 200 | -------------------------------------------------------------------------------- /docs/05-using-functions.md/06-functions.md: -------------------------------------------------------------------------------- 1 | # Lab: Functions 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-functions-2/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 8 | 1.
9 | Select the correct statement(s) for defer statement. 10 | 11 | 1. `defer` statement delays the execution of a function until the previous function returns. 12 | 1. `defer` statement delays the execution of a function until the following function returns. 13 | 1. `defer` statement delays the execution of a surrounding function until the current function returns. 14 | 1. `defer` statement delays the execution of a function until the surrounding function returns. 15 | 16 |
17 | Reveal 18 | 19 | > D 20 | 21 | ```go 22 | func afunction() { 23 | // This function is surrounding the folliowing defer 24 | defer fmt.Println("defer executed") 25 | fmt.Println("this will print first") 26 | } // defer executes here 27 | ``` 28 | 29 |
30 |
31 | 32 | 1.
33 | What would be the output of the following program? 34 | 35 | ```go 36 | package main 37 | 38 | import "fmt" 39 | 40 | func printString(str string) { 41 | fmt.Printf("%q ", str) 42 | } 43 | 44 | func printInt(i int) { 45 | fmt.Printf("%d ", i) 46 | } 47 | 48 | func printFloat(f float64) { 49 | fmt.Printf("%.2f ", f) 50 | } 51 | func main() { 52 | printString("browser") 53 | defer printInt(32) 54 | defer printFloat(0.24) 55 | printString("chrome") 56 | printInt(90) 57 | defer printFloat(89) 58 | printInt(900) 59 | } 60 | ``` 61 | 62 | * "browser" "chrome" 90 0.24 32 900 89.00 63 | * browser chrome 90 900 89.00 0.24 32 64 | * "browser" "chrome" 90 900 89.00 0.24 32 65 | * browser chrome 0.24 32 90 900 89.00 66 | 67 |
68 | Reveal 69 | 70 | > "browser" "chrome" 90 900 89.00 0.24 32 71 | 72 | * `printString` uses the `%q` formatter meaning that strings are printed in quotes. This rules out two possible answers. 73 | * Recall that `defer` statements execute after everything else in the function, so this means that "browser", "chrome" and 90 will be output first. 74 | * Recall that multiple `defer` statements execute in the reverse order to which they are declared. This a "stack" behaviour: last in first out. This tells us that the order of output from the defers will be 89.00, 0.24, 32 - yielding the correct answer. 75 | 76 |
77 |
78 | 79 | 1.
80 | What would be the output of the following program? 81 | 82 | ```go 83 | package main 84 | 85 | import ( 86 | "fmt" 87 | "strings" 88 | ) 89 | 90 | func getString(str string) (string, string) { 91 | return strings.ToLower(str), strings.ToUpper(str) 92 | } 93 | 94 | func main() { 95 | _, lower := getString("BROWSER") 96 | fmt.Println(lower) 97 | } 98 | ``` 99 | 100 | * browser 101 | * error 102 | * BROWSER 103 | * Browser 104 | 105 |
106 | Reveal 107 | 108 | > BROWSER 109 | 110 | * The function `getString` returns two values: 111 | 1. Lower case version of the input 112 | 2. Upper case version of the input 113 | * When the function is called in `main`, the assignment is to `_, lower`. 114 | * The first return value (the lowercase version) is discarded (assigned to `_`). 115 | * The second return value (the uppercase version) is assigned to `lower`, which is then printed. 116 | 117 |
118 |
119 | 120 | 1.
121 | Make the required changes in the function body: 122 | 123 | ```go 124 | func greetings() (x, y string) { 125 | x := "hello " 126 | y := "world" 127 | } 128 | 129 | func main() { 130 | fmt.Print(greetings()) 131 | } 132 | ``` 133 | 134 | ...so the output is `hello world`. Select the corect definitions: 135 | 136 | 1. ```go 137 | func greetings() (x, y string) { 138 | x := "hello " 139 | y := "world" 140 | return x, y 141 | } 142 | ``` 143 | 1. ```go 144 | func greetings() (x, y string) { 145 | x = "hello " 146 | y = "world" 147 | return x, y 148 | } 149 | ``` 150 | 1. ```go 151 | func greetings() (x, y string) { 152 | x = "hello " 153 | y = "world" 154 | return 155 | } 156 | ``` 157 | 1. ```go 158 | func greetings() (x, y string) { 159 | x := "hello " 160 | y := "world" 161 | return "hello world" 162 | } 163 | ``` 164 | 165 |
166 | Reveal 167 | 168 | > B, C 169 | 170 | * A is incorrect because `x` and `y` are named return values, therefore they cannot be reassigned with `:=` 171 | * B is correct because the values are correctly assigned. You can return the named variables by name. 172 | * C is correct because the values are correctly assigned, and the named variables are implicitly returned. 173 | * D is incorrect for the same reason as A, and also because it only returns one value when two are expected. 174 | 175 |
176 |
177 | 178 | 1.
179 | What would be the output of the following program? 180 | 181 | ```go 182 | package main 183 | 184 | import ( 185 | "fmt" 186 | ) 187 | 188 | func main() { 189 | fmt.Println(f1()) 190 | } 191 | 192 | func f1() int { 193 | return f2() 194 | } 195 | 196 | func f2() int { 197 | return 1 198 | } 199 | ``` 200 | 201 | * 1 1 202 | * no output 203 | * error 204 | * 1 205 | 206 |
207 | Reveal 208 | 209 | > 1 210 | 211 | Starting from `main` 212 | 1. It prints the return value of `f1()` 213 | 1. `f1` returns the function `f2` 214 | 1. `f2` returns `1` 215 | 216 | Thus the `fmt.Println` is actually calling `f2` as it's what is returned by `f1`. 217 | 218 |
219 |
220 | 221 | -------------------------------------------------------------------------------- /docs/06-pointers/01-pointers.md: -------------------------------------------------------------------------------- 1 | # Lab: Pointers 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-pointers/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | What would be the output of the following program: 9 | 10 | Note: add package and import statements as needed 11 | 12 | ```go 13 | package main 14 | 15 | import ( 16 | "fmt" 17 | ) 18 | 19 | func modify(y int) int { 20 | y += 15 21 | return y 22 | } 23 | func main() { 24 | y := 20 25 | modify(y) 26 | fmt.Println(y) 27 | } 28 | ``` 29 | 30 | * 35 31 | * 20 32 | * error 33 | * 15 34 | 35 |
36 | Reveal 37 | 38 | > 20 39 | 40 | Contrary to how the function is named, the value of `y` in `main` is *not* modified. A *copy* of `y` is modified inside the `modify` function and the modified value returned, however the return value isn't used. 41 | 42 |
43 |
44 | 45 | 1.
46 | What would be the output of the following program: 47 | 48 | Note: add package and import statements as needed 49 | 50 | ```go 51 | func main() { 52 | y := [3]int{10, 20, 30} 53 | py := &y 54 | fmt.Printf("%T %v \n", py, *py) 55 | } 56 | ``` 57 | 58 | * *[]int
[10 20 30] 59 | * *int [10 20 30] 60 | * *[3]int 61 | * *[3]int [10 20 30] 62 | 63 |
64 | Reveal 65 | 66 | > *[3]int [10 20 30] 67 | 68 | * The assignment `py` is creating a pointer variable, as it takes the address of `y` using the `&` operator. 69 | * The type of `py` is therefore `*[3]int` because it *points to* a `[3]int`, so that's what gets printed by the `%T` formatter. 70 | * Lastly, we get the array content printed with the `%v` formatter, because `py` has been dereferenced with the `*` operator, turning it back into a real `[3]int` 71 | 72 |
73 |
74 | 75 | 1.
76 | What would be the output of the following program: 77 | 78 | Note: add package and import statements as needed 79 | 80 | ```go 81 | func main() { 82 | y := [3]int{10, 20, 30} 83 | fmt.Printf("%v \n", y) 84 | (*&y)[0] = 100 85 | fmt.Printf("%v \n", y) 86 | } 87 | ``` 88 | 89 | * [10 20 30]
[100] 90 | * [10 20 30]
[100 20 30] 91 | * Error 92 | * [10 20 30]
[10 20 30] 93 | 94 |
95 | Reveal 96 | 97 | > [10 20 30]
[100 20 30] 98 | 99 | * The first `Printf` prints the array `y` and a newline. 100 | * `(*&y)` first creates a pointer to `y` with `&`, then immediately dereferences it with `*`, effectively giving us `y` again, so the whole statement `(*&y)[0] = 100` has exactly the same effect as `y[0] = 100`. 101 | * Print the array again, and the first element as expected is `100` 102 | 103 |
104 |
105 | 106 | 1.
107 | What would be the output of the following program: 108 | 109 | Note: add package and import statements as needed 110 | 111 | ```go 112 | func main() { 113 | var y int 114 | var ptr *int = &y 115 | 116 | *ptr = 0 117 | fmt.Println(y) 118 | 119 | *ptr += 5 120 | fmt.Println(y) 121 | } 122 | ``` 123 | 124 | * 5
0 125 | * 0
5 126 | * 0
0 127 | * error 128 | 129 |
130 | Reveal 131 | 132 | > 0
5 133 | 134 | * Create a pointer to `y` as variable `ptr` 135 | * Set the actual value of `y` to zero via a pointer deference, then print `y` 136 | * Set the actual value of `y` to 5 via a pointer deference, then print `y` 137 | 138 |
139 |
140 | 141 | 1.
142 | What would be the output of the following program: 143 | 144 | Note: add package and import statements as needed 145 | 146 | ```go 147 | func main() { 148 | var y int 149 | var ptr *int = &y 150 | fmt.Println(y) 151 | fmt.Println(*ptr) 152 | } 153 | ``` 154 | 155 | 1. 0
<nil> 156 | 1. 0
0 157 | 1. <nil>
<nil> 158 | 1. <nil>
0 159 | 160 |
161 | Reveal 162 | 163 | > B 164 | 165 | * Declare variable y as `int`. Because it has no assignment, it will have the default value zero. 166 | * Create a pointer to `y` as variable `ptr`. This pointer cannot be `` because it has the address of an existing variable which is never `` 167 | * Print `y`, which we know is zero. 168 | * Print the dereferenced value of the pointer, which is the value of `y`, i.e. zero. 169 | 170 |
171 |
172 | 173 | 1.
174 | What would be the output of the following program: 175 | 176 | Note: add package and import statements as needed 177 | 178 | ```go 179 | func main() { 180 | s := 100 181 | var ptr *string = &s 182 | fmt.Println(s) 183 | *ptr += 100 184 | fmt.Println(s) 185 | } 186 | ``` 187 | 188 | * 100 189 | * 200 190 | * 100
200 191 | * error 192 | 193 |
194 | Reveal 195 | 196 | > error 197 | 198 | * The variable `s` is initialized as an `int` by assigning `100` to it. 199 | * The next line is declaring a pointer to `string`, which cannot assume the address of an integer variable. Note that in languages like C, this kind of assignment *would* be allowed and would make for hard to find bugs unless you knew exactly what you were doing! 200 | 201 |
202 |
203 | 204 | 1.
205 | What would be the output of the following program: 206 | 207 | Note: add package and import statements as needed 208 | 209 | ```go 210 | func main() { 211 | s := "hello" 212 | var ptr *string = &s 213 | fmt.Println(s) 214 | *ptr += strings.ToUpper(s) 215 | fmt.Println(s) 216 | } 217 | ``` 218 | 219 | * hello
hello HELLO 220 | * hello
helloHELLO 221 | * HELLO
hello 222 | * hello
hello 223 | 224 |
225 | Reveal 226 | 227 | > hello
helloHELLO 228 | 229 | 1. Declare `s` as a string with value `hello` 230 | 1. Create a pointer to `s` as `ptr`. 231 | 1. Print the value of `s` with a newline. 232 | 1. Via the pointer, append uppercase version of `s` to `s`
`*ptr += strings.ToUpper(s)` is equivalent to `s += strings.ToUpper(s)` 233 | 1. Print the new value of `s` 234 | 235 |
236 |
237 | 238 | -------------------------------------------------------------------------------- /docs/06-pointers/02-pointers-in-functions.md: -------------------------------------------------------------------------------- 1 | # Lab: Pointers 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-pointers-in-functions/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | What would be the output of the following program: 9 | 10 | Note: add package and import statements as needed 11 | 12 | ```go 13 | func modify(numbers ...int) { 14 | for i := range numbers { 15 | numbers[i] -= 5 16 | } 17 | } 18 | func main() { 19 | arr := []int{10, 20, 30} 20 | fmt.Println(arr) 21 | modify(arr...) 22 | fmt.Println(arr) 23 | } 24 | ``` 25 | 26 | * [10 20 30]
[5 15 25] 27 | * [10 20 30]
[10 20 30] 28 | * [10 20 30]
[15 25 35] 29 | * Error 30 | 31 |
32 | Reveal 33 | 34 | > [10 20 30]
[5 15 25] 35 | 36 | * Create a slice of `int` with 3 values 37 | * Print it 38 | * Call the function `modify` which takes a variadic argument. The slice is passed by reference, meaning that if it modifies the values in the slice, then the caller sees the change. Slice data is always passed by reference as they behave like pointers. 39 | * Hence in the final `Println` we see that 5 has bee subtracted from all values. 40 | 41 |
42 |
43 | 44 | 1.
45 | What would be the output of the following program: 46 | 47 | Note: add package and import statements as needed 48 | 49 | ```go 50 | func modify(numbers [3]int) { 51 | for i := range numbers { 52 | numbers[i] -= 5 53 | } 54 | } 55 | func main() { 56 | arr := [3]int{10, 20, 30} 57 | fmt.Println(arr) 58 | modify(arr) 59 | fmt.Println(arr) 60 | } 61 | ``` 62 | 63 | * [10 20 30]
[5 15 25] 64 | * [10 20 30]
[10 20 30] 65 | * [10 20 30]
[15 25 35] 66 | * Error 67 | 68 |
69 | Reveal 70 | 71 | > [10 20 30]
[10 20 30] 72 | 73 | * This time an array has been declared, not a slice 74 | * Arrays are passed by value, therefore the `modify` function receives *a copy* of the array. The caller's array is not modified. 75 | 76 |
77 |
78 | 79 | 1.
80 | What would be the output of the following program: 81 | 82 | Note: add package and import statements as needed 83 | 84 | ```go 85 | func modify(numbers *[3]int) { 86 | for i := range numbers { 87 | numbers[i] -= 5 88 | } 89 | } 90 | func main() { 91 | arr := [3]int{10, 20, 30} 92 | fmt.Println(arr) 93 | modify(arr) 94 | fmt.Println(arr) 95 | } 96 | ``` 97 | 98 | * [10 20 30]
[5 15 25] 99 | * [10 20 30]
[10 20 30] 100 | * [10 20 30]
[15 25 35] 101 | * Error 102 | 103 |
104 | Reveal 105 | 106 | > Error 107 | 108 | * The program will not compile since the `modify` function expects a pointer to an array of `[3]int`. 109 | * The call `modify(arr)` is passing the array itself, not a pointer to it. 110 | 111 |
112 |
113 | 114 | 1.
115 | What would be the output of the following program: 116 | 117 | Note: add package and import statements as needed 118 | 119 | ```go 120 | func modify(s *string) { 121 | *s = strings.ToUpper(*s) 122 | } 123 | 124 | func main() { 125 | s := "hello" 126 | fmt.Println(s) 127 | modify(&s) 128 | fmt.Println(s) 129 | } 130 | ``` 131 | 132 | * hello HELLO 133 | * hello
HELLO 134 | * HELLO hello 135 | * hello 136 | 137 |
138 | Reveal 139 | 140 | > hello
HELLO 141 | 142 | You must add `strings` as an import to use `ToUpper` 143 | 144 | * Initialize a string variable `s` with value `hello`, then print it. 145 | * The `modify` function takes a pointer to string, converts the value it is pointing to to upper case, then stores the conversion back in the variable being pointed to, i.e. it will modify the caller's variable. 146 | * `main` calls `modify` passing the address of the variable `s` - i.e. providing a pointer to `s` 147 | * Print the end result, which is now upper cased. 148 | * There is a newline in the output because `Println` was called twice and `Println` always appends a newline. 149 | 150 |
151 |
152 | 153 | 1.
154 | What would be the output of the following program: 155 | 156 | Note: add package and import statements as needed 157 | 158 | ```go 159 | func modify(s map[string]int) { 160 | s["A"] = 100 161 | } 162 | func main() { 163 | ascii_codes := map[string]int{} 164 | ascii_codes["A"] = 65 165 | fmt.Println(ascii_codes) 166 | modify(ascii_codes) 167 | fmt.Println(ascii_codes) 168 | } 169 | ``` 170 | 171 | * map[A:65]
map[A:65] 172 | * map[A:65]
map[A:100] 173 | * [A:65]
[A:100] 174 | * [A:65]
[A:65] 175 | 176 |
177 | Reveal 178 | 179 | > map[A:65]
map[A:100] 180 | 181 | * When a map is printed, it is always printed like `map[...]` so two answers can be ruled out immediately. 182 | * Maps are always passed by reference in function calls, therefore `modify` will modify the `ascii_codes` map and the modification is seen in the second print. 183 | 184 |
185 |
186 | 187 | *
188 | Wrap up 189 | 190 | * Slices and maps are always passed by reference so they behave like pointers to the caller's data when used as function arguments. If a function modifies a slice or a map argument, the change will affect the caller. 191 | * All other types, including arrays are passed by value (a copy is made for the function to use). If you want a function to be able to modify the caller's variable, then you must use a function that takes a pointer argument like Q4, and pass the address of your variable (`&` operator) to the function. 192 | * When using or modifying the value being pointed to in the function, you use the dereference operator (`*`). 193 | 194 |
195 | -------------------------------------------------------------------------------- /docs/07-struct-methods-and-interfaces/01-struct.md: -------------------------------------------------------------------------------- 1 | # Lab: Struct 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-struct/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | What would be the output of the following program? 9 | 10 | Note: add package and import statements as needed 11 | 12 | ```go 13 | type Movie struct { 14 | name string 15 | rating float32 16 | } 17 | 18 | func main() { 19 | m := Movie{name: "ABCD"} 20 | var m2 Movie 21 | fmt.Printf("%+v", m) 22 | fmt.Printf("%+v", m2) 23 | } 24 | ``` 25 | 26 | * {name: rating:0}{name: rating:0} 27 | * {name:ABCD rating:0}{name: rating:0} 28 | * error 29 | * {name:ABCD rating:0} 30 | 31 |
32 | Reveal 33 | 34 | > {name:ABCD rating:0}{name: rating:0} 35 | 36 | * We have a struct `Movie` with two fields, one `string` and one `float32`. 37 | * Initialize variable `m` with a `Movie` value setting only the `name` field. 38 | * Initialize variable `m2` with a `Movie`, not settings any of the fields. 39 | * Know that all fields of a struct will be initialized with the default values for the fields types if they are not explicitly set, so `string` fields get empty string and `float32` (like all numerics) get zero. 40 | * Now print `m`. The `%+v` formatter means include the field names and field values. So this will emit `{name:ABCD rating:0}` because we set the name in `m`. No newline will be printed since we did not put a `\n` in the string to be printed. Remember only `Println` automatically outputs a newline. 41 | * Now print `m2` which did not have any fields set, so that emits `{name: rating:0}` 42 | 43 |
44 |
45 | 46 | 1.
47 | What would be the output of the following program? 48 | 49 | Note: add package and import statements as needed 50 | 51 | ```go 52 | type Movie struct { 53 | name string 54 | rating float32 55 | } 56 | 57 | func getMovie(s string, r float32) (m Movie) { 58 | m = Movie{ 59 | name: s, 60 | rating: r, 61 | } 62 | return 63 | } 64 | 65 | func main() { 66 | fmt.Printf("%+v", getMovie("xyz", 3.5)) 67 | } 68 | ``` 69 | 70 | * {name: rating:0} 71 | * {name:xyz rating:3.5} 72 | * {xyz 3.5} 73 | * error 74 | 75 |
76 | Reveal 77 | 78 | > {name:xyz rating:3.5} 79 | 80 | * We have the same struct as the previous question. 81 | * We have a new function `getMovie` that initializes a `Movie` struct and returns it using named return value `m` 82 | * Call the function with `xyz` and `3.5` as arguments. These will be put into the struct. 83 | * Print the return value (i.e. the initialized struct) with `%+v` formatter. 84 | 85 |
86 |
87 | 88 | 1.
89 | What would be the output of the following program? 90 | 91 | Note: add package and import statements as needed 92 | 93 | ```go 94 | func getMovie(s string, r float32) (m Movie) { 95 | m = Movie{ 96 | name: s, 97 | rating: r, 98 | } 99 | return 100 | } 101 | 102 | func increaseRating(m *Movie) { 103 | m.rating += 1.0 104 | } 105 | 106 | func main() { 107 | mov := getMovie("xyz", 2.0) 108 | increaseRating(mov) 109 | fmt.Printf("%+v", mov) 110 | } 111 | ``` 112 | 113 | * xyz
3 114 | * error 115 | * {xyz 3} 116 | * {name:xyz rating:3} 117 | 118 |
119 | Reveal 120 | 121 | > Error 122 | 123 | The program will fail to compile because there is a bug! 124 | 125 | The function `increaseRating` requires a pointer to `Movie` struct so that it can modify the values within. In the call to `increaseRating`, the address of `mov` should have been passed, i.e. needs to be `increaseRating(&mov)` 126 | 127 |
128 |
129 | 130 | 1.
131 | What would be the output of the following program? 132 | 133 | Note: add package and import statements as needed 134 | 135 | ```go 136 | type Movie struct { 137 | name string 138 | rating float32 139 | } 140 | 141 | func getMovie(s string, r float32) (m Movie) { 142 | m = Movie{ 143 | name: s, 144 | rating: r, 145 | } 146 | return 147 | } 148 | 149 | func main() { 150 | mov := getMovie("xyz", 2.0) 151 | fmt.Println(mov.name) 152 | fmt.Println(mov.ratings) 153 | } 154 | ``` 155 | 156 | * xyz 2 157 | * xyz
2 158 | * name: xyz
rating: 2 159 | * error 160 | 161 |
162 | Reveal 163 | 164 | > Error 165 | 166 | The program will fail to compile because there is another bug! 167 | 168 | In the last line of the program it is trying to print `mov.ratings`. `Movie` struct has no field `ratings`. The correct name is `rating`. 169 | 170 |
171 |
172 | 173 | 1.
174 | What would be the output of the following program? 175 | 176 | Note: add package and import statements as needed 177 | 178 | ```go 179 | type Movie struct { 180 | name string 181 | rating float32 182 | } 183 | 184 | func getMovie(s string, r float32) (m Movie) { 185 | m = Movie{ 186 | name: s, 187 | rating: r, 188 | } 189 | return 190 | } 191 | 192 | func main() { 193 | mov := getMovie("xyz", 2.1) 194 | mov1 := getMovie("abc", 3.3) 195 | movies := make([]Movie, 5) 196 | movies = append(movies, mov) 197 | movies = append(movies, mov1) 198 | for _, value := range movies { 199 | fmt.Println(value) 200 | } 201 | } 202 | ``` 203 | 204 | * { 0}
{ 0}
{ 0}
{ 0}
{ 0}
{xyz 2.1}
{abc 3.3} 205 | * { 0}
{ 0}
{ 0}
{ 0}
{ 0}
{xyz 2}
{abc 3} 206 | * {name:xyz rating:2.1}
{name:abc rating:3.3}
{name: rating:0}
{name: rating:0}
{name: rating:0}
{name: rating:0}
{name: rating:0} 207 | * {name: rating:0}
{name: rating:0}
{name: rating:0}
{name: rating:0}
{name: rating:0}
{name:xyz rating:2.1}
{name:abc rating:3.3} 208 | 209 |
210 | Reveal 211 | 212 | > { 0}
{ 0}
{ 0}
{ 0}
{ 0}
{xyz 2.1}
{abc 3.3} 213 | 214 | * Two movie structs are initialized using the `getMovie` function. Both are given ratings with a floating point number. This rules out the second answer above as a possibility since its ratings are integers. 215 | * Next, a slice of 5 `Movie` structs is created. All five will be initialized as per the rules mentioned in the explanation for Q1. 216 | * Now we *append* `mov` and `mov1` to the slice, so these will appear *following* the five empty movies. 217 | * When the slice is iterated with `range` the five empty ones will come first, then `mov` then `mov1`. This rules out any answer where `mov` and `mov1` are printed first. 218 | * The default formatter for `Println` is `%v` therefore field names will not be printed, only values, so that rules out any answer where the words "name" and "rating" are printed, leaving only the one possible answer. 219 | 220 |
221 |
222 | 223 | 1.
224 | What would be the output of the following program? 225 | 226 | Note: add package and import statements as needed 227 | 228 | ```go 229 | type Movie struct { 230 | name string 231 | rating float32 232 | } 233 | 234 | func main() { 235 | mov := Movie{"xyz", 2.1} 236 | mov1 := Movie{"abc", 2.1} 237 | if mov.rating == mov1.rating || mov != mov1 { 238 | fmt.Println("condition met") 239 | } else if mov.rating == mov1.rating { 240 | fmt.Println("condition_2 met") 241 | } 242 | } 243 | ``` 244 | 245 | * error 246 | * no output 247 | * condition met
condition_2 met 248 | * condition met 249 | 250 |
251 | Reveal 252 | 253 | > condition met 254 | 255 | * Initialize two movies. They have different names but the same rating. 256 | * `mov.rating == mov1.rating` is true. What comes after `||` doesn't matter and won't be evaluated because the left hand side of `||` was true. However the second condition is in fact true. The two movies are not equal because they have different names. Even if it was false, it would have no effect and `condition met` would still be printed. 257 | * The `else if` clause is also true, but it will not be executed because the first `if` was true. 258 | 259 |
260 |
261 | 262 | -------------------------------------------------------------------------------- /docs/07-struct-methods-and-interfaces/02-struct-and-methods.md: -------------------------------------------------------------------------------- 1 | # Lab: Struct and Methods 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-struct-and-methods/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | Methods are special functions that operate on structs or pointers to structs. They are also known as `receivers`. This, along with interfaces is as close as Go gets to Object Oriented Programming (OOP). 8 | 9 | 1.
10 | What would be the output of the following program? 11 | 12 | Note: add package and import statements as needed 13 | 14 | ```go 15 | type Movie struct { 16 | name string 17 | summary string 18 | rating float32 19 | } 20 | 21 | func (m Movie) getSummary() { 22 | m.summary = "summary" 23 | } 24 | 25 | func (m *Movie) increaseRating() { 26 | m.rating += 1 27 | } 28 | 29 | func main() { 30 | mov := Movie{"xyz", "", 2.1} 31 | fmt.Printf("%+v", mov) 32 | mov.increaseRating() 33 | mov.getSummary() 34 | fmt.Printf("%+v", mov) 35 | } 36 | ``` 37 | 38 | * {name:xyz summary: rating:2.1}{name:xyz summary: rating:3.1} 39 | * {name:xyz summary:summary rating:2.1}
{name:xyz summary:summary rating:3.1} 40 | * {name:xyz summary:summary rating:2.1}{name:xyz summary:summary rating:3.1} 41 | * {name:xyz summary: rating:2.1}
{name:xyz summary: rating:3.1} 42 | 43 |
44 | Reveal 45 | 46 | > {name:xyz summary: rating:2.1}{name:xyz summary: rating:3.1} 47 | 48 | Our old friend the `Movie` struct reappears, this time with an additional field `summary` and a couple of methods. 49 | 50 | * We can immediately rule out any answer that has a newline between the two outputs, as `Printf` does not emit newline unless the format string contains `\n`. 51 | * So why was the summary not set in the call to `getSummary`? Notice that this method is not a pointer receiver, therefore setting values in the struct will have no effect on the caller. 52 | * However `increaseRating` *is* a pointer receiver, therefore the caller's variable `mov` is modified. 53 | 54 |
55 |
56 | 57 | 1.
58 | What would be the output of the following program? 59 | 60 | Note: add package and import statements as needed 61 | 62 | ```go 63 | type Rectangle struct { 64 | length int 65 | breadth int 66 | } 67 | 68 | func (r Rectangle) area() int { 69 | return r.length * r.breadth 70 | } 71 | 72 | func main() { 73 | r := Rectangle{breadth: 10, length: 5} 74 | fmt.Println(r.area()) 75 | fmt.Println(r) 76 | } 77 | ``` 78 | 79 | * 50
{10 5} 80 | * 0
{5 10} 81 | * 50
{5 10} 82 | * 0
{10 5} 83 | 84 |
85 | Reveal 86 | 87 | > 50
{5 10} 88 | 89 | * From the final `Println` where we print `r`, the rectangle struct, we can immediately rule out any answer that prints `{10, 5}` as the fields in the struct are printed in the order they appear in the `type` declaration for the struct. 90 | * Where we initialize the struct in the first line of `main()`, the field initializers when naming the fields can be listed in any order. 91 | * We have a non-pointer receiver `area` which simply returns the area of the rectangle. We are not setting fields in the rectangle struct so we don't require a pointer receiver. 92 | * The first `Println` prints the value returned from the `area` call, which is `50`, yielding the correct answer. 93 | 94 |
95 |
96 | 97 | 1.
98 | What would be the output of the following program? 99 | 100 | Note: add package and import statements as needed 101 | 102 | ```go 103 | type Rectangle struct { 104 | length int 105 | breadth int 106 | } 107 | 108 | func (r Rectangle) area() int { 109 | return r.length * r.breadth 110 | } 111 | 112 | func (r *Rectangle) incLength(n int) { 113 | for i := 0; i < n; i++ { 114 | r.length += i 115 | } 116 | } 117 | 118 | func main() { 119 | r := Rectangle{breadth: 10, length: 5} 120 | fmt.Println(r.area()) 121 | fmt.Println(r) 122 | r.incLength(7) 123 | fmt.Println(r.area()) 124 | fmt.Println(r) 125 | } 126 | ``` 127 | 128 | * error 129 | * 50 {5 10}
260 {26 10} 130 | * 50
{5 10}
50
{26 10} 131 | * 50
{5 10}
260
{26 10} 132 | 133 |
134 | Reveal 135 | 136 | > 50
{5 10}
260
{26 10} 137 | 138 | * The program compiles and has no pointer bugs, so no error. 139 | * There are four separate `PrintLn` so anything that is not four lines of output can be eliminated. 140 | * We have the same struct, it's initialized the same way as the previous question, and the same `area` receiver. 141 | * There is an additional *pointer* receiver `incLength` which can modify fields in the struct. 142 | * The first `Println` for `area` and the following `Println` for the structure will give the same output as the previous question. 143 | * Next, we call `incLength` with `7`. That will add incrementing values of `i` in the `for` loop to the length, i.e. 0 then 1, then 2 all the way up to 6, therefore length ends up as `26`. 144 | * Print the area and the struct again, which now has the modified length of `26` 145 | 146 |
147 |
148 | 149 | 1.
150 | What would be the output of the following program? 151 | 152 | Note: add package and import statements as needed 153 | 154 | ```go 155 | type Employee struct { 156 | eid int 157 | id int 158 | } 159 | 160 | func main() { 161 | employees := make([]Employee, 5) 162 | for i := range employees { 163 | employees[i] = Employee{i, i + 10} 164 | fmt.Println(employees[i]) 165 | } 166 | } 167 | ``` 168 | 169 | * error 170 | * {eid:0 id:10}
{eid:1 id:11}
{eid:2 id:12}
{eid:3 id:13}
{eid:4 id:14} 171 | * {0 10}
{1 11}
{2 12}
{3 13}
{4 14} 172 | * {0 }
{1 }
{2 }
{3 }
{4 } 173 | 174 |
175 | Reveal 176 | 177 | > {0 10}
{1 11}
{2 12}
{3 13}
{4 14} 178 | 179 | * There's no error 180 | * We can rule out any answer that prints the field names, because `Println` won't do that 181 | * We can also rule out any answer that does not include two values in each `{}` since both fields are `int` and `int` always has a printable value, even if it's zero. 182 | * This leaves only one answer. The reason it has the values it does, is because we initialize each value in the struct without giving the field names, so the values are applied in order: `eid` first, then `id`. The `eid` values will go from zero to 4, and the `id` being `i+10` will go from 10 to 14. 183 | 184 | It is however good practice to use field names when initializing a struct since it makes the code easier to read. 185 | 186 |
187 |
188 | 189 | 1.
190 | What would be the output of the following program? 191 | 192 | Note: add package and import statements as needed 193 | 194 | ```go 195 | type Employee struct { 196 | eid int 197 | id int 198 | } 199 | 200 | func (e Employee) get_id() int { 201 | return e.eid + 10 202 | } 203 | 204 | func main() { 205 | employees := make([]Employee, 5) 206 | for i := range employees { 207 | employees[i] = Employee{eid: i} 208 | employees[i].id = employees[i].get_id() 209 | fmt.Printf("%+v\n", employees[i]) 210 | } 211 | } 212 | ``` 213 | 214 | * {0 0}
{1 0}
{2 0}
{3 0}
{4 0} 215 | * {eid:0 id:0}
{eid:1 id:0}
{eid:2 id:0}
{eid:3 id:0}
{eid:4 id:0} 216 | * {0 10}
{1 11}
{2 12}
{3 13}
{4 14} 217 | * {eid:0 id:10}
{eid:1 id:11}
{eid:2 id:12}
{eid:3 id:13}
{eid:4 id:14} 218 | 219 |
220 | Reveal 221 | 222 | > {eid:0 id:10}
{eid:1 id:11}
{eid:2 id:12}
{eid:3 id:13}
{eid:4 id:14} 223 | 224 | * We can rule out any answer that does not print the field names, because we are using `%+v` formatter. 225 | * There is a receiver `get_id` that returns the current value of `eid` plus 10 226 | * In the for loop, each struct is initialized with a value for `eid` only 227 | * Then the `id` is set with the value returned by `get_id`, i.e the `eid` plus ten, which means that `id` is not going to be zero when the struct is printed. 228 | * Then print the struct. 229 | 230 |
231 |
232 | 233 | -------------------------------------------------------------------------------- /docs/07-struct-methods-and-interfaces/03-interfaces.md: -------------------------------------------------------------------------------- 1 | # Lab: Interfaces 2 | 3 | [Take me to the lab!](https://kodekloud.com/topic/lab-interfaces/) 4 | 5 | Help for the [VSCode editor](https://github.com/kodekloudhub/community-faq/blob/main/docs/vscode-tips.md). 6 | 7 | 1.
8 | Select the correct declarations for an interface. 9 | 10 | 1. ```go 11 | type Student interface { 12 | id int 13 | grades []int 14 | func calcGrades() 15 | } 16 | ``` 17 | 1. ```go 18 | type Student interface { 19 | calcGrades() 20 | getName() 21 | } 22 | ``` 23 | 1. ```go 24 | type Employee interface { 25 | calcSalary() 26 | getName() 27 | } 28 | ``` 29 | 1. ```go 30 | type Employee interface { 31 | func calcSalary() 32 | func getName() 33 | } 34 | ``` 35 | 36 |
37 | Reveal 38 | 39 | > B, C 40 | 41 | * A is incorrect because interfaces cannot have fields, only methods. 42 | * D is incorrect because the `func` keyword is not used on interface method declarations. 43 | 44 |
45 |
46 | 47 | 1.
48 | What would be the output of the following program? 49 | 50 | Note: add package and import statements as needed 51 | 52 | ```go 53 | type Student interface { 54 | getPercentage() int 55 | getName() 56 | } 57 | 58 | type Undergrad struct { 59 | name string 60 | grades []int 61 | } 62 | 63 | func (u Undergrad) getPercentage() int { 64 | sum := 0 65 | for _, v := range u.grades { 66 | sum += v 67 | } 68 | return sum / len(u.grades) 69 | } 70 | 71 | func printPercentage(s Student) { 72 | fmt.Println(s.getPercentage()) 73 | } 74 | 75 | func main() { 76 | grades := []int{90, 75, 80} 77 | u := Undergrad{"Ross", grades} 78 | printPercentage(u) 79 | } 80 | ``` 81 | 82 | * No output 83 | * Error 84 | * 81 85 | * 81% 86 | 87 |
88 | Reveal 89 | 90 | > Error 91 | 92 | * There is a bug in this program. It will fail to compile due to the last line which will produce the error `Undergrad does not implement Student (missing getName method)` 93 | * When a struct value is passed as an argument to a function that has an interface parameter, the struct's implementation will be checked by the compiler. 94 | * `Undergrad` has a receiver for `getPercentage` but not for `getName` therefore it is an incomplete implementation of the interface `Student`. 95 | 96 |
97 |
98 | 99 | 1.
100 | What would be the output of the following program? 101 | 102 | Note: add package and import statements as needed 103 | 104 | ```go 105 | type Student interface { 106 | getPercentage() int 107 | getName() string 108 | } 109 | 110 | type Undergrad struct { 111 | name string 112 | grades []int 113 | } 114 | 115 | func (u Undergrad) getPercentage() int { 116 | sum := 0 117 | for _, v := range u.grades { 118 | sum += v 119 | } 120 | return sum / len(u.grades) 121 | } 122 | func (u Undergrad) getName() string { 123 | return u.name 124 | } 125 | 126 | func printData(s Student) { 127 | fmt.Println(s.getName()) 128 | fmt.Println(s.getPercentage()) 129 | } 130 | 131 | func main() { 132 | grades := []int{90, 75, 80} 133 | u := Undergrad{"Ross", grades} 134 | printData(u) 135 | } 136 | ``` 137 | 138 | * No output 139 | * Ross
81 140 | * Error 141 | * 81
Ross 142 | 143 |
144 | Reveal 145 | 146 | > Ross
81 147 | 148 | * The bug from Q2 has been fixed. An implementation has been provided for `getName`, so no error. 149 | * `No output` is incorrect because the two `Println` statements in the `printData` function will be executed. 150 | * While we're there, note that the name will be printed first, so that eliminates another answer. 151 | * Finally, `getPercentage` calculates the average of all the grades in the `grades` slice. The calculation is using integer math, hence `81`. No percent sign is printed. 152 | 153 |
154 |
155 | 156 | 1.
157 | What would be the output of the following program? 158 | 159 | Note: add package and import statements as needed 160 | 161 | ```go 162 | type Student interface { 163 | getPercentage() int 164 | getName() string 165 | } 166 | 167 | type Undergrad struct { 168 | name string 169 | grades []int 170 | } 171 | 172 | type Postgrad struct { 173 | name string 174 | grades []int 175 | } 176 | 177 | func (p Postgrad) getPercentage() int { 178 | sum := 0 179 | for _, v := range p.grades { 180 | sum += v 181 | } 182 | return ((sum * 100) / (len(p.grades) * 200)) 183 | } 184 | func (p Postgrad) getName() string { 185 | return p.name 186 | } 187 | 188 | func (u Undergrad) getPercentage() int { 189 | sum := 0 190 | for _, v := range u.grades { 191 | sum += v 192 | } 193 | return sum / len(u.grades) 194 | } 195 | 196 | func (u Undergrad) getName() string { 197 | return u.name 198 | } 199 | 200 | func printData(s Student) { 201 | fmt.Println(s.getName()) 202 | fmt.Println(s.getPercentage()) 203 | } 204 | 205 | func main() { 206 | u := Undergrad{"Ross", []int{90, 75, 80}} 207 | p := Postgrad{"Joe", []int{150, 190, 185}} 208 | printData(u) 209 | printData(p) 210 | } 211 | ``` 212 | 213 | * Ross 81
Joe 87 214 | * Joe 87
Ross 81 215 | * Ross
81
Joe
87 216 | * Ross
Joe
81
87 217 | 218 |
219 | Reveal 220 | 221 | > Ross
81
Joe
87 222 | 223 | * Now there is a new struct `Postgrad`. `Postgrad` correctly implements the `Student` interface as it has correct receivers for `getName` and `getPercentage`. 224 | * Note that the `getPercentage` for `Postgrad` is a different implementation, i.e. the percentage is calculated differently. 225 | * The function `printData` is the same as in Q3, therefore from that we know the order in which it will print the student data (name, newline, percentage). This eliminates two answers. It also eliminates a third because it won't output two names followed by two percentages. 226 | 227 | 228 |
229 |
230 | 231 | 1.
232 | Which of the following keyword is used to implement an interface in Golang? 233 | 234 | * type struct 235 | * receiver 236 | * No keyword needed to implement an interface 237 | * type interface 238 | 239 |
240 | Reveal 241 | 242 | > No keyword needed to implement an interface 243 | 244 | * Keywords are used to *declare* an interface, not *implement* it. 245 | * Implementation is achieved by providing all of the correct receiver methods as defined by the interface for any struct that wants to provide an implementation. 246 | 247 |
248 |
249 | 250 | -------------------------------------------------------------------------------- /docs/08-additional-content/01-how-do-slices-really-work.md: -------------------------------------------------------------------------------- 1 | # Bonus: How do slices *really* work? 2 | 3 | Now that you have reached the end of the course and learned about arrays, slices, structs and pointers, we can take a deep dive into the mechanics of what makes a slice work under the hood. Hopefully this covers all the questions raised on the KodeKloud forums about slices. 4 | 5 | In some of the code examples below, it is stated "pseudo-code". For those that haven't come across this term, pseudo-code shows a description of the logic that would happen in the *real* code, some of which in these cases would have been written in assembly language rather than pure Go in the Go runtime, for speed."pseudo-function" indicates a made up function call representative of what is actually happening under the hood. Don't try running any of the pseudo-code, it won't work! It serves only as an illustration. Any example complete with `package` and `import` will run. 6 | 7 | * [Refresher](#refresher) 8 | * [Slice Representation](#slice-representation) 9 | * [Slicing arrays and other slices](#slicing-arrays-and-other-slices) 10 | * [Growing Slices](#growing-slices) 11 | 12 | ## Refresher 13 | 14 | You've learned that an array is passed by value. This means that if you pass an array as a function argument, changing the array from inside the function has no effect on the caller's array, since the function gets a complete copy of the *entire* array... 15 | 16 | ```go 17 | package main 18 | 19 | import "fmt" 20 | 21 | func modify([3]int arr) { 22 | arr[0] = 100 23 | } 24 | 25 | func main() { 26 | arr:= [3]int{1, 2, 3} 27 | modify(arr) 28 | fmt.Println(arr) 29 | } 30 | ``` 31 | 32 | This yields 33 | 34 | ``` 35 | [1 2 3] 36 | ``` 37 | 38 | You've also learned that a slice is passed "by reference" (in quotes for reasons that will become clear shortly!). This means that if you pass the slice as a function parameter then changing the slice from inside the function *does* affect the caller's slice (most of the time :smile: - we will see when this is *not* the case later)... 39 | 40 | ```go 41 | package main 42 | 43 | import "fmt" 44 | 45 | func modify([]int arr) { 46 | arr[0] = 100 47 | } 48 | 49 | func main() { 50 | arr:= []int{1, 2, 3} 51 | modify(arr) 52 | fmt.Println(arr) 53 | } 54 | ``` 55 | 56 | This yields 57 | 58 | ``` 59 | [100 2 3] 60 | ``` 61 | 62 | # Slice Representation 63 | 64 | Well... slices are not in reality passed by reference. In fact, they too are passed by value! 65 | 66 | The internal representation of a slice is this struct (also called a slice header), and it is an instance of this struct that is passed to a function call that has a slice argument: 67 | 68 | ```go 69 | type slice struct { 70 | array unsafe.Pointer // Pointer to the first element in the slice. 71 | len int // Length of the slice 72 | cap int // Capacity of the slice 73 | } 74 | ``` 75 | 76 | So, the reason a slice argument acts as though passed by reference is the pointer member of the above struct. Even though the slice header is passed by value (meaning *a copy* of the slice header is received by the `modify` function), the pointer `array` is still the same value, meaning it is pointing to the *same* block of memory that `main` is seeing. Thus when you modify a value in the slice, the caller will see the modification. 77 | 78 | A note about `unsafe` - The `unsafe` package contains methods and types that circumvent the type safety of Go, so should be used with caution! In the `slice` struct above, `unsafe.Pointer` is used because it can point to *anything* - `int`, `string`, `float32`, an instance of your custom struct - literally anything. 79 | 80 | Now let's talk a little more on the functions we can use with slices, with respect to what we have just learned about the representation of a slice using some pseudo-code. 81 | 82 | The function `len()` when used with slices is effectively this: 83 | 84 | ```go 85 | func len(sh slice) { 86 | return sh.len 87 | } 88 | ``` 89 | 90 | Similarly `cap()`: 91 | 92 | ```go 93 | func cap(sh slice) { 94 | return sh.cap 95 | } 96 | ``` 97 | 98 | And `make` is a bit like this. The compiler automatically adjusts the `make` call for the type being stored in the slice, so for `[]int` it would be similar to 99 | 100 | ```go 101 | func make([]int, lenAndCap ...int) slice { 102 | length = lenAndCap[0] 103 | if len(lenAndCap) > 1 { 104 | capacity = lenAndCap[1] 105 | } else { 106 | capacity = length 107 | } 108 | 109 | return slice { 110 | array: alloc(capacity * sizeof(int)), 111 | len: length, 112 | cap: capacity, 113 | } 114 | } 115 | ``` 116 | 117 | For a custom struct 118 | 119 | ```go 120 | 121 | type myStruct struct { 122 | a int 123 | b int 124 | } 125 | 126 | func make([]myStruct, lenAndCap ...int) slice { 127 | length = lenAndCap[0] 128 | if len(lenAndCap) > 1 { 129 | capacity = lenAndCap[1] 130 | } else { 131 | capacity = length 132 | } 133 | 134 | return slice { 135 | array: alloc(capacity * sizeof(myStruct)), 136 | len: length, 137 | cap: capacity, 138 | } 139 | } 140 | ``` 141 | 142 | In the above, note: 143 | 144 | * The pseudo-function `sizeof` determines how many bytes are required to store a single element of the type contained in the slice e.g. `int`, which on modern computers is 8 bytes. Multiply that by the requested capacity to get the total number of bytes required to hold the slice. 145 | * The pseudo-function `alloc` allocates the requested number of bytes of memory from the global heap and returns a pointer to that memory. 146 | 147 | You can see a slice header like this 148 | 149 | ```go 150 | package main 151 | 152 | import ( 153 | "fmt" 154 | "reflect" 155 | "unsafe" 156 | ) 157 | 158 | func main() { 159 | slc := []int{1, 2, 3} 160 | sh := (*reflect.slice)(unsafe.Pointer(&slc)) 161 | fmt.Printf("%+v", sh) 162 | } 163 | ``` 164 | 165 | Output will be something like this 166 | 167 | ``` 168 | &{array:1792106 len:3 cap:3} 169 | ``` 170 | 171 | ## Slicing arrays and other slices 172 | 173 | Recall that when we create a slice over an array or another slice, we are effectively creating a view of a portion of the underlying slice or array. 174 | 175 | ```go 176 | package main 177 | 178 | import "fmt" 179 | 180 | func main() { 181 | arr := [3]int{1, 2, 3} 182 | slc := arr[:] 183 | slc[0] = 100 184 | fmt.Println(arr) 185 | } 186 | ``` 187 | 188 | Output will be 189 | 190 | ``` 191 | [100 2 3] 192 | ``` 193 | 194 | ...because we modified the underlying array through the slice. If we look at the assignment `slc := arr[:]`, the compiler generates something like this pseudo-code, then compiles it. The numbers either side of `:` in `[:]` represent the start and end indices of the underlying array or slice to create the view from. Let's assume the compiler automatically generates `0` for start if there's nothing to the left of `:` and `len(arr)` if there's nothing to the right 195 | 196 | For an array: 197 | 198 | ```go 199 | // Compiler generated makeSlice function 200 | func makeSlice(arr *[3]int, start, end int) []int { 201 | // Remember "arr" is a pointer to the start of the array data 202 | return slice { 203 | array: arr + (start * sizeof(int)), // points to the first element in underlying array as specified by "start" 204 | len: end - start, 205 | cap: end - start, 206 | } 207 | } 208 | 209 | func main() { 210 | arr := [3]int{1, 2, 3} 211 | slc := makeSlice(&arr, 0, len(arr)) // compiler generated 212 | slc[0] = 100 213 | fmt.Println(arr) 214 | } 215 | ``` 216 | 217 | For another slice: 218 | 219 | ```go 220 | // Compiler generated makeSlice function 221 | func makeSlice(slc []int, start, end int) []int { 222 | // get slice header for slc 223 | sh := (*reflect.slice)(unsafe.Pointer(&slc)) 224 | return slice { 225 | array: sh.array + (start * sizeof(int)), // points to the first element in underlying slice as specified by "start" 226 | len: end - start, 227 | cap: end - start, 228 | } 229 | } 230 | 231 | func main() { 232 | originalSlice := []int{1, 2, 3} 233 | slc := makeSlice(originalSlice, 0, len(arr)) // compiler generated 234 | slc[0] = 100 235 | fmt.Println(originalSlice) 236 | } 237 | ``` 238 | 239 | ## Growing Slices 240 | 241 | A slice grows when its *capacity* is exceeded by appending more elements than capacity permits. The pseudo-code for `append` looks something like this 242 | 243 | ```go 244 | func append(slc []typ, appendedItems ...typ) []typ { 245 | // Intially return the slice passed as an argument 246 | returnSlice := slc 247 | 248 | if len(appendedItems) + len(slc) > cap(slc) { 249 | // A new slice is allocated (pseudo-function growSlice) 250 | returnSlice := growSlice(slc, len(appendedItems) + len(slc)) 251 | } 252 | 253 | // pseudo-function, appends the items to the slice and sets length 254 | copyNewItems(returnSlice, appendedItems) 255 | return returnSlice 256 | } 257 | ``` 258 | 259 | Now, if the slice did not grow, then what is returned by `append` is the same slice you passed into `append`. If the slice had to grow, then a *completely new* bigger slice is returned, with a new memory allocation and a copy of the data from the original slice, plus any appended data. The length of this slice is the original length plus the length of the data being append, and the capacity is calculated as discussed further on in this section. This has an effect on what a calling function sees. Let's return to the `modify` example, and this time, force the slice to grow. 260 | 261 | ```go 262 | package main 263 | 264 | import "fmt" 265 | 266 | func modify(slc []int) { 267 | slc2 := []int{4, 5, 6, 7, 8, 9} 268 | // Grow the slice 269 | slc = append(slc, slc2...) 270 | // Now modify first element 271 | slc[0] = 100 272 | } 273 | 274 | func main() { 275 | slc := []int{1, 2, 3} 276 | modify(slc) 277 | fmt.Println(slc) 278 | } 279 | ``` 280 | 281 | This time the output is: 282 | 283 | ``` 284 | [1 2 3] 285 | ``` 286 | 287 | That's because a grow happened in the `modify` function, which caused a *copy* to be made of the original data, so when `slc[0] = 100` happens, it's now modifying a copy, not the original data therefore it's as if we had passed an array and not a slice! This is also why you should always assign the result of `append` back to the slice you are appending to, in case the slice is reallocated. 288 | 289 | Next, let's discuss what happens when a slice grows. The general rule of thumb is that the capacity is doubled, but this is not always the case! The algorithm for growing a slice is fairly complex and takes several factors into consideration when deciding how much extra capacity should be added. One such consideration is that when the slices get to a certain size, the capacity increase factor drops from 2 to 1.25 or you would soon run out of memory! There are other considerations for the size of the element stored in the slice, and the machine architecture. The code for growing a slice can be [found here](https://go.dev/src/runtime/slice.go) beginning at line 157. 290 | 291 | --------------------------------------------------------------------------------