diff --git a/24-structs/05-project-log-parser-structs/main.go b/24-structs/05-project-log-parser-structs/main.go index b744ad4..df4bc1f 100644 --- a/24-structs/05-project-log-parser-structs/main.go +++ b/24-structs/05-project-log-parser-structs/main.go @@ -64,7 +64,7 @@ func main() { p.total += visits // You cannot assign to composite values - // p.sum[name].count += visits + // p.sum[domain].visits += visits // create and assign a new copy of `visit` p.sum[domain] = result{ diff --git a/24-structs/TODO.md b/24-structs/TODO.md deleted file mode 100644 index 5097420..0000000 --- a/24-structs/TODO.md +++ /dev/null @@ -1,19 +0,0 @@ -[x] what? -[x] why? -[x] struct type -[x] struct literal -[x] anonymous structs -[x] named structs -[x] struct fields -[x] compare and assign -[x] printing -[x] embedding -[ ] exporting struct and fields -[ ] struct tags {json encode/decode} - project? - -**LATER:** -[ ] funcs: constructor pattern -[ ] pointers: - [ ] structs and pointers - later - [ ] padding and memory layout - later -[ ] using anonymous structs when testing \ No newline at end of file diff --git a/24-structs/exercises/00-name/main.go b/24-structs/exercises/00-name/main.go deleted file mode 100644 index 50f6bc1..0000000 --- a/24-structs/exercises/00-name/main.go +++ /dev/null @@ -1,21 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -// --------------------------------------------------------- -// EXERCISE: ?? -// -// -// EXPECTED OUTPUT -// -// -// --------------------------------------------------------- - -func main() { - -} diff --git a/24-structs/exercises/00-name/solution/main.go b/24-structs/exercises/00-name/solution/main.go deleted file mode 100644 index bd7e329..0000000 --- a/24-structs/exercises/00-name/solution/main.go +++ /dev/null @@ -1,12 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -func main() { - -} diff --git a/24-structs/exercises/01-warmup/main.go b/24-structs/exercises/01-warmup/main.go new file mode 100644 index 0000000..326998c --- /dev/null +++ b/24-structs/exercises/01-warmup/main.go @@ -0,0 +1,39 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package main + +// --------------------------------------------------------- +// EXERCISE: Warm Up +// +// Starting with this exercise, you'll build a command-line +// game store. +// +// 1. Declare the following structs: +// +// + item: id (int), name (string), price (int) +// +// + game: embed the item, genre (string) +// +// +// 2. Create a game slice using the following data: +// +// id name price genre +// +// 1 god of war 50 action adventure +// 2 x-com 2 30 strategy +// 3 minecraft 20 sandbox +// +// +// 3. Print all the games. +// +// EXPECTED OUTPUT +// Please run the solution to see the output. +// --------------------------------------------------------- + +func main() { +} diff --git a/24-structs/exercises/01-warmup/solution/main.go b/24-structs/exercises/01-warmup/solution/main.go new file mode 100644 index 0000000..619c713 --- /dev/null +++ b/24-structs/exercises/01-warmup/solution/main.go @@ -0,0 +1,39 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package main + +import "fmt" + +func main() { + type item struct { + id int + name string + price int + } + + type game struct { + item + genre string + } + + games := []game{ + { + item: item{id: 1, name: "god of war", price: 50}, + genre: "action adventure", + }, + {item: item{id: 2, name: "x-com 2", price: 40}, genre: "strategy"}, + {item: item{id: 3, name: "minecraft", price: 20}, genre: "sandbox"}, + } + + fmt.Printf("Inanc's game store has %d games.\n\n", len(games)) + + for _, g := range games { + fmt.Printf("#%d: %-15q %-20s $%d\n", + g.id, g.name, "("+g.genre+")", g.price) + } +} diff --git a/24-structs/exercises/02-list/main.go b/24-structs/exercises/02-list/main.go new file mode 100644 index 0000000..ce1d7a4 --- /dev/null +++ b/24-structs/exercises/02-list/main.go @@ -0,0 +1,33 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package main + +// --------------------------------------------------------- +// EXERCISE: List +// +// Now, it's time to add an interface to your program using +// the bufio.Scanner. So the users can list the games, or +// search for the games by id. +// +// 1. Scan for the input in a loop (use bufio.Scanner) +// +// 2. Print the available commands. +// +// 3. Implement the quit command: Quits from the loop. +// +// 4. Implement the list command: Lists all the games. +// +// +// EXPECTED OUTPUT +// Please run the solution and try the program with list and +// quit commands. +// --------------------------------------------------------- + +func main() { + // use your solution from the previous exercise +} diff --git a/24-structs/exercises/02-list/solution/main.go b/24-structs/exercises/02-list/solution/main.go new file mode 100644 index 0000000..3e8bf65 --- /dev/null +++ b/24-structs/exercises/02-list/solution/main.go @@ -0,0 +1,65 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package main + +import ( + "bufio" + "fmt" + "os" +) + +func main() { + type item struct { + id int + name string + price int + } + + type game struct { + item + genre string + } + + games := []game{ + { + item: item{id: 1, name: "god of war", price: 50}, + genre: "action adventure", + }, + {item: item{id: 2, name: "x-com 2", price: 40}, genre: "strategy"}, + {item: item{id: 3, name: "minecraft", price: 20}, genre: "sandbox"}, + } + + fmt.Printf("Inanc's game store has %d games.\n", len(games)) + + in := bufio.NewScanner(os.Stdin) + for { + fmt.Printf(` + > list : lists all the games + > quit : quits + +`) + + if !in.Scan() { + break + } + + fmt.Println() + + switch in.Text() { + case "quit": + fmt.Println("bye!") + return + + case "list": + for _, g := range games { + fmt.Printf("#%d: %-15q %-20s $%d\n", + g.id, g.name, "("+g.genre+")", g.price) + } + } + } +} diff --git a/24-structs/exercises/03-query-by-id/main.go b/24-structs/exercises/03-query-by-id/main.go new file mode 100644 index 0000000..96101f1 --- /dev/null +++ b/24-structs/exercises/03-query-by-id/main.go @@ -0,0 +1,47 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package main + +// --------------------------------------------------------- +// EXERCISE: Query By Id +// +// Add a new command: "id". So the users can query the games +// by id. +// +// 1. Before the loop, index the games by id (use a map). +// +// 2. Add the "id" command. +// When a user types: id 2 +// It should print only the game with id: 2. +// +// 3. Handle the errors: +// +// id +// wrong id +// +// id HEY +// wrong id +// +// id 10 +// sorry. i don't have the game +// +// id 1 +// #1: "god of war" (action adventure) $50 +// +// id 2 +// #2: "x-com 2" (strategy) $40 +// +// +// EXPECTED OUTPUT +// Please also run the solution and try the program with +// list, quit, and id commands to see it in action. +// --------------------------------------------------------- + +func main() { + // use your solution from the previous exercise +} diff --git a/24-structs/exercises/03-query-by-id/solution/main.go b/24-structs/exercises/03-query-by-id/solution/main.go new file mode 100644 index 0000000..272a724 --- /dev/null +++ b/24-structs/exercises/03-query-by-id/solution/main.go @@ -0,0 +1,100 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +func main() { + type item struct { + id int + name string + price int + } + + type game struct { + item + genre string + } + + games := []game{ + { + item: item{id: 1, name: "god of war", price: 50}, + genre: "action adventure", + }, + {item: item{id: 2, name: "x-com 2", price: 40}, genre: "strategy"}, + {item: item{id: 3, name: "minecraft", price: 20}, genre: "sandbox"}, + } + + // index the games by id + byID := make(map[int]game) + for _, g := range games { + byID[g.id] = g + } + + fmt.Printf("Inanc's game store has %d games.\n", len(games)) + + in := bufio.NewScanner(os.Stdin) + for { + fmt.Printf(` + > list : lists all the games + > id N : queries a game by id + > quit : quits + +`) + + if !in.Scan() { + break + } + + fmt.Println() + + cmd := strings.Fields(in.Text()) + if len(cmd) == 0 { + continue + } + + switch cmd[0] { + case "quit": + fmt.Println("bye!") + return + + case "list": + for _, g := range games { + fmt.Printf("#%d: %-15q %-20s $%d\n", + g.id, g.name, "("+g.genre+")", g.price) + } + + case "id": + if len(cmd) != 2 { + fmt.Println("wrong id") + continue + } + + id, err := strconv.Atoi(cmd[1]) + if err != nil { + fmt.Println("wrong id") + continue + } + + g, ok := byID[id] + if !ok { + fmt.Println("sorry. i don't have the game") + continue + } + + fmt.Printf("#%d: %-15q %-20s $%d\n", + g.id, g.name, "("+g.genre+")", g.price) + } + } +} diff --git a/24-structs/exercises/README.md b/24-structs/exercises/README.md index 0982f4e..9daa642 100644 --- a/24-structs/exercises/README.md +++ b/24-structs/exercises/README.md @@ -1,5 +1,15 @@ -# Structs Exercises +# Struct Exercises -## Warm-Up +You'll build a queryable command-line game store. -1. **[?](https://github.com/inancgumus/learngo/tree/master/???)** \ No newline at end of file +1. **[Warm Up](https://github.com/inancgumus/learngo/tree/master/24-structs/exercises/01-warmup)** + + Load up the data into the game store. + +2. **[List](https://github.com/inancgumus/learngo/tree/master/24-structs/exercises/02-list)** + + Now, it's time to add an interface to your program using the bufio.Scanner. So the users can list the games, or search for the games by id. + +3. **[Query By Id](https://github.com/inancgumus/learngo/tree/master/24-structs/exercises/03-query-by-id)** + + Add a new command: "id". So the users can query the games by id. \ No newline at end of file diff --git a/24-structs/questions/README.md b/24-structs/questions/README.md new file mode 100644 index 0000000..d9050c7 --- /dev/null +++ b/24-structs/questions/README.md @@ -0,0 +1,178 @@ +## When should you use a struct type? +1. For storing the same type of values +2. For adding an additional type of values in runtime +3. For combining different types in a single type to represent a concept *CORRECT* + +> **1:** Arrays, slices, and maps are better candidates for that. +> +> **2:** Struct fields are fixed at compile-time, you cannot add additional fields in runtime, neither you can remove them. +> +> **3:** That's right. A struct type combines different types of fields in a single type. You can use a struct type to represent a concept. +> + + +## What are the properties of struct fields? +1. They all should be of the same type +2. Each one should have a name and possibly a different type *CORRECT* +3. You can add additional fields in runtime +4. You can remove the existing fields in runtime + +> **2:** Yes, each field should have a unique name. Also, each field should have a type, but every field can have a different type. +> + + +## What is wrong with the following code? +```go +type weather struct { + temperature, humidity float64 + windSpeed float64 + temperature float64 +} +``` +1. Nothing is wrong with it +2. `temperature, humidity float64` field is a syntax error +3. `temperature` field is not unique *CORRECT* + +> **2:** That's a parallel definition. It defines two float64 fields: temperature and humidity. It is correct. +> +> **3:** Right! Struct field names should be unique. +> + + +## What is the zero-value of the following struct value? +```go +var movie struct { + title, genre string + rating float64 + released bool +} +``` +1. `{}` +2. `{title: "", genre: "", rating: 0, released: false}` *CORRECT* +3. `{title: "", genre: "", rating: 0, released: true}` +4. `{"title, genre": "", rating: 0, released: false}` + +> **1:** That's an empty struct value with no fields. +> +> **2:** Right! Go initializes a struct's fields to zero-values depending on their type. +> + + + +## What is the type of the following struct? +```go +avengers := struct { + title, genre string + rating float64 + released bool +}{ + "avengers: end game", "sci-fi", 8.9, true, +} + +fmt.Printf("%T\n", avengers) +``` +1. `struct{}` +2. `struct{ string; string; float64; bool }` +3. `struct{ title string; genre string; rating float64; released bool }` *CORRECT* +4. `{title: "avengers: end game"; genre: "sci-fi"; rating: 8.9; released: true}` + +> **1:** That's an empty struct type with no fields. +> +> **2:** Fields names is also a part of a struct's type. +> +> **3:** Right! Field names and types are part of a struct's type. +> +> **4:** Nope, that's a struct value. +> + + +## Are the following struct values equal? +```go +type movie struct { + title, genre string + rating float64 + released bool +} + +avengers := movie{"avengers: end game", "sci-fi", 8.9, true} +clone := movie{ + title: "avengers: end game", genre: "sci-fi", + rating: 8.9, released: true, + } +``` +1. There is a syntax error +2. Yes *CORRECT* +3. No + +> **2:** When creating a struct value, it doesn't matter whether you use the field names or not. So, they are equal. +> + + + +## Are the following struct values equal? If not, why? +```go +type movie struct { + title, genre string + rating float64 + released bool +} + +avengers := movie{ + title: "avengers: end game", genre: "sci-fi", + rating: 8.9, released: true, +} + +clone := movie{title: "avengers: end game", genre: "sci-fi"} + +fmt.Println(avengers == clone) +``` +1. Yes: They have the same set of fields +2. No : They are not comparable +3. No : Field values are different *CORRECT* + +> **1:** That's right, this means they are comparable, but that's not enough. +> +> **2:** Yes, they are. They use the same struct type. +> +> **3:** Yes, when you omit some of the fields, Go assigns zero values to them. Here, "clone" struct value's "rating" and "released" fields are: 0, and false, respectively. +> + + +## Do the movie and performance struct types have the same types? +```go +type item struct { title string } +type movie struct { item } +type performance struct { item } +``` +1. Yes: They have the same set of fields +2. No : They have different type names *CORRECT* +3. No : An embedded field cannot be compared + +> **2:** Right! Types with different names cannot be compared. However, you can convert one of them to the other because they have the same set of fields. movie{} == movie(performance{}) is ok, or vice versa. +> + + +## What does the program print? +```go +type item struct{ title string } + +type movie struct { + item + title string +} + +m := movie{ + title: "avengers: end game", + item: item{"midnight in paris"}, +} + +fmt.Println(m.title, "&", m.item.title) +``` +1. midnight in paris & midnight in paris +2. avengers: end game & avengers: end game +3. midnight in paris & avengers: end game +4. avengers: end game & midnight in paris *CORRECT* + +> **4:** Right! `m.title` returns "avengers: end game" because the outer type always takes priority. However, `m.item.title` returns "midnight in paris" because you explicitly get it from the inner type: item. +> + diff --git a/30-concurrency/xxx-concurrent-downloader/fetch/session.go b/30-concurrency/xxx-concurrent-downloader/fetch/session.go index ee1f18f..3de9ea3 100644 --- a/30-concurrency/xxx-concurrent-downloader/fetch/session.go +++ b/30-concurrency/xxx-concurrent-downloader/fetch/session.go @@ -32,8 +32,8 @@ func (s *Session) Start(transfers ...Transfer) <-chan Progress { for _, t := range transfers { go func(t Transfer) { + defer wg.Done() t.Start(updates, s.done) - wg.Done() }(t) }