diff --git a/Go-Succinctly.pdf b/Go-Succinctly.pdf new file mode 100644 index 0000000..a3c1541 Binary files /dev/null and b/Go-Succinctly.pdf differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..388af23 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Go Succinctly + +This is the companion repo for [*Go Succinctly*](https://github.com/Gommunity/gosuccinctly) by Amir Irani. + +[![cover](https://github.com/Gommunity/gosuccinctly/blob/master/cover.png)](https://github.com/Gommunity/gosuccinctly) + +## [*Download pdf*](https://github.com/Gommunity/gosuccinctly/blob/master/Go-Succinctly.pdf) \ No newline at end of file diff --git a/cover.png b/cover.png new file mode 100644 index 0000000..bcb6972 Binary files /dev/null and b/cover.png differ diff --git a/listing1.go b/listing1.go new file mode 100644 index 0000000..73c45a1 --- /dev/null +++ b/listing1.go @@ -0,0 +1,11 @@ +// Code listing 1: https://play.golang.org/p/2C7wwJ6nxG + +// Our first program will print the classic "hello world" +// message. Here's the full source code. +package main + +import "fmt" + +func main() { + fmt.Println("hello world") +} \ No newline at end of file diff --git a/listing10.go b/listing10.go new file mode 100644 index 0000000..90f1749 --- /dev/null +++ b/listing10.go @@ -0,0 +1,20 @@ +// Code listing 10: https://play.golang.org/p/Lu01QP5AOri + +package main + +import ( + "fmt" +) + +func main() { + myArray := [...]string{"Apples", "Oranges", "Bananas"} + fmt.Printf("Initial array values: %v\n", myArray) + myFunction(myArray) + fmt.Printf("Final array values: %v\n", myArray) +} + +func myFunction(arr [3]string) { + // Change Oranges to Strawberries + arr[1] = "Strawberries" + fmt.Printf("Array values in myFunction(): %v\n", arr) +} diff --git a/listing11.go b/listing11.go new file mode 100644 index 0000000..7ddbc08 --- /dev/null +++ b/listing11.go @@ -0,0 +1,78 @@ +// Code listing 11: https://play.golang.org/p/Z3_U32sn8RF + +// _Slices_ are a key data type in Go, giving a more +// powerful interface to sequences than arrays. + +package main + +import "fmt" + +func main() { + + // Unlike arrays, slices are typed only by the + // elements they contain (not the number of elements). + // To create an empty slice with non-zero length, use + // the builtin `make`. Here we make a slice of + // `string`s of length `3` (initially zero-valued). + s := make([]string, 3) + fmt.Println("emp:", s) + + // We can set and get just like with arrays. + s[0] = "a" + s[1] = "b" + s[2] = "c" + fmt.Println("set:", s) + fmt.Println("get:", s[2]) + + // `len` returns the length of the slice as expected. + fmt.Println("len:", len(s)) + + // In addition to these basic operations, slices + // support several more that make them richer than + // arrays. One is the builtin `append`, which + // returns a slice containing one or more new values. + // Note that we need to accept a return value from + // `append` as we may get a new slice value. + s = append(s, "d") + s = append(s, "e", "f") + fmt.Println("apd:", s) + + // Slices can also be `copy`'d. Here we create an + // empty slice `c` of the same length as `s` and copy + // into `c` from `s`. + c := make([]string, len(s)) + copy(c, s) + fmt.Println("cpy:", c) + + // Slices support a "slice" operator with the syntax + // `slice[low:high]`. For example, this gets a slice + // of the elements `s[2]`, `s[3]`, and `s[4]`. + l := s[2:5] + fmt.Println("sl1:", l) + + // This slices up to (but excluding) `s[5]`. + l = s[:5] + fmt.Println("sl2:", l) + + // And this slices up from (and including) `s[2]`. + l = s[2:] + fmt.Println("sl3:", l) + + // We can declare and initialize a variable for slice + // in a single line as well. + t := []string{"g", "h", "i"} + fmt.Println("dcl:", t) + + // Slices can be composed into multi-dimensional data + // structures. The length of the inner slices can + // vary, unlike with multi-dimensional arrays. + twoD := make([][]int, 3) + for i := 0; i < 3; i++ { + innerLen := i + 1 + twoD[i] = make([]int, innerLen) + for j := 0; j < innerLen; j++ { + twoD[i][j] = i + j + } + } + fmt.Println("2d: ", twoD) +} \ No newline at end of file diff --git a/listing12.go b/listing12.go new file mode 100644 index 0000000..2584c78 --- /dev/null +++ b/listing12.go @@ -0,0 +1,20 @@ +// Code listing 12: https://play.golang.org/p/kHqSobJC2Yv + +package main + +import ( + "fmt" +) + +func main() { + mySlice := []string{"Apples", "Oranges", "Bananas"} + fmt.Printf("Initial slice values: %v\n", mySlice) + myFunction(mySlice) + fmt.Printf("Final slice values: %v\n", mySlice) +} + +func myFunction(fruits []string) { + // Change Oranges to Strawberries + fruits[1] = "Strawberries" + fmt.Printf("Slice values in myFunction(): %v\n", fruits) +} \ No newline at end of file diff --git a/listing13.go b/listing13.go new file mode 100644 index 0000000..c0ae6f6 --- /dev/null +++ b/listing13.go @@ -0,0 +1,14 @@ +// Code listing 13: https://play.golang.org/p/p3ewucCUFer + +package main + +import ( + "fmt" +) + +func main() { + mySlice := make([]int, 4, 8) + fmt.Printf("Initial Length: %d\n", len(mySlice)) + fmt.Printf("Capacity: %d\n", cap(mySlice)) + fmt.Printf("Contents: %v\n", mySlice) +} \ No newline at end of file diff --git a/listing14.go b/listing14.go new file mode 100644 index 0000000..930d1a4 --- /dev/null +++ b/listing14.go @@ -0,0 +1,24 @@ +// Code listing: https://play.golang.org/p/BtiZKrqyImq + +package main + +import ( + "fmt" +) + +func main() { + + mySlice := make([]int, 0, 8) + mySlice = append(mySlice, 1, 3, 5, 7, 9, 11, 13, 17) + + fmt.Printf("Contents: %v\n", mySlice) + fmt.Printf("Number of Items: %d\n", len(mySlice)) + fmt.Printf("Capacity: %d\n", cap(mySlice)) + + mySlice[8] = 19 + + fmt.Printf("Contents: %v\n", mySlice) + fmt.Printf("Number of Items: %d\n", len(mySlice)) + fmt.Printf("Capacity: %d\n", cap(mySlice)) + +} \ No newline at end of file diff --git a/listing15.go b/listing15.go new file mode 100644 index 0000000..348acd1 --- /dev/null +++ b/listing15.go @@ -0,0 +1,24 @@ +// Code listing 15: https://play.golang.org/p/yE-1Rhccebv + +package main + +import ( + "fmt" +) + +func main() { + + mySlice := make([]int, 0, 8) + mySlice = append(mySlice, 1, 3, 5, 7, 9, 11, 13, 17) + + fmt.Printf("Contents: %v\n", mySlice) + fmt.Printf("Number of Items: %d\n", len(mySlice)) + fmt.Printf("Capacity: %d\n", cap(mySlice)) + + mySlice = append(mySlice, 19) + + fmt.Printf("Contents: %v\n", mySlice) + fmt.Printf("Number of Items: %d\n", len(mySlice)) + fmt.Printf("Capacity: %d\n", cap(mySlice)) + +} \ No newline at end of file diff --git a/listing16.go b/listing16.go new file mode 100644 index 0000000..622a45d --- /dev/null +++ b/listing16.go @@ -0,0 +1,52 @@ +// Code listing 16: https://play.golang.org/p/U67R66Oab8r + +// _Maps_ are Go's built-in [associative data type](http://en.wikipedia.org/wiki/Associative_array) +// (sometimes called _hashes_ or _dicts_ in other languages). + +package main + +import "fmt" + +func main() { + + // To create an empty map, use the builtin `make`: + // `make(map[key-type]val-type)`. + m := make(map[string]int) + + // Set key/value pairs using typical `name[key] = val` + // syntax. + m["k1"] = 7 + m["k2"] = 13 + + // Printing a map with e.g. `fmt.Println` will show all of + // its key/value pairs. + fmt.Println("map:", m) + + // Get a value for a key with `name[key]`. + v1 := m["k1"] + fmt.Println("v1: ", v1) + + // The builtin `len` returns the number of key/value + // pairs when called on a map. + fmt.Println("len:", len(m)) + + // The builtin `delete` removes key/value pairs from + // a map. + delete(m, "k2") + fmt.Println("map:", m) + + // The optional second return value when getting a + // value from a map indicates if the key was present + // in the map. This can be used to disambiguate + // between missing keys and keys with zero values + // like `0` or `""`. Here we didn't need the value + // itself, so we ignored it with the _blank identifier_ + // `_`. + _, prs := m["k2"] + fmt.Println("prs:", prs) + + // You can also declare and initialize a new map in + // the same line with this syntax. + n := map[string]int{"foo": 1, "bar": 2} + fmt.Println("map:", n) +} \ No newline at end of file diff --git a/listing17.go b/listing17.go new file mode 100644 index 0000000..7198da5 --- /dev/null +++ b/listing17.go @@ -0,0 +1,24 @@ +// Code listing 17: https://play.golang.org/p/jYhjajBm7pQ + +package main + +import "fmt" + +func main() { + actor := map[string]int{ + "Paltrow": 43, + "Cruise": 53, + "Redford": 79, + "Diaz": 43, + "Kilmer": 56, + "Pacino": 75, + "Ryder": 44, + } + + for i := 1; i < 4; i++ { + fmt.Printf("\nRUN NUMBER %d\n", i) + for key, value := range actor { + fmt.Printf("%s : %d years old\n", key, value) + } + } +} \ No newline at end of file diff --git a/listing18.go b/listing18.go new file mode 100644 index 0000000..28205a2 --- /dev/null +++ b/listing18.go @@ -0,0 +1,34 @@ +// Code listing 18: https://play.golang.org/p/GwFoxWxhuaF + +package main + +import ( + "fmt" + "sort" +) + +func main() { + actor := map[string]int{ + "Paltrow": 43, + "Cruise": 53, + "Redford": 79, + "Diaz": 43, + "Kilmer": 56, + "Pacino": 75, + "Ryder": 44, + } + + // Store the keys in a slice + var sortedActor []string + for key := range actor { + sortedActor = append(sortedActor, key) + } + // Sort the slice alphabetically + sort.Strings(sortedActor) + + /* Retrieve the keys from the slice and use + them to look up the map values */ + for _, name := range sortedActor { + fmt.Printf("%s : %d years old\n", name, actor[name]) + } +} diff --git a/listing19.go b/listing19.go new file mode 100644 index 0000000..0df3ed5 --- /dev/null +++ b/listing19.go @@ -0,0 +1,21 @@ +// Code listing 19: https://play.golang.org/p/ueJmA28U5EF + +package main + +import "fmt" + +func main() { + + m := make(map[string]int) + + m["k1"] = 7 + m["k2"] = 13 + + delete(m, "k2") + + if _, ok := m["k2"]; ok { + fmt.Println("Ok") + } else { + fmt.Println("NotOk") + } +} \ No newline at end of file diff --git a/listing2.go b/listing2.go new file mode 100644 index 0000000..b51fd06 --- /dev/null +++ b/listing2.go @@ -0,0 +1,13 @@ +// Code listing 2: https://play.golang.org/p/vyoCoYrzTpo + +package main + +import "fmt" + +func init() { + fmt.Println("first") +} + +func main() { + fmt.Println("second") +} \ No newline at end of file diff --git a/listing20.go b/listing20.go new file mode 100644 index 0000000..beaa48c --- /dev/null +++ b/listing20.go @@ -0,0 +1,50 @@ +// Code listing 20: https://play.golang.org/p/SkL_AS-1Jd + +// _range_ iterates over elements in a variety of data +// structures. Let's see how to use `range` with some +// of the data structures we've already learned. + +package main + +import "fmt" + +func main() { + + // Here we use `range` to sum the numbers in a slice. + // Arrays work like this too. + nums := []int{2, 3, 4} + sum := 0 + for _, num := range nums { + sum += num + } + fmt.Println("sum:", sum) + + // `range` on arrays and slices provides both the + // index and value for each entry. Above we didn't + // need the index, so we ignored it with the + // blank identifier `_`. Sometimes we actually want + // the indexes though. + for i, num := range nums { + if num == 3 { + fmt.Println("index:", i) + } + } + + // `range` on map iterates over key/value pairs. + kvs := map[string]string{"a": "apple", "b": "banana"} + for k, v := range kvs { + fmt.Printf("%s -> %s\n", k, v) + } + + // `range` can also iterate over just the keys of a map. + for k := range kvs { + fmt.Println("key:", k) + } + + // `range` on strings iterates over Unicode code + // points. The first value is the starting byte index + // of the `rune` and the second the `rune` itself. + for i, c := range "go" { + fmt.Println(i, c) + } +} \ No newline at end of file diff --git a/listing21.go b/listing21.go new file mode 100644 index 0000000..79c92e8 --- /dev/null +++ b/listing21.go @@ -0,0 +1,37 @@ +// Code listing 21: https://play.golang.org/p/JpNfVtAjrc4 + +// _Functions_ are central in Go. We'll learn about +// functions with a few different examples. + +package main + +import "fmt" + +// Here's a function that takes two `int`s and returns +// their sum as an `int`. +func plus(a int, b int) int { + + // Go requires explicit returns, i.e. it won't + // automatically return the value of the last + // expression. + return a + b +} + +// When you have multiple consecutive parameters of +// the same type, you may omit the type name for the +// like-typed parameters up to the final parameter that +// declares the type. +func plusPlus(a, b, c int) int { + return a + b + c +} + +func main() { + + // Call a function just as you'd expect, with + // `name(args)`. + res := plus(1, 2) + fmt.Println("1+2 =", res) + + res = plusPlus(1, 2, 3) + fmt.Println("1+2+3 =", res) +} \ No newline at end of file diff --git a/listing22.go b/listing22.go new file mode 100644 index 0000000..099db87 --- /dev/null +++ b/listing22.go @@ -0,0 +1,16 @@ +// Code listing 22: https://play.golang.org/p/bOG8oBahGnm + +package main + +import "fmt" + +func main() { + + plus := func(a int, b int) int { + + return a + b + } + + res := plus(1, 2) + fmt.Println("1+2 =", res) +} \ No newline at end of file diff --git a/listing23.go b/listing23.go new file mode 100644 index 0000000..600cbec --- /dev/null +++ b/listing23.go @@ -0,0 +1,29 @@ +// Code listing 23: https://play.golang.org/p/chwFmr5dG1 + +// Go has built-in support for _multiple return values_. +// This feature is used often in idiomatic Go, for example +// to return both result and error values from a function. + +package main + +import "fmt" + +// The `(int, int)` in this function signature shows that +// the function returns 2 `int`s. +func vals() (int, int) { + return 3, 7 +} + +func main() { + + // Here we use the 2 different return values from the + // call with _multiple assignment_. + a, b := vals() + fmt.Println(a) + fmt.Println(b) + + // If you only want a subset of the returned values, + // use the blank identifier `_`. + _, c := vals() + fmt.Println(c) +} \ No newline at end of file diff --git a/listing24.go b/listing24.go new file mode 100644 index 0000000..3a577fb --- /dev/null +++ b/listing24.go @@ -0,0 +1,35 @@ +// Code listing 24: https://play.golang.org/p/7f0JlVhToDD + +// [_Variadic functions_](http://en.wikipedia.org/wiki/Variadic_function) +// can be called with any number of trailing arguments. +// For example, `fmt.Println` is a common variadic +// function. + +package main + +import "fmt" + +// Here's a function that will take an arbitrary number +// of `int`s as arguments. +func sum(nums ...int) { + fmt.Print(nums, " ") + total := 0 + for _, num := range nums { + total += num + } + fmt.Println(total) +} + +func main() { + + // Variadic functions can be called in the usual way + // with individual arguments. + sum(1, 2) + sum(1, 2, 3) + + // If you already have multiple args in a slice, + // apply them to a variadic function using + // `func(slice...)` like this. + nums := []int{1, 2, 3, 4} + sum(nums...) +} \ No newline at end of file diff --git a/listing25.go b/listing25.go new file mode 100644 index 0000000..f6b3475 --- /dev/null +++ b/listing25.go @@ -0,0 +1,42 @@ +// Code listing 25: https://play.golang.org/p/zb93qzV6iN3 + +// Go supports [_anonymous functions_](http://en.wikipedia.org/wiki/Anonymous_function), +// which can form closures. +// Anonymous functions are useful when you want to define +// a function inline without having to name it. + +package main + +import "fmt" + +// This function `intSeq` returns another function, which +// we define anonymously in the body of `intSeq`. The +// returned function _closes over_ the variable `i` to +// form a closure. +func intSeq() func() int { + i := 0 + return func() int { + i++ + return i + } +} + +func main() { + + // We call `intSeq`, assigning the result (a function) + // to `nextInt`. This function value captures its + // own `i` value, which will be updated each time + // we call `nextInt`. + nextInt := intSeq() + + // See the effect of the closure by calling `nextInt` + // a few times. + fmt.Println(nextInt()) + fmt.Println(nextInt()) + fmt.Println(nextInt()) + + // To confirm that the state is unique to that + // particular function, create and test a new one. + newInts := intSeq() + fmt.Println(newInts()) +} \ No newline at end of file diff --git a/listing26.go b/listing26.go new file mode 100644 index 0000000..453379c --- /dev/null +++ b/listing26.go @@ -0,0 +1,22 @@ +// Code listing 26: https://play.golang.org/p/RFn-rf42ap + +// Go supports +// recursive functions. +// Here's a classic factorial example. + +package main + +import "fmt" + +// This `fact` function calls itself until it reaches the +// base case of `fact(0)`. +func fact(n int) int { + if n == 0 { + return 1 + } + return n * fact(n-1) +} + +func main() { + fmt.Println(fact(7)) +} \ No newline at end of file diff --git a/listing27.go b/listing27.go new file mode 100644 index 0000000..e45fdc2 --- /dev/null +++ b/listing27.go @@ -0,0 +1,44 @@ +// Code listing 27: https://play.golang.org/p/KdE4TBbUL2 + +// Go supports pointers, +// allowing you to pass references to values and records +// within your program. + +package main + +import "fmt" + +// We'll show how pointers work in contrast to values with +// 2 functions: `zeroval` and `zeroptr`. `zeroval` has an +// `int` parameter, so arguments will be passed to it by +// value. `zeroval` will get a copy of `ival` distinct +// from the one in the calling function. +func zeroval(ival int) { + ival = 0 +} + +// `zeroptr` in contrast has an `*int` parameter, meaning +// that it takes an `int` pointer. The `*iptr` code in the +// function body then _dereferences_ the pointer from its +// memory address to the current value at that address. +// Assigning a value to a dereferenced pointer changes the +// value at the referenced address. +func zeroptr(iptr *int) { + *iptr = 0 +} + +func main() { + i := 1 + fmt.Println("initial:", i) + + zeroval(i) + fmt.Println("zeroval:", i) + + // The `&i` syntax gives the memory address of `i`, + // i.e. a pointer to `i`. + zeroptr(&i) + fmt.Println("zeroptr:", i) + + // Pointers can be printed too. + fmt.Println("pointer:", &i) +} \ No newline at end of file diff --git a/listing28.go b/listing28.go new file mode 100644 index 0000000..57cb757 --- /dev/null +++ b/listing28.go @@ -0,0 +1,43 @@ +// Code listing 28: https://play.golang.org/p/OMCP5KFC10 + +// Go's _structs_ are typed collections of fields. +// They're useful for grouping data together to form +// records. + +package main + +import "fmt" + +// This `person` struct type has `name` and `age` fields. +type person struct { + name string + age int +} + +func main() { + + // This syntax creates a new struct. + fmt.Println(person{"Bob", 20}) + + // You can name the fields when initializing a struct. + fmt.Println(person{name: "Alice", age: 30}) + + // Omitted fields will be zero-valued. + fmt.Println(person{name: "Fred"}) + + // An `&` prefix yields a pointer to the struct. + fmt.Println(&person{name: "Ann", age: 40}) + + // Access struct fields with a dot. + s := person{name: "Sean", age: 50} + fmt.Println(s.name) + + // You can also use dots with struct pointers - the + // pointers are automatically dereferenced. + sp := &s + fmt.Println(sp.age) + + // Structs are mutable. + sp.age = 51 + fmt.Println(sp.age) +} \ No newline at end of file diff --git a/listing29.go b/listing29.go new file mode 100644 index 0000000..9ea6518 --- /dev/null +++ b/listing29.go @@ -0,0 +1,39 @@ +// Code listing 29: https://play.golang.org/p/254m_9Yjwa + +// Go supports _methods_ defined on struct types. + +package main + +import "fmt" + +type rect struct { + width, height int +} + +// This `area` method has a _receiver type_ of `*rect`. +func (r *rect) area() int { + return r.width * r.height +} + +// Methods can be defined for either pointer or value +// receiver types. Here's an example of a value receiver. +func (r rect) perim() int { + return 2*r.width + 2*r.height +} + +func main() { + r := rect{width: 10, height: 5} + + // Here we call the 2 methods defined for our struct. + fmt.Println("area: ", r.area()) + fmt.Println("perim:", r.perim()) + + // Go automatically handles conversion between values + // and pointers for method calls. You may want to use + // a pointer receiver type to avoid copying on method + // calls or to allow the method to mutate the + // receiving struct. + rp := &r + fmt.Println("area: ", rp.area()) + fmt.Println("perim:", rp.perim()) +} \ No newline at end of file diff --git a/listing3.go b/listing3.go new file mode 100644 index 0000000..e5a25e0 --- /dev/null +++ b/listing3.go @@ -0,0 +1,24 @@ +// Code listing 3: https://play.golang.org/p/fgGVOyuZdu + +// Go has various value types including strings, +// integers, floats, booleans, etc. Here are a few +// basic examples. + +package main + +import "fmt" + +func main() { + + // Strings, which can be added together with `+`. + fmt.Println("go" + "lang") + + // Integers and floats. + fmt.Println("1+1 =", 1+1) + fmt.Println("7.0/3.0 =", 7.0/3.0) + + // Booleans, with boolean operators as you'd expect. + fmt.Println(true && false) + fmt.Println(true || false) + fmt.Println(!true) +} \ No newline at end of file diff --git a/listing30.go b/listing30.go new file mode 100644 index 0000000..0f41c26 --- /dev/null +++ b/listing30.go @@ -0,0 +1,42 @@ +// Code listing 30: https://play.golang.org/p/ufYS79Dx4BO + +package main + +import ( + "fmt" +) + +type Discount struct { + percent float32 + promotionId string +} + +type ManagersSpecial struct { + Discount + extraoff float32 +} + +func main() { + + normalPrice := float32(99.99) + + januarySale := Discount{15.00, "January"} + managerSpecial := ManagersSpecial{januarySale, 10.00} + + discountedPrice := januarySale.Calculate(normalPrice) + managerDiscount := managerSpecial.Calculate(normalPrice) + + fmt.Printf("Original price: $%4.2f\n", normalPrice) + fmt.Printf("Discount percentage: %2.2f\n", + januarySale.percent) + fmt.Printf("Discounted price: $%4.2f\n", discountedPrice) + fmt.Printf("Manager's special: $%4.2f\n", managerDiscount) +} + +func (d Discount) Calculate(originalPrice float32) float32 { + return originalPrice - (originalPrice / 100 * d.percent) +} + +func (ms ManagersSpecial) Calculate(originalPrice float32) float32 { + return ms.Discount.Calculate(originalPrice) - ms.extraoff +} \ No newline at end of file diff --git a/listing31.go b/listing31.go new file mode 100644 index 0000000..9afda24 --- /dev/null +++ b/listing31.go @@ -0,0 +1,64 @@ +// Code listing 31: https://play.golang.org/p/313UebA3rD + +// _Interfaces_ are named collections of method +// signatures. + +package main + +import "fmt" +import "math" + +// Here's a basic interface for geometric shapes. +type geometry interface { + area() float64 + perim() float64 +} + +// For our example we'll implement this interface on +// `rect` and `circle` types. +type rect struct { + width, height float64 +} +type circle struct { + radius float64 +} + +// To implement an interface in Go, we just need to +// implement all the methods in the interface. Here we +// implement `geometry` on `rect`s. +func (r rect) area() float64 { + return r.width * r.height +} +func (r rect) perim() float64 { + return 2*r.width + 2*r.height +} + +// The implementation for `circle`s. +func (c circle) area() float64 { + return math.Pi * c.radius * c.radius +} +func (c circle) perim() float64 { + return 2 * math.Pi * c.radius +} + +// If a variable has an interface type, then we can call +// methods that are in the named interface. Here's a +// generic `measure` function taking advantage of this +// to work on any `geometry`. +func measure(g geometry) { + fmt.Println(g) + fmt.Println(g.area()) + fmt.Println(g.perim()) +} + +func main() { + r := rect{width: 3, height: 4} + c := circle{radius: 5} + + // The `circle` and `rect` struct types both + // implement the `geometry` interface so we can use + // instances of + // these structs as arguments to `measure`. + measure(r) + measure(c) +} \ No newline at end of file diff --git a/listing32.go b/listing32.go new file mode 100644 index 0000000..3d91f69 --- /dev/null +++ b/listing32.go @@ -0,0 +1,26 @@ +// Code listing 32: https://play.golang.org/p/7uw26q10mbY + +package main + +import ( + "fmt" +) + +func main() { + displayType(42) + displayType(3.14) + displayType("ここでは文字列です") +} + +func displayType(i interface{}) { + switch theType := i.(type) { + case int: + fmt.Printf("%d is an §§§§§§§§§§§integer\n", theType) + case float64: + fmt.Printf("%f is a 64-bit float\n", theType) + case string: + fmt.Printf("%s is a string\n", theType) + default: + fmt.Printf("I don't know what %v is\n", theType) + } +} \ No newline at end of file diff --git a/listing33.go b/listing33.go new file mode 100644 index 0000000..a3b5e6f --- /dev/null +++ b/listing33.go @@ -0,0 +1,13 @@ +// Code listing 33: https://play.golang.org/p/njiry2LJ_qk + +package main + +import ( + "fmt" +) + +func main() { + var anything interface{} = "something" + aString := anything.(string) + fmt.Println(aString) +} \ No newline at end of file diff --git a/listing34.go b/listing34.go new file mode 100644 index 0000000..6ad5314 --- /dev/null +++ b/listing34.go @@ -0,0 +1,13 @@ +// Code listing 34: https://play.golang.org/p/9KT-MkAf3UJ + +package main + +import ( + "fmt" +) + +func main() { + var anything interface{} = "something" + aInt := anything.(int) + fmt.Println(aInt) +} \ No newline at end of file diff --git a/listing35.go b/listing35.go new file mode 100644 index 0000000..57866ea --- /dev/null +++ b/listing35.go @@ -0,0 +1,17 @@ +// Code listing 35: https://play.golang.org/p/lcR_JPZvsSM + +package main + +import ( + "fmt" +) + +func main() { + var anything interface{} = "something" + aInt, ok := anything.(int) + if !ok { + fmt.Println("Cannot turn input into an integer") + } else { + fmt.Println(aInt) + } +} \ No newline at end of file diff --git a/listing4.go b/listing4.go new file mode 100644 index 0000000..b496cd8 --- /dev/null +++ b/listing4.go @@ -0,0 +1,36 @@ +// Code listing 4: https://play.golang.org/p/1FnG0dJfxs8 + +// In Go, _variables_ are explicitly declared and used by +// the compiler to e.g. check type-correctness of function +// calls. + +package main + +import "fmt" + +func main() { + + // `var` declares 1 or more variables. + var a = "initial" + fmt.Println(a) + + // You can declare multiple variables at once. + var b, c int = 1, 2 + fmt.Println(b, c) + + // Go will infer the type of initialized variables. + var d = true + fmt.Println(d) + + // Variables declared without a corresponding + // initialization are _zero-valued_. For example, the + // zero value for an `int` is `0`. + var e int + fmt.Println(e) + + // The `:=` syntax is shorthand for declaring and + // initializing a variable, e.g. for + // `var f string = "short"` in this case. + f := "short" + fmt.Println(f) +} \ No newline at end of file diff --git a/listing5.go b/listing5.go new file mode 100644 index 0000000..5111c2f --- /dev/null +++ b/listing5.go @@ -0,0 +1,35 @@ +// Code listing 5: https://play.golang.org/p/T5sj0eINnp + +// Go supports _constants_ of character, string, boolean, +// and numeric values. + +package main + +import "fmt" +import "math" + +// `const` declares a constant value. +const s string = "constant" + +func main() { + fmt.Println(s) + + // A `const` statement can appear anywhere a `var` + // statement can. + const n = 500000000 + + // Constant expressions perform arithmetic with + // arbitrary precision. + const d = 3e20 / n + fmt.Println(d) + + // A numeric constant has no type until it's given + // one, such as by an explicit cast. + fmt.Println(int64(d)) + + // A number can be given a type by using it in a + // context that requires one, such as a variable + // assignment or function call. For example, here + // `math.Sin` expects a `float64`. + fmt.Println(math.Sin(n)) +} \ No newline at end of file diff --git a/listing6.go b/listing6.go new file mode 100644 index 0000000..48d764e --- /dev/null +++ b/listing6.go @@ -0,0 +1,40 @@ +// Code listing 6: https://play.golang.org/p/KNLLSX4Io_ + +// `for` is Go's only looping construct. Here are +// three basic types of `for` loops. + +package main + +import "fmt" + +func main() { + + // The most basic type, with a single condition. + i := 1 + for i <= 3 { + fmt.Println(i) + i = i + 1 + } + + // A classic initial/condition/after `for` loop. + for j := 7; j <= 9; j++ { + fmt.Println(j) + } + + // `for` without a condition will loop repeatedly + // until you `break` out of the loop or `return` from + // the enclosing function. + for { + fmt.Println("loop") + break + } + + // You can also `continue` to the next iteration of + // the loop. + for n := 0; n <= 5; n++ { + if n%2 == 0 { + continue + } + fmt.Println(n) + } +} \ No newline at end of file diff --git a/listing7.go b/listing7.go new file mode 100644 index 0000000..9c3ecb8 --- /dev/null +++ b/listing7.go @@ -0,0 +1,37 @@ +// Code listing 7: https://play.golang.org/p/g-aqMz0Ivf + +// Branching with `if` and `else` in Go is +// straight-forward. + +package main + +import "fmt" + +func main() { + + // Here's a basic example. + if 7%2 == 0 { + fmt.Println("7 is even") + } else { + fmt.Println("7 is odd") + } + + // You can have an `if` statement without an else. + if 8%4 == 0 { + fmt.Println("8 is divisible by 4") + } + + // A statement can precede conditionals; any variables + // declared in this statement are available in all + // branches. + if num := 9; num < 0 { + fmt.Println(num, "is negative") + } else if num < 10 { + fmt.Println(num, "has 1 digit") + } else { + fmt.Println(num, "has multiple digits") + } +} + +// Note that you don't need parentheses around conditions +// in Go, but that the braces are required. \ No newline at end of file diff --git a/listing8.go b/listing8.go new file mode 100644 index 0000000..6e94f83 --- /dev/null +++ b/listing8.go @@ -0,0 +1,63 @@ +// Code listing 8: https://play.golang.org/p/TJ4Az0KuLfL + +// _Switch statements_ express conditionals across many +// branches. + +package main + +import "fmt" +import "time" + +func main() { + + // Here's a basic `switch`. + i := 2 + fmt.Print("Write ", i, " as ") + switch i { + case 1: + fmt.Println("one") + case 2: + fmt.Println("two") + case 3: + fmt.Println("three") + } + + // You can use commas to separate multiple expressions + // in the same `case` statement. We use the optional + // `default` case in this example as well. + switch time.Now().Weekday() { + case time.Saturday, time.Sunday: + fmt.Println("It's the weekend") + default: + fmt.Println("It's a weekday") + } + + // `switch` without an expression is an alternate way + // to express if/else logic. Here we also show how the + // `case` expressions can be non-constants. + t := time.Now() + switch { + case t.Hour() < 12: + fmt.Println("It's before noon") + default: + fmt.Println("It's after noon") + } + + // A type `switch` compares types instead of values. You + // can use this to discover the type of an interface + // value. In this example, the variable `t` will have the + // type corresponding to its clause. + whatAmI := func(i interface{}) { + switch t := i.(type) { + case bool: + fmt.Println("I'm a bool") + case int: + fmt.Println("I'm an int") + default: + fmt.Printf("Don't know type %T\n", t) + } + } + whatAmI(true) + whatAmI(1) + whatAmI("hey") +} \ No newline at end of file diff --git a/listing9.go b/listing9.go new file mode 100644 index 0000000..4b42c33 --- /dev/null +++ b/listing9.go @@ -0,0 +1,44 @@ +// Code listing 9: https://play.golang.org/p/l-A8eBnwio + +// In Go, an _array_ is a numbered sequence of elements of a +// specific length. + +package main + +import "fmt" + +func main() { + + // Here we create an array `a` that will hold exactly + // 5 `int`s. The type of elements and length are both + // part of the array's type. By default an array is + // zero-valued, which for `int`s means `0`s. + var a [5]int + fmt.Println("emp:", a) + + // We can set a value at an index using the + // `array[index] = value` syntax, and get a value with + // `array[index]`. + a[4] = 100 + fmt.Println("set:", a) + fmt.Println("get:", a[4]) + + // The builtin `len` returns the length of an array. + fmt.Println("len:", len(a)) + + // Use this syntax to declare and initialize an array + // in one line. + b := [5]int{1, 2, 3, 4, 5} + fmt.Println("dcl:", b) + + // Array types are one-dimensional, but you can + // compose types to build multi-dimensional data + // structures. + var twoD [2][3]int + for i := 0; i < 2; i++ { + for j := 0; j < 3; j++ { + twoD[i][j] = i + j + } + } + fmt.Println("2d: ", twoD) +} \ No newline at end of file