美文网首页Go笔记
学习golang过程中遇到的坑

学习golang过程中遇到的坑

作者: 土豆_大大 | 来源:发表于2017-06-21 14:11 被阅读164次

    defer与panic

    func中defer是队列形式存储的,panic执行后面的defer不加入队列

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        defer_call()
    }
    
    func defer_call() {
        defer func() { fmt.Println("打印前") }()
        defer func() { fmt.Println("打印中") }()
        defer func() { fmt.Println("打印后") }()
    
        panic("触发异常")
    }
    

    range 重用地址

    range 循环,会重用地址,也就是说,for _, stu := range stus 中的 stu 总是在同一个地址

    type student struct {
        Name string
        Age  int
    }
    
    func pase_student() {
        m := make(map[string]*student)
        stus := []student{
            {Name: "zhou", Age: 24},
            {Name: "li", Age: 23},
            {Name: "wang", Age: 22},
        }
        for _, stu := range stus {
            m[stu.Name] = &stu
        }
    }
    

    select里面的case条件是随机性的

    func main() {
        runtime.GOMAXPROCS(1)
        int_chan := make(chan int, 1)
        string_chan := make(chan string, 1)
        int_chan <- 1
        string_chan <- "hello"
        select {
        case value := <-int_chan:
            fmt.Println(value)
        case value := <-string_chan:
            panic(value)
        }
    }
    

    defer的匿名函数参数是拷贝地址的(如果是指针就是最后指针的值),而函数里面的函数是优先在main函数体中执行的

    func calc(index string, a, b int) int {
        ret := a + b
        fmt.Println(index, a, b, ret)
        return ret
    }
    
    func main() {
        a := 1
        b := 2
        defer calc("1", a, calc("10", a, b))
        a = 0
        defer calc("2", a, calc("20", a, b))
        b = 1
    }
    

    append 是往后面追加数据

    func main() {
        s := make([]int, 5)
        s = append(s, 1, 2, 3)
        fmt.Println(s) // 输出 0 0 0 0 0 1 2 3
    }
    

    interface接口 不通的对象类型对应了不同的方法集,从而影响interface接口实现的对象

    Methods Receivers         Values
    -----------------------------------------------
    (t T)                     T and *T
    
    (t *T)                    *T 
    
    package main
    
    import (
        "fmt"
    )
    
    type People interface {
        Speak(string) string
    }
    
    type Stduent struct{}
    
    func (stu *Stduent) Speak(think string) (talk string) {
        if think == "bitch" {
            talk = "You are a good boy"
        } else {
            talk = "hi"
        }
        return
    }
    
    func main() {
        var peo People = Stduent{}
        think := "bitch"
        fmt.Println(peo.Speak(think)) //指针类型的receiver 方法实现接口时,只有指针类型的对象实现了该接口 需要改成var peo People = &Stduent{}
    }
    

    nil类型的type vaule都是nil 而interface的nil数据结构不一样

    package main
    
    import (
        "fmt"
    )
    
    type People interface {
        Show()
    }
    
    type Student struct{}
    
    func (stu *Student) Show() {
    
    }
    
    func live() People {
        var stu *Student
        return stu
    }
    
    func main() {
        if live() == nil {
            fmt.Println("AAAAAAA")
        } else {
            fmt.Println("BBBBBBB")  //输出的时BBB
        }
    }
    

    append函数实现原理

    1. 如果nums的cap够用,则会直接在nums指向的数组后面追加元素,返回的slice和原来的slice是同一个对象。显然,这种情况下原来的slice的值会发生变化! 
    2. 如果nums的cap不够用(上述代码就是这种情况),则会重新分配一个数组空间用来存储数据,并且返回指向新数组的slice。这时候原来的slice指向的数组并没有发生任何变化! 
    3. 当然,在任何情况下,返回的结果都是追加之后的slice,这一点没有问题!
    
    package main
    
    import (
        "fmt"
    )
    
    func main() {
        x := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
        fmt.Println(append(x[:5], x[6:]...), x) //x:1 2 3 4 5 7 8 9 10 10
    }
    
    

    相关文章

      网友评论

        本文标题:学习golang过程中遇到的坑

        本文链接:https://www.haomeiwen.com/subject/owazqxtx.html