天天看点

Go by example Notebooks03 (Recursion, Pointers, Strings and Runes, Structs, Methods)

Recursion

Go support recursive functions.

[[email protected] Day02]$ vim recursion.go
[[email protected] Day02]$ cat recursion.go 
package main

import "fmt"

func fact(n int) int {
    if n == 0 {
        return 1
    }
    return n * fact(n-1)
}

func main(){
    fmt.Println(fact(7))
    var fib func(n int) int


    fib = func(n int) int {
        if n < 2 {
           return n
        }
        return fib(n-1) + fib(n-2)
    }

    fmt.Println(fib(7))
}
[[email protected] Day02]$ go run recursion.go
5040
13
[[email protected] Day02]$ 
           

Pointers

Go supports pointers, allowing you to pass references to values and records within your program.

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.

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.

The 

&i

 syntax gives the memory address of 

i

, i.e. a pointer to 

i

.

Pointers can be printed too.

zeroval

 doesn’t change the 

i

 in 

main

, but 

zeroptr

 does because it has a reference to the memory address for that variable.
[[email protected] Day02]$ vim pointers.go
[[email protected] Day02]$ cat pointers.go
package main

import "fmt"

func zeroval(ival int){
    ival = 0
}

func zeroptr(iptr *int) {
     *iptr = 0
}


func main(){
    i := 1
    fmt.Println("initial:",i)

    zeroval(i)
    fmt.Println("zeroval:",i)

    zeroptr(&i)
    fmt.Println("zeroptr:", i)

    fmt.Println("pointer:", &i)
}

[[email protected] Day02]$ go run pointers.go
initial: 1
zeroval: 1
zeroptr: 0
pointer: 0xc0000b4000
[[email protected] Day02]$ 
           

Strings and Runes

A Go string is a read-only slice of bytes. The language and the standard library treat strings specially - as containers of text encoded in UTF-8. In other languages, strings are made of “characters”. In Go, the concept of a character is called a 

rune

 - it’s an integer that represents a Unicode code point. This Go blog post is a good introduction to the topic.
[[email protected] Day02]$ vim strings_and_runes.go 
[[email protected] Day02]$ cat strings_and_runes.go
package main

import (
     "fmt"
     "unicode/utf8"
)


func main() {
    const s ="สวัสดี"

    fmt.Println("Len:", len(s))


    for i := 0; i <len(s); i++ {
        fmt.Printf("%x ", s[i])
    }
    fmt.Println()

    fmt.Println("Rune count:", utf8.RuneCountInString(s))



    for idx, runeValue := range s {
        fmt.Printf("%#U starts at %d\n", runeValue, idx)
    }
    fmt.Println("\nUsing DecodeRuneInString")
    for i,w := 0,0; i < len(s);i += w {
        runeValue, width := utf8.DecodeRuneInString(s[i:])
        fmt.Printf("%#U start at %d\n", runeValue, i)
        w = width

        examineRune(runeValue)
    }
}

func examineRune(r rune) {
     if  r == 't' {
        fmt.Println("found tee")
     } else if r == 'ส' {
        fmt.Println("found so sua")
     }
}
[[email protected] Day02]$ go run strings_and_runes.go
Len: 18
e0 b8 aa e0 b8 a7 e0 b8 b1 e0 b8 aa e0 b8 94 e0 b8 b5 
Rune count: 6
U+0E2A 'ส' starts at 0
U+0E27 'ว' starts at 3
U+0E31 'ั' starts at 6
U+0E2A 'ส' starts at 9
U+0E14 'ด' starts at 12
U+0E35 'ี' starts at 15

Using DecodeRuneInString
U+0E2A 'ส' start at 0
found so sua
U+0E27 'ว' start at 3
U+0E31 'ั' start at 6
U+0E2A 'ส' start at 9
found so sua
U+0E14 'ด' start at 12
U+0E35 'ี' start at 15
[[email protected] Day02]$ 
           

Structs

Go’s structs are typed collections of fields. They’re useful for grouping data together to form records.
[[email protected] Day02]$ vim structs.go   
[[email protected] Day02]$ cat structs.go   
package main

import "fmt"

type person struct {
    name string
    age int
}

func newPerson(name string) *person {

     p := person{name: name}
     p.age = 42
     return &p
}

func main() {
    fmt.Println(person{"Bob", 20})

    fmt.Println(person{name: "Alice", age:30})

    fmt.Println(person{name: "Fred"})

    fmt.Println(&person{name: "Ann", age: 40})

    fmt.Println(newPerson("Jon"))

    s := person{name: "Sean", age: 50}
    fmt.Println(s.name)

    sp := &s
    fmt.Println(sp.age)

    sp.age = 51
    fmt.Println(sp.age)
}
[[email protected] Day02]$ go run structs.go 
{Bob 20}
{Alice 30}
{Fred 0}
&{Ann 40}
&{Jon 42}
Sean
50
51
[[email protected] Day02]$ 
           

Methods

Go supports methods defined on struct types.
[[email protected] Day02]$ vim methods.go   
[[email protected] Day02]$ cat methods.go   
package main

import "fmt"

type rect struct {
   width, height int
}

func (r *rect) area() int{
    return r.width * r.height
}


func (r *rect) perim() int{
            return 2*r.width + 2*r.height
}

func main(){
    r := rect{width: 10, height: 5}

    fmt.Println("area: ", r.area())
    fmt.Println("perim ", r.perim())

    rp := &r
    fmt.Println("area: ", rp.area())
    fmt.Println("perim:", rp.perim())

}
[[email protected] Day02]$ go run methods.go
area:  50
perim  30
area:  50
perim: 30
[[email protected] Day02]$