Go圣经-学习笔记之函数和错误处理


声明:本文转载自https://my.oschina.net/u/3287304/blog/1555654,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

上一篇 Go圣经-学习笔记之复合类型(三)

下一篇 Go圣经-学习笔记之函数值(二)

函数声明

下面给出函数的四种声明方法:

func add(x int, y int) int { return x+y }  func add(x, y int) (z int) { z = x + y ; return z }  func first(x int, _ int) int { return x } func second(int, int) int { return 0 } 

存在必有其存在的价值,那后两者存在的应用场景在哪里呢?我表示持续懵逼中......, 我写了这个场景,看可以不?

type Interface interface {     Add(int, int) int     Sub(int, int) int     Mul(int, int) int }  type Idem struct{}  func (i Idem) Add(x int, y int) int {     return x + y }  func (i Idem) Sub(int, int) int {     return 0 }  func (i Idem) Mul(x int, _ int) int {     return x * 2 } 

Go语言有一个非常核心的特性:组合,上一篇文章也提及了。如果一个对象是由多个接口、匿名方法集或者对象的自身行为集构成。如果这个对象觉得有些行为是它忽略或者不想要的,这时候就可以采用上述的后两者方法去声明方法,但是这个是方法的声明,不是函数的声明。能想到的就这么多,其他我就不知道了。

函数递归

对于递归的运用,我们通过一个url,获取网页数据流,然后通过html标准库解析数据,获取各个标签元素节点。

说明: 运用html标准库解析完数据流,得到的是一个多叉树的元素节点,包括:文档节点、文本节点、元素标签节点、评论节点、注脚节点和错误节点。由这六个节点构成一颗多叉树

DEMO实例代码片段

********************************************************************** // html标准库相关说明: type Node struct {     Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node      Type      NodeType     DataAtom  atom.Atom     Data      string     Namespace string     Attr      []Attribute } func Parse(r io.Reader) (*Node, error) **********************************************************************   var (     purl = flag.String("url", "https://www.golang.org", "website url") )  func main() {     var (         resp *http.Response         err  error         node *html.Node     )     flag.Parse()     if resp, err = http.Get(*purl); err != nil {         log.Fatal(err.Error())         return     }     node, err = html.Parse(resp.Body)     if err != nil {         log.Fatal(err.Error())         return     }     resp.Body.Close()     // 我们采用多叉树的深度遍历算法,并打印所有节点元素url。     for _, link := range visit(nil, node) {         fmt.Println(link)     } }  func visit(links []string, node *html.Node) []string {     if node.Type == html.ElementNode && node.Data == "a" {         for _, attr := range node.Attr {             links = append(links, attr.Val)         }     }     for child := node.FirstChild; child != nil; child = child.NextSibling {         links = visit(links, child)     }     return links } 

递归元素的存储是由stack数据结构存储的。C++等主流语言的stack栈是由固定大小的,如果过多递归会导致栈内存溢出。但是Go语言的栈是动态分配的,按需分配,一般不需要考虑stack溢出安全问题,但是还是要多多尽量节约内存

大家吐槽比较多的函数返回error

在Go语言标准库使用过程中,几乎每个函数或者方法返回参数的最后一个类型都是error,类似:

func xx(sss type, ...) (xxx type, ..., err error) 

比如,我们经常这样做:

*************************************************** // ioutil标准库: func ReadAll(r io.Reader) (data []byte, err error) ***************************************************  if bts, err := ioutil.ReadAll(r); err !=nil{     err = errors.Wrap(err, "xxxxx")     return } 

大家觉得如果调用的每个方法或者函数,都要处理error,大家比较崩溃。Go语言官方是这样解释返回error的设计的:

由于对于某个应该在控制流程中处理的错误而言,将这个错误以异常的形式抛出会混乱对错误的描述,这通常会导致一些糟糕的后果。当某个程序错误被当作异常处理后,这个错误会将堆栈信息返回给用户,这些信息复杂且无用,无法帮助定位错误

所以Go语言想通过控制流if,return语句处理异常,这使得编程人员能更多的关注错误处理。

在这里给大家提供用于error追踪的包,很好用。github地址:errors

// 我一般这样使用 // 业务逻辑层 func AddSaleOrder(so *SaleOrder, o *orm.Ormer) (retCode int, err error) {     if _, err = (*o).Insert(so); err != nil {         err = errors.Wrap(err, "AddSaleOrder")         retCode = consts.DB__INSERT_ERROR         return     }     return }  // 控制层 func (s *SaleOrderController) AddSaleOrder() {     var so *models.SaleOrder     ......     if retCode, err = models.AddSaleOrder(so, nil); err !=nil {         Logger.Error(err.Error()) // 这里的err.Error() 会返回整个的error跟踪调用链         s.Data["json"] = map[string]interface{}{             "err_code": retCode,             "err_msg": errors.Cause(err).Error(), // 这个返回err调用链中产生错误最初始的形态。         }         s.ServeJSON()         return     }     s.Data["json"] = map[string]interface{}{         "err_code": 0,         "err_msg": "",     }     s.ServeJSON()     return } 

这样做的好处是:我们服务端既可以记录错误产生的整个调用链跟踪,同时,前端也返回了关键错误。屏蔽了不想要用户看到的信息。

本文发表于2017年10月25日 08:34
(c)注:本文转载自https://my.oschina.net/u/3287304/blog/1555654,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2116 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1