博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Golang的一些学习
阅读量:7098 次
发布时间:2019-06-28

本文共 3509 字,大约阅读时间需要 11 分钟。

在 Go 中使用命名返回变量捕获 panic

在下面代码中,如果pressButton发生panic,那么不会执行到return err,导致返回的err是nil。

func doStuff() error {          var err error        // If there is a panic we need to recover in a deferred func        defer func() {            if r := recover(); r != nil {                err = errors.New("the meeseeks went crazy!")            }        }()            pressButton()        return err    }

可以使用命名返回变量解决,即使我们从未触碰到 doStuff 函数的末尾的返回语句,也会立刻返回这个 err 变量。

func doStuff() (err error) {          // If there is a panic we need to recover in a deferred func        defer func() {            if r := recover(); r != nil {                err = errors.New("the meeseeks went crazy!")            }        }()            pressButton()        return err    }

重新切片(slice)

从 slice 中重新切出新 slice 时,新 slice 会引用原 slice 的底层数组,将导致难以预料的内存使用。可以通过拷贝临时 slice 的数据,而不是重新切片来解决:

func get() (res []byte) {        raw := make([]byte, 10000)        fmt.Println(len(raw), cap(raw), &raw[0])    // 10000 10000 0xc420080000        res = make([]byte, 3)        copy(res, raw[:3])        return    }    func test() {        slice := a[2:3:4]        //可以利用第三个参数控制容量        //如果设置容量和长度相同,可以append时新创建底层数组,不影响原有的    }

类型声明与方法

从一个现有的非 interface 类型创建新类型时,并不会继承原有的方法:

// 定义 Mutex 的自定义类型    type myMutex sync.Mutex        func main() {        var mtx myMutex        mtx.Lock()        mtx.UnLock()    }    //mtx.Lock undefined (type myMutex has no field or method Lock)…

如果你需要使用原类型的方法,可将原类型以匿名字段的形式嵌到你定义的新 struct 中:

// 类型以字段形式直接嵌入    type myLocker struct {        sync.Mutex    }        func main() {        var locker myLocker        locker.Lock()        locker.Unlock()    }

for + 闭包函数

type field struct {        name string    }        func (p *field) print() {        fmt.Println(p.name)    }        // 错误示例    func main() {        data := []field{
{"one"}, {"two"}, {"three"}} for _, v := range data { go v.print() } time.Sleep(3 * time.Second) // 输出 three three three } // 正确示例 func main() { data := []field{
{"one"}, {"two"}, {"three"}} for _, v := range data { v := v go v.print() } time.Sleep(3 * time.Second) // 输出 one two three } // 正确示例 func main() { data := []*field{
{"one"}, {"two"}, {"three"}} for _, v := range data { // 此时迭代值 v 是三个元素值的地址,每次 v 指向的值不同 go v.print() } time.Sleep(3 * time.Second) // 输出 one two three }

defer函数参数

对 defer 延迟执行的函数,它的参数会在声明时候就会求出具体值,而不是在执行时才求值:

// 在 defer 函数中参数会提前求值    func main() {        var i = 1        defer fmt.Println("result: ", func() int { return i * 2 }())        i++    }

select default

如果有default子句,case不满足条件时执行该语句。

如果没有default字句,select将阻塞,直到某个case可以运行;Go不会重新对channel或值进行求值。

缓冲通道中,刚好相反,由于元素值的传递是异步的,所以发送操作在成功向通道发送元素值之后就会立即结束(它不会关心是否有接收操作)。

如果使用非缓冲,ret值必须被接收。如果此函数等待超时直接返回nil,会导致Ret这个Chan在模块那边写不进去堵死。

func (m *friendModule) Gift*****(cmd GiftCmd) *GiftRet {        ctx, cancel := context.WithTimeout(context.Background(), util.ASyncCmdTimeOut)        defer cancel()        cmd.Ret = make(chan GiftRet, 1) ##非缓冲bug        select {        case m.GiftChan <- cmd:        case <-ctx.Done():            logs.Error("friend moduel gift cmdChan is full")        }        select {        case ret := <-cmd.Ret:            return &ret        case <-ctx.Done():            logs.Error("friend moduel gift cmdChan apply <-retChan timeout")            return nil        }    }

转载于:https://www.cnblogs.com/Przz/p/9519112.html

你可能感兴趣的文章
Linux操作系统中重定向命令行的技巧总结
查看>>
不仅仅是远程桌面,微软“桌面云”技术概览 (1)远程桌面协议 RDP 8.0
查看>>
校园网应用分析
查看>>
Python的面向对象、Class 概念与使用
查看>>
从传统运维到云运维演进历程之软件定义存储(三)下
查看>>
技术分享连载(二十)
查看>>
Java -- JDBC 学习--调用函数&存储过程
查看>>
关于PC或笔记本的一些安全设定
查看>>
DNS Security Tips
查看>>
吴家坟女子专修学院郭杜校区计算机分院的学年总结
查看>>
OpenCV实现手写体数字训练与识别
查看>>
Linux IP、DNS、Route配置
查看>>
Windows Server 2012 R2 NIC Teaming
查看>>
文件系统一些概念【更新完毕】
查看>>
Eclipse的一个重要功能
查看>>
HCE Benchmark
查看>>
设置基于Windows策略的QOS
查看>>
配置Linux日志文件
查看>>
黑客攻防专题三:名词介绍
查看>>
吐槽一下现在的代码编辑器
查看>>