跳转至

Golang tips and traps

未使用的变量

package main

var gvar int //not an error

func main() {  
    two := 2      //error, unused variable
    var three int //error, even though it's assigned 3 on the next line
    three = 3
    _=two

}

包导入

package main
import . "fmt"
func main() {
    Println()
}

init

package main
import . "fmt"

const Hello="hello"
var world string

func init(){
    world = "world"
    Println(Hello, world)
}

func main(){}

nil pointer

    var m *int //nil int pointer
    var n map[string]int //nil map[string]int reference
    *m=4    //error
    //m=new(int)

bitwise Operator

func main() {
    a:=2
    fmt.Println(^a)
    //~ XOR
    //优先级
}

map , slice is reference

func main() {
    s:=make([][]int,0)
    d:=[]int{6,6,6}
    s=append(s, d)
    s=append(s, d)
    d[0]=7
    fmt.Println(s)
}s

connect multi slice

package concat

func concatCopyPreAllocate(slices [][]byte) []byte {
    var totalLen int
    for _, s := range slices {
        totalLen += len(s)
    }
    tmp := make([]byte, totalLen)
    var i int
    for _, s := range slices {
        i += copy(tmp[i:], s)
    }
    return tmp
}

func concatAppend(slices [][]byte) []byte {
    var tmp []byte
    for _, s := range slices {
        tmp = append(tmp, s...)
    }
    return tmp
}

rune

func main() {
    data2 := "青云"
    fmt.Println(len([]rune(data2)))
}

func main() {
    data := "é"//two codpoints ,combining character
    fmt.Println(len(data)) //prints: 3
    fmt.Println(len([]rune(data)))//print:2
}

composistion

package main

import "fmt"

type Person interface {
    Introduce()
}
type Student struct {
    name string
}
type Teacher struct {
    name string
}
func (s Student) Introduce(){
    fmt.Println("Hi, I'm ",s.name)
}
func (s *Teacher) Introduce(){
    fmt.Println("Hi, I'm teacher",s.name)
}
type School struct {
    Person
    number int
}
func main() {

    zhichen:=School{
        Student{"wzc"},
        123,
    }
    zhichen.Introduce()
}

struct compare

只有struct中数据都可以比较时,才能用 ==

type data struct {  
    num int
    fp float32
    complex complex64
    str string
    char rune
    yes bool
    events <-chan string
    handler interface{}
    ref *byte
    raw [10]byte //array
}

func main() {  
    v1 := data{}
    v2 := data{}
    fmt.Println("v1 == v2:",v1 == v2) //prints: v1 == v2: true
}

DeepEqual() & bytes.Equal

package main

import (
    "fmt"
    "bytes"
    "reflect"
)

func main() {
    //nil and empty
    var b1 []byte
    b2 := []byte{}
    fmt.Println("b1 == b2:", bytes.Equal(b1, b2)) //print: b1 == b2: true
    fmt.Println("b1 == b2",reflect.DeepEqual(b1,b2))//print: b1 == b2:false
}
package main

import (
    "fmt"
    "reflect"
    "encoding/json"
)

func main() {
    var str string = "one"
    var in interface{} = "one"
    fmt.Println("str == in:",str == in,reflect.DeepEqual(str, in))
    //prints: str == in: true true

    v1 := []string{"one","two"}
    v2 := []interface{}{"one","two"}
    fmt.Println("v1 == v2:",reflect.DeepEqual(v1, v2))
    //prints: v1 == v2: false (not ok)

    data := map[string]interface{}{
        "code": 200,
        "value": []string{"one","two"},
    }
    encoded, _ := json.Marshal(data)
    var decoded map[string]interface{}
    json.Unmarshal(encoded, &decoded)
    fmt.Println("data == decoded:",reflect.DeepEqual(data, decoded))
    //prints: data == decoded: false (not ok)
}

goroutines sync group

func main() {
    var wg sync.WaitGroup
    workerCount := 2

    for i := 0; i < workerCount; i++ {
        wg.Add(1)
        go doit(i,&wg)
    }
    wg.Wait()
    fmt.Println("all done!")
}

func doit(workerId int,group *sync.WaitGroup) {//must pointer
    defer group.Done()
    fmt.Printf("[%v] is running\n",workerId)
    time.Sleep(3 * time.Second)
    fmt.Printf("[%v] is done\n",workerId)
}

chan buffer size

func main() {
    a:=make(chan bool,1)
    a<-true
    var vg sync.WaitGroup
    vg.Add(1)
    go func() {
        defer vg.Done()
        log.Println(<-a)

        }()
        vg.Wait()

}

nil channel & closed channel

 //close a nil chan will panic
 //send or read nil chan will lock
 //sent a closed chan will panic
 //you can read close chan
 //a closed chan never blocked
func WaitMany(a, b chan bool) {
        var aclosed, bclosed bool
        for !aclosed || !bclosed {
                select {
                case <-a:
                        aclosed = true
                case <-b:
                        bclosed = true
                }
        }
        //do something
}

package main

import (
        "fmt"
        "time"
)

func WaitMany(a, b chan bool) { 
        for a != nil || b != nil {
                select {
                case <-a:
                        a = nil
                case <-b:
                        b = nil
                }
        }
}

func main() {
        a, b := make(chan bool), make(chan bool)
        t0 := time.Now()
        go func() {
                close(a)
                close(b)
        }()
        WaitMany(a, b)
        fmt.Printf("waited %v for WaitMany\n", time.Since(t0))
}
https://dave.cheney.net/2013/04/30/curious-channels
package main

import (
    "fmt"
    "time"
)

func main() {
    a := make(chan bool)
    go sentTrue(a)//no buffer will be sending...
    time.Sleep(20*time.Millisecond)
    close(a)
    fmt.Println("channel has closed")
    fmt.Println(<-a)

}

func sentTrue(a chan bool) {
    a <- true

}

variables in loop

func main() {
    data := []string{"one", "two", "three"}
    for _, v := range data {
        go func() {
            fmt.Println(v)

        }()
    }

    time.Sleep(3 * time.Second)
}

break loop

func main() {  
    loop:
        for {
            switch {
            case true:
                fmt.Println("breaking out...")
                break loop
            }
        }

    fmt.Println("out!")
}

close http body

func main() {  
    resp, err := http.Get("https://www.qingcloud.com/")
    if resp != nil {
        defer resp.Body.Close()
    }
    if err != nil {
        fmt.Println(err)
        return
    }
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(string(body))
}

defer call

package main

import "fmt"

func main() {  
    var i int = 1

    defer fmt.Println("result =>",func() int { return i * 2 }())
    i++
    //prints: result => 2 (if you expected 4)
}

map not addressable

type data struct {
    name string
}

func (p *data) print() {
    fmt.Println("name:",p.name)
}


func main() {
    d1 := data{"one"}
    d1.print() //ok
    m := map[string]data {"3":data{"three"}}
    m["3"].print()
}
package main

type data struct {
    name string
}
//how to set value
func main() {
    m := map[string]data {"x":{"one"}}
    m["x"].name = "two" //error
    r := m["x"]
    r.name = "two"
    m["x"] = r
    fmt.Printf("%v",m) //prints: map[x:{two}]
}
package main

type data struct {
    name string
}

func main() {
    m := map[string]*data {"x":{"one"}}
    m["z"].name = "what?" //???
}

"nil" Interfaces and "nil" Interfaces Values

package main

import "fmt"

func main() {
    var data *byte
    var in interface{}

    fmt.Println(data,data == nil) //prints: <nil> true
    fmt.Println(in,in == nil)     //prints: <nil> true
    in = data
    fmt.Println(in,in == nil)     //prints: <nil> false
}
package main

import "fmt"

func retnil()interface{}{
    var result *struct{}=nil
    return result
}
func main() {
    fmt.Println(nil)
}

评论