├── chapter13 ├── test_1.txt ├── test.txt ├── error.go ├── hash_crc32.go ├── sha_1.go ├── read.go ├── walk.go ├── write.go ├── list.go ├── max.go ├── readdir.go ├── mutex.go ├── files_folders.go ├── http.go ├── hash_crc32_files.go ├── string.go ├── sort.go ├── rpc.go └── tcp.go ├── chapter4 ├── problems │ ├── 2.md │ ├── 1.md │ ├── 6.go │ ├── 5.go │ ├── 4.md │ └── 3.md ├── variable.go ├── constant.go ├── variable_1.go ├── multiple_var.go ├── variable_2.go ├── scope.go ├── variable_3.go └── example.go ├── chapter10 ├── problems │ ├── 1.md │ ├── 3.md │ └── 2.go ├── routine_1.go ├── routine_2.go ├── channel_1.go ├── select.go └── timeout.go ├── chapter6 ├── problems │ ├── 1.md │ ├── 2.md │ ├── 3.md │ └── 4.go ├── array.go ├── average.go ├── main.go ├── map.go ├── elements.go ├── slice.go └── states.go ├── chapter8 ├── problems │ ├── 1.md │ ├── 2.md │ ├── 3.md │ ├── 4.go │ └── 5.go ├── new.go └── pointer.go ├── chapter3 ├── numbers.go ├── problems │ ├── 3.go │ ├── 4.md │ ├── 1.md │ ├── 2.md │ └── 5.go ├── strings.go └── booleans.go ├── chapter2 ├── problems │ ├── 3.md │ ├── 1.md │ ├── 2.md │ ├── 3.go │ └── 5.go └── main.go ├── chapter5 ├── for_2.go ├── for_1.go ├── problems │ ├── 2.go │ ├── 1.go │ ├── 1.md │ └── 3.go ├── for_if.go └── switch.go ├── chapter7 ├── closure.go ├── multiple.go ├── recursive.go ├── variadic.go ├── problems │ ├── 5.go │ ├── 1.go │ ├── 3.go │ ├── 4.go │ ├── 2.go │ └── 6.md └── function.go ├── README.md ├── chapter11 ├── main.go ├── problems │ ├── 2.md │ ├── 5.md │ ├── 3.md │ ├── 1.md │ └── 4.go └── math │ ├── math.go │ └── math_test.go ├── chapter12 └── problems │ ├── 1 │ ├── math.go │ └── math_test.go │ └── 2 │ ├── simplemath.go │ └── simplemath_test.go ├── chapter9 ├── circle.go ├── circle_with_method.go ├── problems │ ├── 1.md │ ├── 2.md │ └── 3.go ├── rectangle.go ├── embedded_type.go ├── animal_struct.go └── interface.go └── .gitignore /chapter13/test_1.txt: -------------------------------------------------------------------------------- 1 | test -------------------------------------------------------------------------------- /chapter13/test.txt: -------------------------------------------------------------------------------- 1 | The quick brown fox jumps over the lazy dog. 2 | -------------------------------------------------------------------------------- /chapter4/problems/2.md: -------------------------------------------------------------------------------- 1 | **What is the value of `x` after running: `x := 5; x += 1` ?** 2 | 3 | x = 6 -------------------------------------------------------------------------------- /chapter10/problems/1.md: -------------------------------------------------------------------------------- 1 | **How do you specify the direction of a channel type?** 2 | 3 | With arrow sign <- and -> -------------------------------------------------------------------------------- /chapter6/problems/1.md: -------------------------------------------------------------------------------- 1 | **How do you access the 4th element of an array or slice?** 2 | 3 | array[3] and slice[3] -------------------------------------------------------------------------------- /chapter8/problems/1.md: -------------------------------------------------------------------------------- 1 | **How do you get the memory address of a variable?** 2 | 3 | Using `&` before any variable -------------------------------------------------------------------------------- /chapter3/numbers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("1 + 1 =", 1.0+1.0) 7 | } 8 | -------------------------------------------------------------------------------- /chapter6/problems/2.md: -------------------------------------------------------------------------------- 1 | **What is the length of a slice created using: `make([]int, 3, 9)`?** 2 | 3 | 3, with the capacity of 9. -------------------------------------------------------------------------------- /chapter3/problems/3.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(uint64(321325 * 424521)) 7 | } 8 | -------------------------------------------------------------------------------- /chapter2/problems/3.md: -------------------------------------------------------------------------------- 1 | **Our program begain with `package main`. What would the files in the `fmt` package begin with?** 2 | 3 | `package fmt` -------------------------------------------------------------------------------- /chapter4/variable.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var x string = "Hello World" 7 | fmt.Println(x) 8 | } 9 | -------------------------------------------------------------------------------- /chapter10/problems/3.md: -------------------------------------------------------------------------------- 1 | **What is a buffered channel? how would you create one with a capacity of 20?** 2 | ``` 3 | c := make(chan int, 20) 4 | ``` -------------------------------------------------------------------------------- /chapter4/constant.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | const x string = "Hello World" 7 | fmt.Println(x) 8 | } 9 | -------------------------------------------------------------------------------- /chapter6/array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var x [5]int 7 | x[4] = 100 8 | fmt.Println(x) 9 | } 10 | -------------------------------------------------------------------------------- /chapter5/for_2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | for i := 1; i <= 10; i++ { 7 | fmt.Println(i) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /chapter4/variable_1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var x string 7 | x = "Hello World" 8 | fmt.Println(x) 9 | } 10 | -------------------------------------------------------------------------------- /chapter5/for_1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | i := 1 7 | for i <= 10 { 8 | fmt.Println(i) 9 | i = i + 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter6/problems/3.md: -------------------------------------------------------------------------------- 1 | **Given the array:*** 2 | ``` 3 | x := [6]string{"a", "b", "c", "d", "e", "f"} 4 | ``` 5 | **What would `x[2:5]` give you?** 6 | 7 | {"c", "d", "e", "f"} -------------------------------------------------------------------------------- /chapter2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // this is a comment 6 | 7 | func main() { 8 | var x string = "Hello World" 9 | fmt.Println(x) 10 | } 11 | -------------------------------------------------------------------------------- /chapter2/problems/1.md: -------------------------------------------------------------------------------- 1 | **What is a whitespace?** 2 | 3 | Newlines, spaces and tabs are whitespaces. Go mostly doesn't care about whitespace, we use it to make prorams easier to read. -------------------------------------------------------------------------------- /chapter4/problems/1.md: -------------------------------------------------------------------------------- 1 | **What are two ways to create a new variable?** 2 | 3 | ```go 4 | var myvar int = 3 // Conventional way 5 | myvar := 3 // Type inferrence 6 | ``` -------------------------------------------------------------------------------- /chapter13/error.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | err := errors.New("error message") 10 | fmt.Println(err) 11 | } 12 | -------------------------------------------------------------------------------- /chapter4/multiple_var.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var ( 6 | a = 5 7 | b = 10 8 | c = 15 9 | ) 10 | 11 | func main() { 12 | fmt.Println(a, b, c) 13 | } 14 | -------------------------------------------------------------------------------- /chapter7/closure.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | add := func(x, y int) int { 7 | return x + y 8 | } 9 | fmt.Println(add(1, 1)) 10 | } 11 | -------------------------------------------------------------------------------- /chapter5/problems/2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | for i := 1; i <= 100; i++ { 7 | if i%3 == 0 { 8 | fmt.Println(i) 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Golang-book 2 | =========== 3 | 4 | Chapter-by-chapter examples and problems from [An Introduction to Programming in Go](http://www.golang-book.com/) by Caleb Doxsey. 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /chapter4/variable_2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var x string 7 | x = "first " 8 | fmt.Println(x) 9 | x = "second" 10 | fmt.Println(x) 11 | } 12 | -------------------------------------------------------------------------------- /chapter7/multiple.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func f() (int, int) { 6 | return 5, 6 7 | } 8 | 9 | func main() { 10 | x, y := f() 11 | fmt.Println(x, y) 12 | } 13 | -------------------------------------------------------------------------------- /chapter8/problems/2.md: -------------------------------------------------------------------------------- 1 | **How do you assign a value to a pointer?** 2 | 3 | By prepending `*` to its type, like: 4 | 5 | ``` 6 | var num *int = 10 7 | 8 | num := 0 9 | *num = 10 10 | ``` -------------------------------------------------------------------------------- /chapter4/scope.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var x string = "Hello World" 6 | 7 | func main() { 8 | fmt.Println(x) 9 | } 10 | 11 | func f() { 12 | fmt.Println(x) 13 | } 14 | -------------------------------------------------------------------------------- /chapter4/variable_3.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var x string 7 | x = "first " 8 | fmt.Println(x) 9 | x = x + "second" 10 | fmt.Println(x) 11 | } 12 | -------------------------------------------------------------------------------- /chapter3/strings.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(len("Hello World")) 7 | fmt.Println("Hello World"[1]) 8 | fmt.Println("Hello " + "World") 9 | } 10 | -------------------------------------------------------------------------------- /chapter5/problems/1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | i := 10 7 | if i > 10 { 8 | fmt.Println("Big") 9 | } else { 10 | fmt.Println("Small") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter5/problems/1.md: -------------------------------------------------------------------------------- 1 | **What does the following program print:** 2 | 3 | ``` 4 | i := 10 5 | if i > 10 { 6 | fmt.Println("Big") 7 | } else { 8 | fmt.Println("Small") 9 | } 10 | ``` 11 | 12 | Small. -------------------------------------------------------------------------------- /chapter11/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | import "golang-book/chapter11/math" 5 | 6 | func main() { 7 | xs := []float64{1, 2, 3, 4} 8 | avg := math.Average(xs) 9 | fmt.Println(avg) 10 | } 11 | -------------------------------------------------------------------------------- /chapter4/problems/6.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func fToM(feet float64) (meter float64) { 6 | meter = feet * 0.3048 7 | return 8 | } 9 | 10 | func main() { 11 | fmt.Println(fToM(57)) 12 | } 13 | -------------------------------------------------------------------------------- /chapter13/hash_crc32.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "hash/crc32" 6 | ) 7 | 8 | func main() { 9 | h := crc32.NewIEEE() 10 | h.Write([]byte("test")) 11 | v := h.Sum32() 12 | fmt.Println(v) 13 | } 14 | -------------------------------------------------------------------------------- /chapter13/sha_1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/sha1" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | h := sha1.New() 10 | h.Write([]byte("test")) 11 | bs := h.Sum([]byte{}) 12 | fmt.Println(bs) 13 | } 14 | -------------------------------------------------------------------------------- /chapter11/problems/2.md: -------------------------------------------------------------------------------- 1 | **What is the difference between an identifier that starts with a capital letter and one which doesn't? (`Average` vs `average`)** 2 | 3 | Anything that starts with a capital letter can be used by other programs. -------------------------------------------------------------------------------- /chapter4/problems/5.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(fToC(57)) 7 | } 8 | 9 | func fToC(fTemp float32) (cTemp float32) { 10 | cTemp = (fTemp - 32) * 5 / 9 11 | return 12 | } 13 | -------------------------------------------------------------------------------- /chapter11/problems/5.md: -------------------------------------------------------------------------------- 1 | **How would you document the functions you created in #3?** 2 | 3 | `godoc golang-book/chapter11/problems/4 Avereage` 4 | `godoc golang-book/chapter11/problems/4 Min` 5 | `godoc golang-book/chapter11/problems/4 Max` -------------------------------------------------------------------------------- /chapter4/problems/4.md: -------------------------------------------------------------------------------- 1 | **What is the difference between `var` and `const`?** 2 | 3 | `var` is a mutable (changeable) variable, while `const` is used to define a fixed-value variable that will never change throughout the rest of the program. -------------------------------------------------------------------------------- /chapter4/example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Print("Enter a number: ") 7 | var input float64 8 | fmt.Scanf("%f", &input) 9 | 10 | output := input * 2 11 | 12 | fmt.Println(output) 13 | } 14 | -------------------------------------------------------------------------------- /chapter3/booleans.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(true && true) 7 | fmt.Println(true && false) 8 | fmt.Println(true || true) 9 | fmt.Println(true || false) 10 | fmt.Println(!true) 11 | } 12 | -------------------------------------------------------------------------------- /chapter5/for_if.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | i := 1 7 | for i <= 10 { 8 | if i%2 == 0 { 9 | fmt.Println(i, "even") 10 | } else { 11 | fmt.Println(i, "odd") 12 | } 13 | i++ 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /chapter7/recursive.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func factorial(x uint) uint { 6 | if x == 0 { 7 | return 1 8 | } 9 | return x * factorial(x-1) 10 | } 11 | 12 | func main() { 13 | fmt.Println(factorial(5)) 14 | } 15 | -------------------------------------------------------------------------------- /chapter8/problems/3.md: -------------------------------------------------------------------------------- 1 | **How do you create a new pointer?** 2 | 3 | By prepending a `*` before it, like: 4 | 5 | ``` 6 | var myPtr *float64 7 | ``` 8 | Or use Go's built-in function, like: 9 | 10 | ``` 11 | myPtr := new(float64) 12 | ``` -------------------------------------------------------------------------------- /chapter13/read.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | ) 7 | 8 | func main() { 9 | bs, err := ioutil.ReadFile("test.txt") 10 | if err != nil { 11 | return 12 | } 13 | str := string(bs) 14 | fmt.Println(str) 15 | } 16 | -------------------------------------------------------------------------------- /chapter11/math/math.go: -------------------------------------------------------------------------------- 1 | package math 2 | 3 | // Finds the average of a series of numbers 4 | func Average(xs []float64) float64 { 5 | total := float64(0) 6 | for _, x := range xs { 7 | total += x 8 | } 9 | return total / float64(len(xs)) 10 | } 11 | -------------------------------------------------------------------------------- /chapter7/variadic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func add(args ...int) int { 6 | total := 0 7 | for _, v := range args { 8 | total += v 9 | } 10 | return total 11 | } 12 | 13 | func main() { 14 | fmt.Println(add(1, 2, 3)) 15 | } 16 | -------------------------------------------------------------------------------- /chapter13/walk.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | ) 8 | 9 | func main() { 10 | filepath.Walk(".", func(path string, info os.FileInfo, err error) error { 11 | fmt.Println(path) 12 | return nil 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /chapter13/write.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "os" 4 | 5 | func main() { 6 | file, err := os.Create("test_1.txt") 7 | if err != nil { 8 | // handle error here 9 | return 10 | } 11 | defer file.Close() 12 | 13 | file.WriteString("test") 14 | } 15 | -------------------------------------------------------------------------------- /chapter2/problems/2.md: -------------------------------------------------------------------------------- 1 | **What is a comment? What are the two ways of writing a comment?** 2 | 3 | Comments are ignored by the Go compiler and are there for programmers to read. Go supports two styles of comments: 4 | // for inline comments and /* */ for block comments. -------------------------------------------------------------------------------- /chapter2/problems/3.go: -------------------------------------------------------------------------------- 1 | // We used the `Println` function defined in the `fmt` 2 | // package. If we wanted to use the `Exit` function from 3 | // the `os` package what would we need to do? 4 | 5 | package main 6 | 7 | import "os" 8 | 9 | func main() { 10 | Exit() 11 | } 12 | -------------------------------------------------------------------------------- /chapter10/routine_1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func f(n int) { 6 | for i := 0; i < 100; i++ { 7 | fmt.Println(n, ":", i) 8 | } 9 | } 10 | 11 | func main() { 12 | go f(0) 13 | var input string 14 | fmt.Scanln(&input) 15 | fmt.Println(input) 16 | } 17 | -------------------------------------------------------------------------------- /chapter2/problems/5.go: -------------------------------------------------------------------------------- 1 | // Modify the program we wrote so that instead of printing 2 | // `Hello World` it prints `Hello, my name is` followed by your name. 3 | 4 | package main 5 | 6 | import "fmt" 7 | 8 | func main() { 9 | fmt.Print("Hello, my name is " + "your name.") 10 | } 11 | -------------------------------------------------------------------------------- /chapter8/problems/4.go: -------------------------------------------------------------------------------- 1 | // What is the value of x after running this program? 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func square(x *float64) { 8 | *x = *x * *x 9 | fmt.Println(*x) 10 | } 11 | func main() { 12 | x := 1.5 13 | square(&x) 14 | } 15 | 16 | // The answer is 2.25 17 | -------------------------------------------------------------------------------- /chapter13/list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "container/list" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | var x list.List 10 | x.PushBack(1) 11 | x.PushBack(2) 12 | x.PushBack(3) 13 | 14 | for e := x.Front(); e != nil; e = e.Next() { 15 | fmt.Println(e.Value.(int)) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /chapter6/average.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | x := [5]float64{ 7 | 98, 8 | 93, 9 | 77, 10 | 82, 11 | 83, 12 | } 13 | 14 | var total float64 = 0 15 | for _, value := range x { 16 | total += value 17 | } 18 | fmt.Println(total / float64(len(x))) 19 | } 20 | -------------------------------------------------------------------------------- /chapter12/problems/1/math.go: -------------------------------------------------------------------------------- 1 | package math 2 | 3 | // Finds the average of a series of numbers 4 | func Average(xs []float64) float64 { 5 | total := float64(0) 6 | if len(xs) == 0 { 7 | return total 8 | } 9 | 10 | for _, x := range xs { 11 | total += x 12 | } 13 | return total / float64(len(xs)) 14 | } 15 | -------------------------------------------------------------------------------- /chapter13/max.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "math/rand" 7 | ) 8 | 9 | func main() { 10 | // Define flags 11 | maxp := flag.Int("max", 6, "the max value") 12 | // Parse 13 | flag.Parse() 14 | // Generate a number between 0 and max 15 | fmt.Println(rand.Intn(*maxp)) 16 | } 17 | -------------------------------------------------------------------------------- /chapter8/new.go: -------------------------------------------------------------------------------- 1 | // Another way to get a pointer is to use the built-in `new` function 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func one(xPtr *int) { 8 | *xPtr = 1 9 | } 10 | 11 | func main() { 12 | // this is a pointer 13 | xPtr := new(int) 14 | one(xPtr) 15 | fmt.Println(*xPtr) // x is 1 16 | } 17 | -------------------------------------------------------------------------------- /chapter7/problems/5.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func fib(n uint) uint { 6 | if n == 0 { 7 | return 0 8 | } else if n == 1 { 9 | return 1 10 | } 11 | return fib(n-1) + fib(n-2) 12 | } 13 | 14 | func main() { 15 | for i := 0; i <= 10; i++ { 16 | fmt.Println(fib(uint(i))) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter11/problems/3.md: -------------------------------------------------------------------------------- 1 | **What is a package alias? How do you make one?** 2 | 3 | A package alias is used when there's a package name collision. Say, we have our own `math` package and Go's core `math` package. We write: 4 | 5 | ``` 6 | import m ~/Go/path/to/our/math 7 | import math 8 | 9 | m.Average() 10 | math.Pi 11 | ``` -------------------------------------------------------------------------------- /chapter6/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var x [5]float64 7 | x[0] = 98 8 | x[1] = 93 9 | x[2] = 77 10 | x[3] = 82 11 | x[4] = 83 12 | 13 | var total float64 = 0 14 | for i := 0; i < len(x); i++ { 15 | total += x[i] 16 | } 17 | fmt.Println(total / float64(len(x))) 18 | } 19 | -------------------------------------------------------------------------------- /chapter3/problems/4.md: -------------------------------------------------------------------------------- 1 | **What is a string? How do you find its length?** 2 | 3 | String is a sequence of 'string' of characters with a definite (immutable) length used to represent text. Go strings re made up of individual bytes, usually one for each character. 4 | 5 | To find the length of a string, use Go built-in function `len()` -------------------------------------------------------------------------------- /chapter8/problems/5.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func swap(x *int, y *int) { 6 | xVal := *x 7 | yVal := *y 8 | 9 | *x = yVal 10 | *y = xVal 11 | } 12 | 13 | func main() { 14 | x := 8 15 | y := 3 16 | swap(&x, &y) 17 | fmt.Println("x Should be 3 ->", x) 18 | fmt.Println("y Should be 8 ->", y) 19 | } 20 | -------------------------------------------------------------------------------- /chapter6/map.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | x := make(map[string]int) 7 | x["year"] = 1999 8 | x["age"] = 10 9 | delete(x, "age") 10 | fmt.Println("x: ", x) 11 | 12 | y := make(map[string]string) 13 | y["name"] = "George Ong" 14 | y["age"] = "18" 15 | fmt.Println("His name is " + y["name"] + ", he is " + y["age"]) 16 | } 17 | -------------------------------------------------------------------------------- /chapter9/circle.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | import "math" 5 | 6 | type Circle struct { 7 | x, y, r float64 8 | } 9 | 10 | func circleArea(c *Circle) float64 { 11 | return math.Pi * c.r * c.r 12 | } 13 | 14 | func main() { 15 | // create a circle with coordinate (0,0) and r = 5 16 | c := Circle{0, 0, 5} 17 | fmt.Println(circleArea(&c)) 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/circle_with_method.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | import "math" 5 | 6 | type Circle struct { 7 | x, y, r float64 8 | } 9 | 10 | func (c *Circle) area() float64 { 11 | return math.Pi * c.r * c.r 12 | } 13 | 14 | func main() { 15 | // create a circle with coordinate (0,0) and r = 5 16 | c := Circle{0, 0, 5} 17 | fmt.Println(c.area()) 18 | } 19 | -------------------------------------------------------------------------------- /chapter13/readdir.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | dir, err := os.Open(".") 10 | if err != nil { 11 | return 12 | } 13 | defer dir.Close() 14 | 15 | fileInfos, err := dir.Readdir(-1) 16 | if err != nil { 17 | return 18 | } 19 | for _, fi := range fileInfos { 20 | fmt.Println(fi.Name()) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /chapter3/problems/1.md: -------------------------------------------------------------------------------- 1 | **How are integers stored on a computer?** 2 | 3 | Go's integer types are: `uint8`, `uint16`, `uint32`, `uint64`, `int8`, `int16`, `int32`, `int64`. Hence meaning integers can be stored in 8 bits (a byte, which can represent integer 0-255), 16 bits (2 bytes), 32 bits (3 bytes) and 64 bits (4 bytes). Prefix `u-` or `unsigned` meaning integers can only be 0 and positive numbers. -------------------------------------------------------------------------------- /chapter3/problems/2.md: -------------------------------------------------------------------------------- 1 | **We know that (in base 10) the largest 1 digit number is 9 and the largest 2 digit number is 99. Given that in binary the largest 2 digit num- ber is 11 (3), the largest 3 digit number is 111 (7) and the largest 4 digit number is 1111 (15) what's the largest 8 digit number? (hint: 101-1 = 9 and 102-1 = 99)** 2 | 3 | 11111111 equals 255 in base 10. (That's a byte, or 8 bits) -------------------------------------------------------------------------------- /chapter9/problems/1.md: -------------------------------------------------------------------------------- 1 | **What's the difference between a method and a function?** 2 | 3 | A function is a block of code that maps zero or more input parameters to zero or more output parameters. Functions are also known as procedures or subroutines. 4 | 5 | A method is a function that is "owned" or related to an object or a struct, and can be called by an instance with a dot notation. (obj.method()) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | *~ 27 | *# -------------------------------------------------------------------------------- /chapter13/mutex.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | m := new(sync.Mutex) 11 | 12 | for i := 0; i < 10; i++ { 13 | go func(i int) { 14 | m.Lock() 15 | fmt.Println(i, "start") 16 | time.Sleep(time.Second) 17 | fmt.Println(i, "end") 18 | m.Unlock() 19 | }(i) 20 | } 21 | 22 | var input string 23 | fmt.Scanln(&input) 24 | } 25 | -------------------------------------------------------------------------------- /chapter3/problems/5.go: -------------------------------------------------------------------------------- 1 | // Whats the value of the expression `(true && false) || 2 | // (false && true) || !(false && false)`? 3 | 4 | // true && false = false 5 | // false && true = false 6 | // false && false = false 7 | // Therefore, false || false || !false = true 8 | 9 | package main 10 | 11 | import "fmt" 12 | 13 | func main() { 14 | fmt.Println((true && false) || (false && true) || !(false && false)) 15 | } 16 | -------------------------------------------------------------------------------- /chapter6/problems/4.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | x := []int{ 7 | 48, 96, 86, 68, 8 | 57, 82, 63, 70, 9 | 37, 34, 83, 27, 10 | 19, 97, 9, 17, 11 | } 12 | 13 | fmt.Println(minVal(x)) 14 | } 15 | 16 | func minVal(arr []int) int { 17 | min := arr[0] 18 | 19 | for i := 1; i < len(arr); i++ { 20 | if arr[i] < min { 21 | min = arr[i] 22 | } 23 | } 24 | return min 25 | } 26 | -------------------------------------------------------------------------------- /chapter11/problems/1.md: -------------------------------------------------------------------------------- 1 | **Why do we use packages?** 2 | 3 | Package bundles code for reusing. It reduces the chance of having overlapping names. (Namespacing) This keeps our function names short and concise, organizes code so that its easier to find code for reusing, and speeds up the compiler by only requiring recompilation of smaller chunks of a program. Although we use the package `fmt`, we don't have to recompile it every time we change our program. -------------------------------------------------------------------------------- /chapter10/routine_2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | func f(n int) { 10 | for i := 0; i < 10; i++ { 11 | fmt.Println(n, ":", i) 12 | amt := time.Duration(rand.Intn(250)) 13 | time.Sleep(time.Millisecond * amt) 14 | } 15 | } 16 | 17 | func main() { 18 | for i := 0; i < 10; i++ { 19 | go f(i) 20 | } 21 | var input string 22 | fmt.Scanln(&input) 23 | fmt.Println(input) 24 | } 25 | -------------------------------------------------------------------------------- /chapter7/problems/1.go: -------------------------------------------------------------------------------- 1 | /* `sum` is a function which takes a slice of numbers and 2 | * adds them together. What would its function signature 3 | * look like in Go? 4 | */ 5 | 6 | package main 7 | 8 | import "fmt" 9 | 10 | func main() { 11 | mySlice := []int{1, 2, 3, 5, 10} 12 | fmt.Println(sum(mySlice)) 13 | } 14 | 15 | func sum(numSlice []int) (sum int) { 16 | sum = 0 17 | for v := range numSlice { 18 | sum += numSlice[v] 19 | } 20 | return 21 | } 22 | -------------------------------------------------------------------------------- /chapter12/problems/2/simplemath.go: -------------------------------------------------------------------------------- 1 | package simplemath 2 | 3 | // Find minimum and maximum value of a float64 slice 4 | func Min(xs []float64) float64 { 5 | min := xs[0] 6 | for i := 1; i < len(xs); i++ { 7 | if xs[i] < min { 8 | min = xs[i] 9 | } 10 | } 11 | return min 12 | } 13 | 14 | func Max(xs []float64) float64 { 15 | max := xs[0] 16 | for i := 1; i < len(xs); i++ { 17 | if xs[i] > max { 18 | max = xs[i] 19 | } 20 | } 21 | return max 22 | } 23 | -------------------------------------------------------------------------------- /chapter7/problems/3.go: -------------------------------------------------------------------------------- 1 | /* Write a function with one variadic parameter that finds the 2 | * greatest number in a list of numbers 3 | */ 4 | 5 | package main 6 | 7 | import "fmt" 8 | 9 | func main() { 10 | arr := []int{1, 2, 3, 4, 5} 11 | fmt.Println(greatest(arr...)) 12 | } 13 | 14 | func greatest(args ...int) int { 15 | greatest := args[0] 16 | for v := 1; v <= len(args); v++ { 17 | if v > greatest { 18 | greatest = v 19 | } 20 | } 21 | return greatest 22 | } 23 | -------------------------------------------------------------------------------- /chapter7/problems/4.go: -------------------------------------------------------------------------------- 1 | // Using `makeEvenGenerator` as an example, write a 2 | // `makeOddGenerator` function that generates odd numbers. 3 | 4 | package main 5 | 6 | import "fmt" 7 | 8 | func makeOddGenerator() func() uint { 9 | i := uint(1) 10 | return func() (ret uint) { 11 | ret = i 12 | i += 2 13 | return 14 | } 15 | } 16 | 17 | func main() { 18 | nextOdd := makeOddGenerator() 19 | fmt.Println(nextOdd()) 20 | fmt.Println(nextOdd()) 21 | fmt.Println(nextOdd()) 22 | } 23 | -------------------------------------------------------------------------------- /chapter7/function.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func average(xs []float64) float64 { 6 | total := 0.0 7 | for _, v := range xs { 8 | total += v 9 | } 10 | return total / float64(len(xs)) 11 | } 12 | 13 | func total(xs []float64) (total float64) { 14 | total = 0.0 15 | for _, v := range xs { 16 | total += v 17 | } 18 | return 19 | } 20 | 21 | func main() { 22 | scores := []float64{98, 93, 77, 82, 83} 23 | fmt.Println(average(scores)) 24 | fmt.Println(total(scores)) 25 | } 26 | -------------------------------------------------------------------------------- /chapter9/rectangle.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | import "math" 5 | 6 | type Rectangle struct { 7 | x1, y1, x2, y2 float64 8 | } 9 | 10 | func distance(x1, y1, x2, y2 float64) float64 { 11 | a := x2 - x1 12 | b := y2 - y1 13 | return math.Sqrt(a*a + b*b) 14 | } 15 | 16 | func (r *Rectangle) area() float64 { 17 | l := distance(r.x1, r.y1, r.x1, r.y2) 18 | w := distance(r.x1, r.y1, r.x2, r.y2) 19 | return l * w 20 | } 21 | 22 | func main() { 23 | r := Rectangle{0, 0, 10, 10} 24 | fmt.Println(r.area()) 25 | } 26 | -------------------------------------------------------------------------------- /chapter13/files_folders.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | file, err := os.Open("test.txt") 10 | if err != nil { 11 | // handle the error here 12 | return 13 | } 14 | defer file.Close() 15 | 16 | // get the file size 17 | stat, err := file.Stat() 18 | if err != nil { 19 | return 20 | } 21 | 22 | // read the file 23 | bs := make([]byte, stat.Size()) 24 | _, err = file.Read(bs) 25 | if err != nil { 26 | return 27 | } 28 | 29 | str := string(bs) 30 | fmt.Println(str) 31 | } 32 | -------------------------------------------------------------------------------- /chapter9/embedded_type.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Person struct { 6 | name string 7 | } 8 | 9 | // People can talk... 10 | func (someguy *Person) Talk() { 11 | fmt.Println("Hi, my name is", someguy.name) 12 | } 13 | 14 | type Android struct { 15 | Person // anonymous field without a name 16 | model string 17 | } 18 | 19 | func main() { 20 | p := new(Person) 21 | p.name = "Roger" 22 | p.Talk() 23 | 24 | a := new(Android) 25 | a.name = "HAL2000" 26 | // Since androids are persons, androids can talk too! 27 | a.Talk() 28 | } 29 | -------------------------------------------------------------------------------- /chapter13/http.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | ) 7 | 8 | func hello(res http.ResponseWriter, req *http.Request) { 9 | res.Header().Set( 10 | "Content-Type", 11 | "text/html", 12 | ) 13 | io.WriteString( 14 | res, 15 | ` 16 | 17 | 18 | Hello World 19 | 20 | 21 | Hello World! 22 | 23 | `, 24 | ) 25 | } 26 | 27 | func main() { 28 | http.HandleFunc("/hello", hello) 29 | http.ListenAndServe(":9000", nil) 30 | } 31 | -------------------------------------------------------------------------------- /chapter13/hash_crc32_files.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "hash/crc32" 6 | "io/ioutil" 7 | ) 8 | 9 | func getHash(filename string) (uint32, error) { 10 | bs, err := ioutil.ReadFile("test1.txt") 11 | if err != nil { 12 | return 0, err 13 | } 14 | h := crc32.NewIEEE() 15 | h.Write(bs) 16 | return h.Sum32(), nil 17 | } 18 | 19 | func main() { 20 | h1, err := getHash("test1.txt") 21 | if err != nil { 22 | return 23 | } 24 | h2, err := getHash("test2.txt") 25 | if err != nil { 26 | return 27 | } 28 | fmt.Println(h1, h2, h1 == h2) 29 | } 30 | -------------------------------------------------------------------------------- /chapter6/elements.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | elements := make(map[string]string) 7 | elements["H"] = "Hydrogen" 8 | elements["He"] = "Helium" 9 | elements["Li"] = "Lithium" 10 | elements["Be"] = "Beryllium" 11 | elements["B"] = "Boron" 12 | elements["C"] = "Carbon" 13 | elements["N"] = "Nitrogen" 14 | elements["O"] = "Oxygen" 15 | elements["F"] = "Fluorine" 16 | elements["Ne"] = "Neon" 17 | 18 | //fmt.Println(elements["Li"]) 19 | //name, ok := elements["Un"] 20 | name, ok := elements["N"] 21 | fmt.Println(name, ok) 22 | } 23 | -------------------------------------------------------------------------------- /chapter11/problems/4.go: -------------------------------------------------------------------------------- 1 | package simplemath 2 | 3 | // Find average, minimum and maximum value of a float64 slice 4 | func Average(xs []float64) float64 { 5 | total := 0.0 6 | for _, v := range xs { 7 | total += v 8 | } 9 | return total / float64(len(xs)) 10 | } 11 | 12 | func Min(xs []float64) float64 { 13 | min := xs[0] 14 | for v := 1; i <= len(xs); i++ { 15 | if v < min { 16 | min = v 17 | } 18 | } 19 | } 20 | 21 | func Max(xs []float64) float64 { 22 | max := xs[0] 23 | for i := 1; i <= len(xs); i++ { 24 | if i > max { 25 | max = i 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /chapter7/problems/2.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Write a function which takes an integer and halves it and 3 | * returns `true` if it was even or `false` if it was odd. 4 | * For example `half(1)` should return `(0, false)` and 5 | * `half(2)` should return `(1, true)`. 6 | */ 7 | 8 | package main 9 | 10 | import "fmt" 11 | 12 | func main() { 13 | fmt.Println(half(255)) 14 | } 15 | 16 | func half(num int) (int, bool) { 17 | halfling := num / 2 18 | even := false 19 | 20 | if halfling%2 == 0 { 21 | even = true 22 | } else { 23 | even = false 24 | } 25 | return halfling, even 26 | } 27 | -------------------------------------------------------------------------------- /chapter8/pointer.go: -------------------------------------------------------------------------------- 1 | // When a function is called taking an argument, that argument's value 2 | // is copied to the function: 3 | 4 | // func zero(x int) { 5 | // x = 0 6 | // } 7 | // func main() { 8 | // x := 5 9 | // zero(x) 10 | // fmt.Println(x) // x is still 5 11 | 12 | // If we want to actually pass in the argument and modify it, not just 13 | // its value, we need to pass in its pointer. 14 | 15 | package main 16 | 17 | import "fmt" 18 | 19 | func zero(xPtr *int) { 20 | *xPtr = 0 21 | } 22 | 23 | func main() { 24 | x := 5 25 | zero(&x) 26 | fmt.Println(x) // x is 0 27 | } 28 | -------------------------------------------------------------------------------- /chapter12/problems/1/math_test.go: -------------------------------------------------------------------------------- 1 | package math 2 | 3 | import "testing" 4 | 5 | // Create a struct of inputs and outputs 6 | type testpair struct { 7 | values []float64 8 | average float64 9 | } 10 | 11 | // tests slice with inputs and outputs 12 | var tests = []testpair{ 13 | {[]float64{}, 0}, 14 | } 15 | 16 | func TestAverage(t *testing.T) { 17 | // loop through each pair 18 | for _, pair := range tests { 19 | v := Average(pair.values) 20 | if v != pair.average { 21 | t.Error( 22 | "For", pair.values, 23 | "expected", pair.average, 24 | "got", v, 25 | ) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /chapter5/problems/3.go: -------------------------------------------------------------------------------- 1 | /* 2 | Write a program that prints the numbers from 1 to 100. But for multiples of three print "Fizz" instead of the number and for the multiples of five print "Buzz". For numbers which are multiples of both three and five print "FizzBuzz". 3 | */ 4 | 5 | package main 6 | 7 | import "fmt" 8 | 9 | func main() { 10 | for i := 1; i <= 100; i++ { 11 | if (i%3 == 0) && (i%5 == 0) { 12 | fmt.Println("FizzBuzz") 13 | } else if i%5 == 0 { 14 | fmt.Println("Buzz") 15 | } else if i%3 == 0 { 16 | fmt.Println("Fizz") 17 | } else { 18 | fmt.Println(i) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /chapter4/problems/3.md: -------------------------------------------------------------------------------- 1 | **What is scope and how do you determine the scope of variable in Go?** 2 | 3 | Go is lexically scoped using blocks, which means that the variable only exists within the nearest curly braces `{``}` (a block) including any nested curly braces (blocks), but not outside of them. 4 | 5 | for instance: 6 | 7 | ```go 8 | package main 9 | 10 | import "fmt" 11 | 12 | func main() { 13 | x := 10 14 | fmt.Println(x) 15 | } 16 | 17 | func f() { 18 | fmt.Println(x) 19 | } 20 | ``` 21 | 22 | function `f` won't be able to reach `x`, since `x`'s scope begin and end inside function `main`'s block. -------------------------------------------------------------------------------- /chapter5/switch.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | 7 | var input float64 8 | fmt.Scanf("%f", &input) 9 | 10 | switch input { 11 | case 0: 12 | fmt.Println("Zero") 13 | case 1: 14 | fmt.Println("One") 15 | case 2: 16 | fmt.Println("Two") 17 | case 3: 18 | fmt.Println("Three") 19 | case 4: 20 | fmt.Println("Four") 21 | case 5: 22 | fmt.Println("Five") 23 | case 6: 24 | fmt.Println("Six") 25 | case 7: 26 | fmt.Println("Seven") 27 | case 8: 28 | fmt.Println("Eight") 29 | case 9: 30 | fmt.Println("Nine") 31 | default: 32 | fmt.Println("Unknown") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /chapter9/problems/2.md: -------------------------------------------------------------------------------- 1 | **Why would you use an embedded anonymous field instead of a normal named field?** 2 | 3 | Sometime, we will prefer a "is-a" relationship over "has-a". Consider this example: 4 | 5 | ``` 6 | type Animal struct { 7 | Kingdom string 8 | Age uint8 9 | NumLegs uint8 10 | } 11 | ``` 12 | Now, when we want a struct of Dog, we write: 13 | 14 | ``` 15 | type Dog struct { 16 | Animal 17 | Name string 18 | } 19 | ``` 20 | We say Dog "is-a" Animal when the field is anonymous. Dog will inherit all fields from Animal. Animal in this case is a concept, or template (class), not an object the Dog has. -------------------------------------------------------------------------------- /chapter11/math/math_test.go: -------------------------------------------------------------------------------- 1 | package math 2 | 3 | import "testing" 4 | 5 | // Create a struct of inputs and outputs 6 | type testpair struct { 7 | values []float64 8 | average float64 9 | } 10 | 11 | // tests slice with inputs and outputs 12 | var tests = []testpair{ 13 | {[]float64{1, 2}, 1.5}, 14 | {[]float64{1, 1, 1, 1, 1, 1}, 1}, 15 | {[]float64{-1, 1}, 0}, 16 | } 17 | 18 | func TestAverage(t *testing.T) { 19 | // loop through each pair 20 | for _, pair := range tests { 21 | v := Average(pair.values) 22 | if v != pair.average { 23 | t.Error( 24 | "For", pair.values, 25 | "expected", pair.average, 26 | "got", v, 27 | ) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /chapter6/slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | slice1 := []int{1, 2, 3} 7 | slice2 := append(slice1, 4, 5, 6) 8 | fmt.Println(slice1, slice2) 9 | 10 | slice3 := []int{1, 2, 3} 11 | slice4 := make([]int, 2) 12 | copy(slice4, slice3) 13 | fmt.Println(slice3, slice4) 14 | 15 | slice5 := make([]int, 10) 16 | slice5 = append(slice5, 9, 8, 7) 17 | fmt.Println("slice5: ", slice5) 18 | 19 | slice6 := make([]string, 3) 20 | slice6 = append(slice6, "last") 21 | slice6[0] = "first" 22 | slice6[1] = "mid" 23 | slice6[2] = "before_last" 24 | fmt.Println("slice6: ", slice6) 25 | 26 | slice7 := make([]string, 3) 27 | copy(slice7, slice6) 28 | fmt.Println("slice7: ", slice7) 29 | } 30 | -------------------------------------------------------------------------------- /chapter13/string.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println( 10 | // true 11 | strings.Contains("test", "es"), 12 | // 2 13 | strings.Count("test", "t"), 14 | // true 15 | strings.HasPrefix("test", "te"), 16 | // true 17 | strings.HasSuffix("test", "st"), 18 | // 1 19 | strings.Index("test", "e"), 20 | // "a-b" 21 | strings.Join([]string{"a", "b"}, "-"), 22 | // == "aaaaa" 23 | strings.Repeat("a", 5), 24 | // "bbaa" 25 | strings.Replace("aaaa", "a", "b", 2), 26 | // []string{"a","b","c","d","e"} 27 | strings.Split("a-b-c-d-e", "-"), 28 | // "test" 29 | strings.ToLower("TEST"), 30 | // "TEST" 31 | strings.ToUpper("test"), 32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /chapter10/channel_1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // c channel can only be sent to 9 | func pinger(c chan<- string) { 10 | for i := 0; ; i++ { 11 | c <- "ping" 12 | } 13 | } 14 | 15 | // c channel can both be sent to or receiving from 16 | // thus bi-directional 17 | func ponger(c chan string) { 18 | for i := 0; ; i++ { 19 | c <- "pong" 20 | } 21 | } 22 | 23 | // c channel can only be receiving from 24 | func printer(c <-chan string) { 25 | for { 26 | msg := <-c 27 | fmt.Println(msg) 28 | time.Sleep(time.Second * 1) 29 | } 30 | } 31 | func main() { 32 | var c chan string = make(chan string) 33 | go pinger(c) 34 | go ponger(c) 35 | go printer(c) 36 | 37 | var input string 38 | fmt.Scanln(&input) 39 | } 40 | -------------------------------------------------------------------------------- /chapter10/problems/2.go: -------------------------------------------------------------------------------- 1 | // Write your own `Sleep` function using `time.After` 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "time" 8 | ) 9 | 10 | // c channel can only be sent to 11 | func pinger(c chan<- string) { 12 | for i := 0; ; i++ { 13 | c <- "ping" 14 | } 15 | } 16 | 17 | // c channel can only be receiving from 18 | func printer(c <-chan string) { 19 | for { 20 | msg := <-c 21 | fmt.Println(msg) 22 | time.Sleep(time.Second * 1) 23 | } 24 | } 25 | func main() { 26 | // bi-directional channel 27 | c1 := make(chan string) 28 | 29 | go func() { 30 | for { 31 | select { 32 | case msg1 := <-c1: 33 | fmt.Println("Message 1", msg1) 34 | case <-time.After(time.Second * 2): 35 | fmt.Println("timeout") 36 | } 37 | } 38 | }() 39 | 40 | var input string 41 | fmt.Scanln(&input) 42 | } 43 | -------------------------------------------------------------------------------- /chapter9/animal_struct.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | type Animal struct { 9 | Kingdom string 10 | Specie string 11 | Age rune // alias for uint32 12 | Pod uint64 13 | } 14 | 15 | func (a *Animal) Born() { 16 | fmt.Println("I'm born on", time.Now()) 17 | } 18 | 19 | func (a *Animal) MakeSound() { 20 | fmt.Println("...") 21 | } 22 | 23 | func (a *Animal) Walk() { 24 | fmt.Println("I'm walking...") 25 | } 26 | 27 | type Dog struct { 28 | Animal // Dog "is-a" Animal 29 | Name string // Dog "has-a" Name 30 | } 31 | 32 | func main() { 33 | a := new(Animal) 34 | a.Pod = 4 35 | a.Born() 36 | a.MakeSound() 37 | a.Walk() 38 | fmt.Println() 39 | max := new(Dog) 40 | max.Name = "Max" 41 | max.Pod = 4 42 | fmt.Println(max.Pod) 43 | max.Born() 44 | max.MakeSound() 45 | max.Walk() 46 | } 47 | -------------------------------------------------------------------------------- /chapter13/sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | type Person struct { 9 | Name string 10 | Age int 11 | } 12 | 13 | type ByName []Person 14 | 15 | func (this ByName) Len() int { 16 | return len(this) 17 | } 18 | func (this ByName) Less(i, j int) bool { 19 | return this[i].Name < this[j].Name 20 | } 21 | func (this ByName) Swap(i, j int) { 22 | this[i], this[j] = this[j], this[i] 23 | } 24 | 25 | type ByAge []Person 26 | 27 | func (this ByAge) Len() int { 28 | return len(this) 29 | } 30 | func (this ByAge) Less(i, j int) bool { 31 | return this[i].Age < this[j].Age 32 | } 33 | func (this ByAge) Swap(i, j int) { 34 | this[i], this[j] = this[j], this[i] 35 | } 36 | 37 | func main() { 38 | kids := []Person{ 39 | {"Jill", 9}, 40 | {"Jack", 10}, 41 | {"Manny", 5}, 42 | } 43 | sort.Sort(ByName(kids)) 44 | fmt.Println(kids) 45 | sort.Sort(ByAge(kids)) 46 | fmt.Println(kids) 47 | } 48 | -------------------------------------------------------------------------------- /chapter13/rpc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "net/rpc" 7 | ) 8 | 9 | type Server struct{} 10 | 11 | func (this *Server) Negate(i int64, reply *int64) error { 12 | *reply = -i 13 | return nil 14 | } 15 | 16 | func server() { 17 | rpc.Register(new(Server)) 18 | ln, err := net.Listen("tcp", ":9999") 19 | if err != nil { 20 | fmt.Println(err) 21 | return 22 | } 23 | for { 24 | c, err := ln.Accept() 25 | if err != nil { 26 | continue 27 | } 28 | go rpc.ServeConn(c) 29 | } 30 | } 31 | 32 | func client() { 33 | c, err := rpc.Dial("tcp", "127.0.0.1:9999") 34 | if err != nil { 35 | fmt.Println(err) 36 | return 37 | } 38 | var result int64 39 | err = c.Call("Server.Negate", int64(999), &result) 40 | if err != nil { 41 | fmt.Println(err) 42 | } else { 43 | fmt.Println("Server.Negate(999) =", result) 44 | } 45 | } 46 | 47 | func main() { 48 | go server() 49 | go client() 50 | 51 | var input string 52 | fmt.Scanln(&input) 53 | } 54 | -------------------------------------------------------------------------------- /chapter12/problems/2/simplemath_test.go: -------------------------------------------------------------------------------- 1 | package simplemath 2 | 3 | import "testing" 4 | 5 | // Create a struct of inputs and outputs 6 | type testpair struct { 7 | values []float64 8 | min float64 9 | max float64 10 | } 11 | 12 | // tests slice with inputs and outputs 13 | var tests = []testpair{ 14 | {[]float64{1, 2, 3, 4, 5}, 1, 5}, 15 | {[]float64{1, 10, 34, 2, 8}, 1, 34}, 16 | {[]float64{1.5, 4.2, 67, 32, 0.2}, 0.2, 67}, 17 | {[]float64{4500, 10e+7, 12, 54.8}, 12, 10e+7}, 18 | } 19 | 20 | func TestMin(t *testing.T) { 21 | // loop through each pair 22 | for _, pair := range tests { 23 | v := Min(pair.values) 24 | if v != pair.min { 25 | t.Error( 26 | "For", pair.values, 27 | "expected", pair.min, 28 | "got", v, 29 | ) 30 | } 31 | } 32 | } 33 | func TestMax(t *testing.T) { 34 | // loop through each pair 35 | for _, pair := range tests { 36 | v := Max(pair.values) 37 | if v != pair.max { 38 | t.Error( 39 | "For", pair.values, 40 | "expected", pair.max, 41 | "got", v, 42 | ) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /chapter10/select.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // c channel can only be sent to 9 | func pinger(c chan<- string) { 10 | for i := 0; ; i++ { 11 | c <- "ping" 12 | } 13 | } 14 | 15 | // c channel can both be sent to or receiving from 16 | // thus bi-directional 17 | func ponger(c chan string) { 18 | for i := 0; ; i++ { 19 | c <- "pong" 20 | } 21 | } 22 | 23 | // c channel can only be receiving from 24 | func printer(c <-chan string) { 25 | for { 26 | msg := <-c 27 | fmt.Println(msg) 28 | time.Sleep(time.Second * 1) 29 | } 30 | } 31 | func main() { 32 | // bi-directional channel 33 | c1 := make(chan string) 34 | c2 := make(chan string) 35 | 36 | go func() { 37 | for { 38 | c1 <- "from 1" 39 | time.Sleep(time.Second * 2) 40 | } 41 | }() 42 | go func() { 43 | for { 44 | c2 <- "from 2" 45 | time.Sleep(time.Second * 3) 46 | } 47 | }() 48 | go func() { 49 | for { 50 | select { 51 | case msg1 := <-c1: 52 | fmt.Println(msg1) 53 | case msg2 := <-c2: 54 | fmt.Println(msg2) 55 | } 56 | } 57 | }() 58 | 59 | var input string 60 | fmt.Scanln(&input) 61 | } 62 | -------------------------------------------------------------------------------- /chapter6/states.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | elements := map[string]map[string]string{ 7 | "H": map[string]string{ 8 | "name": "Hydrogen", 9 | "state": "gas", 10 | }, 11 | "He": map[string]string{ 12 | "name": "Helium", 13 | "state": "gas", 14 | }, 15 | "Li": map[string]string{ 16 | "name": "Lithium", 17 | "state": "solid", 18 | }, 19 | "Be": map[string]string{ 20 | "name": "Beryllium", 21 | "state": "solid", 22 | }, 23 | "B": map[string]string{ 24 | "name": "Boron", 25 | "state": "solid", 26 | }, 27 | "C": map[string]string{ 28 | "name": "Carbon", 29 | "state": "solid", 30 | }, 31 | "N": map[string]string{ 32 | "name": "Nitrogen", 33 | "state": "gas", 34 | }, 35 | "O": map[string]string{ 36 | "name": "Oxygen", 37 | "state": "gas", 38 | }, 39 | "F": map[string]string{ 40 | "name": "Fluorine", 41 | "state": "gas", 42 | }, 43 | "Ne": map[string]string{ 44 | "name": "Neon", 45 | "state": "gas", 46 | }, 47 | } 48 | 49 | if el, ok := elements["Li"]; ok { 50 | fmt.Println(el["name"], el["state"]) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /chapter9/interface.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | import "math" 5 | 6 | type Circle struct { 7 | x, y, r float64 8 | } 9 | 10 | // area() method for Circle 11 | func (c *Circle) area() float64 { 12 | return math.Pi * c.r * c.r 13 | } 14 | 15 | type Rectangle struct { 16 | x1, y1, x2, y2 float64 17 | } 18 | 19 | // function to get distance between any two points 20 | func distance(x1, y1, x2, y2 float64) (area float64) { 21 | a := x2 - x1 22 | b := y2 - y1 23 | return math.Sqrt(a*a + b*b) 24 | } 25 | 26 | // area() method for Rectangle 27 | func (r *Rectangle) area() float64 { 28 | l := distance(r.x1, r.y1, r.x1, r.y2) 29 | w := distance(r.x1, r.y1, r.x2, r.y1) 30 | return l * w 31 | } 32 | 33 | // Shape interface 34 | type Shape interface { 35 | area() float64 36 | perimeter() float64 37 | } 38 | 39 | // a function taking a Shape interface 40 | func totalArea(shapes ...Shape) float64 { 41 | var area float64 42 | for _, s := range shapes { 43 | area += s.area() 44 | } 45 | return area 46 | } 47 | 48 | func main() { 49 | r := Rectangle{0, 0, 10, 10} 50 | c := Circle{0, 0, 5} 51 | fmt.Println(totalArea(&c, &r)) 52 | } 53 | -------------------------------------------------------------------------------- /chapter7/problems/6.md: -------------------------------------------------------------------------------- 1 | **What are defer, panic and recover? How do you recover from a run-timepanic?** 2 | 3 | `defer` is a special Go statement used to schedule a function call to be run after the function completes (very much like `finally` in Python). For example: 4 | 5 | ```go 6 | package main 7 | 8 | import "fmt" 9 | 10 | func first() { 11 | fmt.Println("1st") 12 | } 13 | func second() { 14 | fmt.Println("2nd") 15 | } 16 | func main() { 17 | defer second() 18 | first() 19 | } 20 | ``` 21 | This program prints `1st` followed by `2nd`. Basically, `defer` moves the call to `second` to the end of the function. 22 | 23 | `panic` cause a run time error. We can handle a run-time panic with the built-in `recover` function. `recover` stops the panic and returns the value that was passed to the call to `panic`. For instance: 24 | 25 | ```go 26 | package main 27 | 28 | import "fmt" 29 | 30 | func main() { 31 | defer func() { 32 | str := recover() 33 | fmt.Println(str) 34 | } () 35 | panic("PANICKING!") 36 | } 37 | ``` 38 | Note the `()` after `defer`, that's a function call. `defer` works with a called function only. -------------------------------------------------------------------------------- /chapter13/tcp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/gob" 5 | "fmt" 6 | "net" 7 | ) 8 | 9 | func server() { 10 | // listen on a port 11 | ln, err := net.Listen("tcp", ":9999") 12 | if err != nil { 13 | fmt.Println(err) 14 | return 15 | } 16 | for { 17 | // accept a connection 18 | c, err := ln.Accept() 19 | if err != nil { 20 | fmt.Println(err) 21 | continue 22 | } 23 | // handle the connection 24 | go handleServerConnection(c) 25 | } 26 | } 27 | 28 | func handleServerConnection(c net.Conn) { 29 | // receive the message 30 | var msg string 31 | err := gob.NewDecoder(c).Decode(&msg) 32 | if err != nil { 33 | fmt.Println(err) 34 | } else { 35 | fmt.Println("Received", msg) 36 | } 37 | 38 | c.Close() 39 | } 40 | 41 | func client() { 42 | // connect to the server 43 | c, err := net.Dial("tcp", "127.0.0.1:9999") 44 | if err != nil { 45 | fmt.Println(err) 46 | return 47 | } 48 | 49 | // send the message 50 | msg := "Hello World" 51 | fmt.Println("Sending", msg) 52 | err = gob.NewEncoder(c).Encode(msg) 53 | if err != nil { 54 | fmt.Println(err) 55 | } 56 | 57 | c.Close() 58 | } 59 | 60 | func main() { 61 | go server() 62 | go client() 63 | 64 | var input string 65 | fmt.Scanln(&input) 66 | } 67 | -------------------------------------------------------------------------------- /chapter10/timeout.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // c channel can only be sent to 9 | func pinger(c chan<- string) { 10 | for i := 0; ; i++ { 11 | c <- "ping" 12 | } 13 | } 14 | 15 | // c channel can both be sent to or receiving from 16 | // thus bi-directional 17 | func ponger(c chan string) { 18 | for i := 0; ; i++ { 19 | c <- "pong" 20 | } 21 | } 22 | 23 | // c channel can only be receiving from 24 | func printer(c <-chan string) { 25 | for { 26 | msg := <-c 27 | fmt.Println(msg) 28 | time.Sleep(time.Second * 1) 29 | } 30 | } 31 | func main() { 32 | // bi-directional channel 33 | c1 := make(chan string) 34 | c2 := make(chan string) 35 | 36 | go func() { 37 | for { 38 | c1 <- "from 1" 39 | time.Sleep(time.Second * 2) 40 | } 41 | }() 42 | go func() { 43 | for { 44 | c2 <- "from 2" 45 | time.Sleep(time.Second * 3) 46 | } 47 | }() 48 | go func() { 49 | for { 50 | select { 51 | case msg1 := <-c1: 52 | fmt.Println("Message 1", msg1) 53 | case msg2 := <-c2: 54 | fmt.Println("Message 2", msg2) 55 | // create a channel that send timeout after 2 secs 56 | case <-time.After(time.Second * 2): 57 | fmt.Println("timeout") 58 | } 59 | } 60 | }() 61 | 62 | var input string 63 | fmt.Scanln(&input) 64 | } 65 | -------------------------------------------------------------------------------- /chapter9/problems/3.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | import "math" 5 | 6 | type Circle struct { 7 | x, y, r float64 8 | } 9 | 10 | // area() method for Circle 11 | func (c *Circle) area() float64 { 12 | return math.Pi * c.r * c.r 13 | } 14 | 15 | // perimater() method for Circle 16 | func (c *Circle) perimeter() float64 { 17 | return math.Pi * (c.r * 2) 18 | } 19 | 20 | type Rectangle struct { 21 | x1, y1, x2, y2 float64 22 | } 23 | 24 | // function to get distance between any two points 25 | func distance(x1, y1, x2, y2 float64) (area float64) { 26 | a := x2 - x1 27 | b := y2 - y1 28 | return math.Sqrt(a*a + b*b) 29 | } 30 | 31 | // area() method for Rectangle 32 | func (r *Rectangle) area() float64 { 33 | l := distance(r.x1, r.y1, r.x1, r.y2) 34 | w := distance(r.x1, r.y1, r.x2, r.y1) 35 | return l * w 36 | } 37 | 38 | func (r *Rectangle) perimeter() float64 { 39 | l := distance(r.x1, r.y1, r.x1, r.y2) 40 | w := distance(r.x1, r.y1, r.x2, r.y1) 41 | return l*2 + w*2 42 | } 43 | 44 | // Shape interface 45 | type Shape interface { 46 | area() float64 47 | perimeter() float64 48 | } 49 | 50 | // a function taking a Shape interface 51 | func totalArea(shapes ...Shape) float64 { 52 | var area float64 53 | for _, s := range shapes { 54 | area += s.area() 55 | } 56 | return area 57 | } 58 | 59 | func main() { 60 | r := Rectangle{0, 0, 10, 10} 61 | c := Circle{0, 0, 5} 62 | fmt.Println(totalArea(&c, &r)) 63 | fmt.Println(r.perimeter()) 64 | fmt.Println(c.perimeter()) 65 | } 66 | --------------------------------------------------------------------------------