go by example part 2
This commit is contained in:
parent
afe165089d
commit
c1b7c64da2
38
5-go-by-example/11-range.go
Normal file
38
5-go-by-example/11-range.go
Normal file
@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// range iterates over elements in a variety of data structures
|
||||
func main() {
|
||||
|
||||
// use range to sum the numbers in a slice
|
||||
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
|
||||
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 iterate over keys of a map
|
||||
for k := range kvs {
|
||||
fmt.Println("key:", k)
|
||||
}
|
||||
|
||||
// range on strings iterates over Unicode code points
|
||||
for i, c := range "go" {
|
||||
fmt.Println(i, c)
|
||||
}
|
||||
}
|
24
5-go-by-example/12-function.go
Normal file
24
5-go-by-example/12-function.go
Normal file
@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// function that takes two ints and returns their sum as an int
|
||||
// Go requires explicit returns
|
||||
func plus(a int, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
// multiple consecutive parameters of the same type,
|
||||
// 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
|
||||
res := plus(1, 2)
|
||||
fmt.Println("1+2 =", res)
|
||||
|
||||
res = plusPlus(1, 2, 3)
|
||||
fmt.Println("1+2+3 =", res)
|
||||
}
|
20
5-go-by-example/13-muliple-return-value.go
Normal file
20
5-go-by-example/13-muliple-return-value.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// (int, int) in this function signature shows that the function returns 2 ints
|
||||
func vals() (int, int) {
|
||||
return 3, 7
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// use the 2 different return values
|
||||
a, b := vals()
|
||||
fmt.Println(a)
|
||||
fmt.Println(b)
|
||||
|
||||
// use the blank identifier _
|
||||
_, c := vals()
|
||||
fmt.Println(c)
|
||||
}
|
26
5-go-by-example/14-variadic-function.go
Normal file
26
5-go-by-example/14-variadic-function.go
Normal file
@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Variadic functions can be called with any number of trailing arguments
|
||||
|
||||
// take an arbitrary number of ints 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
|
||||
sum(1, 2)
|
||||
sum(1, 2, 3)
|
||||
|
||||
// apply multiple args to a variadic function
|
||||
nums := []int{1, 2, 3, 4}
|
||||
sum(nums...)
|
||||
}
|
29
5-go-by-example/15-closures.go
Normal file
29
5-go-by-example/15-closures.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Go supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it.
|
||||
|
||||
// intSeq returns another function, which is defined 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() {
|
||||
// call intSeq, assigning the result (a function) to nextInt
|
||||
nextInt := intSeq()
|
||||
|
||||
// see the effect of the closure
|
||||
fmt.Println(nextInt())
|
||||
fmt.Println(nextInt())
|
||||
fmt.Println(nextInt())
|
||||
|
||||
// confirm that the state is unique to that particular function
|
||||
newInts := intSeq()
|
||||
fmt.Println(newInts())
|
||||
}
|
29
5-go-by-example/16-recursion.go
Normal file
29
5-go-by-example/16-recursion.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// 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))
|
||||
|
||||
// Closures can also be recursive, but this requires the closure to be declared with a typed var explicitly before it’s defined
|
||||
var fib func(n int) int
|
||||
|
||||
// Go knows which function to call with fib as it is defined previously in main
|
||||
fib = func(n int) int {
|
||||
if n < 2 {
|
||||
return n
|
||||
}
|
||||
return fib(n-1) + fib(n-2)
|
||||
|
||||
}
|
||||
|
||||
fmt.Println(fib(7))
|
||||
}
|
33
5-go-by-example/17-pointers.go
Normal file
33
5-go-by-example/17-pointers.go
Normal file
@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Go supports pointers, allowing you to pass references to values and records within your program
|
||||
|
||||
// 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 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)
|
||||
|
||||
// &i syntax gives the memory address
|
||||
zeroptr(&i)
|
||||
fmt.Println("zeroptr:", i)
|
||||
|
||||
// Pointers can be printed
|
||||
fmt.Println("pointer:", &i)
|
||||
}
|
49
5-go-by-example/18-structs.go
Normal file
49
5-go-by-example/18-structs.go
Normal file
@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Go’s structs are typed collections of fields. They’re useful for grouping data together to form records.
|
||||
|
||||
// this person struct type has name and age fields
|
||||
type person struct {
|
||||
name string
|
||||
age int
|
||||
}
|
||||
|
||||
// newPerson constructs a new person struct with the given name
|
||||
// safely return a pointer to local variable as a local variable will survive the scope of the function
|
||||
func newPerson(name string) *person {
|
||||
p := person{name: name}
|
||||
p.age = 42
|
||||
return &p
|
||||
}
|
||||
|
||||
func main() {
|
||||
// create a new struct
|
||||
fmt.Println(person{"Bob", 20})
|
||||
|
||||
// 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"})
|
||||
|
||||
// & prefix yields a pointer to the struct
|
||||
fmt.Println(&person{name: "Ann", age: 40})
|
||||
|
||||
// encapsulate new struct creation in constructor functions (ideomatic)
|
||||
fmt.Println(newPerson("Jon"))
|
||||
|
||||
// access struct fields with a dot
|
||||
s := person{name: "Sean", age: 50}
|
||||
fmt.Println(s.name)
|
||||
|
||||
// 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)
|
||||
}
|
32
5-go-by-example/19-methods.go
Normal file
32
5-go-by-example/19-methods.go
Normal file
@ -0,0 +1,32 @@
|
||||
// methods defined on struct types
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type rect struct {
|
||||
width, height int
|
||||
}
|
||||
|
||||
// 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
|
||||
func (r rect) perim() int {
|
||||
return 2*r.width + 2*r.height
|
||||
}
|
||||
|
||||
func main() {
|
||||
r := rect{width: 10, height: 5}
|
||||
|
||||
// call 2 methods defined for the struct
|
||||
fmt.Println("area: ", r.area())
|
||||
fmt.Println("perim:", r.perim())
|
||||
|
||||
// Go automatically handles conversion between values and pointers for method calls
|
||||
rp := &r
|
||||
fmt.Println("area: ", rp.area())
|
||||
fmt.Println("perim:", rp.perim())
|
||||
}
|
55
5-go-by-example/20-interfaces.go
Normal file
55
5-go-by-example/20-interfaces.go
Normal file
@ -0,0 +1,55 @@
|
||||
// Interfaces are named collections of method signatures
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// basic interface for geometric shapes
|
||||
type geometry interface {
|
||||
area() float64
|
||||
perim() float64
|
||||
}
|
||||
|
||||
// implement interface on rect and circle types
|
||||
type rect struct {
|
||||
width, height float64
|
||||
}
|
||||
type circle struct {
|
||||
radius float64
|
||||
}
|
||||
|
||||
// implement geometry on rects
|
||||
func (r rect) area() float64 {
|
||||
return r.width * r.height
|
||||
}
|
||||
func (r rect) perim() float64 {
|
||||
return 2*r.width + 2*r.height
|
||||
}
|
||||
|
||||
// implementation for circles
|
||||
func (c circle) area() float64 {
|
||||
return math.Pi * c.radius * c.radius
|
||||
}
|
||||
func (c circle) perim() float64 {
|
||||
return 2 * math.Pi * c.radius
|
||||
}
|
||||
|
||||
// call methods that are in the named interface
|
||||
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}
|
||||
|
||||
// circle and rect struct types both implement the geometry interface
|
||||
// use instances of these structs as arguments to measure
|
||||
measure(r)
|
||||
measure(c)
|
||||
}
|
Loading…
Reference in New Issue
Block a user