go by example part 2

This commit is contained in:
WieErWill 2022-01-01 19:47:24 +01:00
parent afe165089d
commit c1b7c64da2
10 changed files with 335 additions and 0 deletions

View 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)
}
}

View 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)
}

View 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)
}

View 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...)
}

View 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())
}

View 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 its 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))
}

View 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)
}

View File

@ -0,0 +1,49 @@
package main
import "fmt"
// Gos structs are typed collections of fields. Theyre 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)
}

View 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())
}

View 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)
}