在Go语言中。函数能够有多个返回值,这个特性我们已经在之前的样例见过非常多,非常多标准库函数都会返回两个值,一个是期望得到的函数执行结果,另外一个是函数出错时的错误值。

以下的程序是findlinks的改进版本号,它能够自己发起HTTP请求,这样就不必再执行fetch。由于HTTP请求和解析操作都可能会失败。因此findlinks声明了两个返回值:存储链接的列表和错误值。一般而言。HTML的解析器当遇到错误时,会构造出错误的HTML节点,因此解析HTML非常少失败。一旦失败。非常可能是由于IO错误导致的。

gopl.io/ch5/findlinks2

func main() {
for _, url := range os.Args[1:] {
links, err := findLinks(url)
if err != nil {
fmt.Fprintf(os.Stderr, "findlinks2: %v\n", err)
continue
}
for _, link := range links {
fmt.Println(link)
}
}
} // findLinks performs an HTTP GET request for url, parses the
// response as HTML, and extracts and returns the links.
func findLinks(url string) ([]string, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
return nil, fmt.Errorf("getting %s: %s", url, resp.Status)
}
doc, err := html.Parse(resp.Body)
resp.Body.Close()
if err != nil {
return nil, fmt.Errorf("parsing %s as HTML: %v", url, err)
}
return visit(nil, doc), nil
}

findlinks有4个return语句,每个return都返回了一对值。前三个return将返回执行过程中遇到的错误信息,第一个直接返回错误信息,后面两个通过fmt.Errorf输出更加具体的错误信息。

假设findlinks成功结束,最后的return语句将解析获得的链接列表返回给用户。这时的错误信息是nil。

在finallinks中,我们必须确保resp.Body被关闭,然后释放网络资源,甚至当错误发生时。

尽管Go的垃圾回收机制会回收不再使用的内存,可是不要该假定未使用的操作系统资源也会被回收。比如打开的文件、网络连接等,我们应该进行显式的回收!

多返回值函数返回给调用者的是一组值,因此调用者必须显式的将这些值赋给相应的变量(假设这些变量会在后面被使用):

links, err := findLinks(url)

假设某个值不被使用。能够将其分配给空白操作符(blank identifier):

links, _ := findLinks(url) // 这里表示忽略返回的错误

一个函数能够将还有一个有多返回值的函数作为返回值:

func findLinksLog(url string) ([]string, error) {
log.Printf("findLinks %s", url)
return findLinks(url)
}

这个特性在debug时非常方便,我们仅仅须要一条语句就能够输出全部的返回值。以下的代码是等价的:

log.Println(findLinks(url))
links, err := findLinks(url)
log.Println(links, err)

能够使用具名返回值来给返回值赋与明白的意义,尤其在返回值的类型都同样时,就像以下这样:

func Size(rect image.Rectangle) (width, height int)
func Split(path string) (dir, file string)
func HourMinSec(t time.Time) (hour, minute, second int)

尽管良好的命名非常重要。但你也不必为每个返回值都取一个适当的名字。

比方,依照惯例,函数的最后一个bool类型的返回值表示函数是否执行成功,error类型的返回值代表函数的错误信息,对于这些相似的惯例。我们不必思考合适的命名。

假设一个函数的全部返回值都是具名的,那么该函数的return语句能够省略操作数,这样的称之为裸返回(bare return)。

// CountWordsAndImages does an HTTP GET request for the HTML
// document url and returns the number of words and images in it.
func CountWordsAndImages(url string) (words, images int, err error) {
resp, err := http.Get(url)
if err != nil {
return
}
doc, err := html.Parse(resp.Body)
resp.Body.Close()
if err != nil {
err = fmt.Errorf("parsing HTML: %s", err)
return
}
words, images = countWordsAndImages(doc)
return
}
func countWordsAndImages(n *html.Node) (words, images int) { /* ... */ }

这里将依照返回值列表的顺序。返回全部的返回值,在上面的样例中,每个return语句都等价于:

return words, images, err

当一个函数有多处return语句以及很多返回值时,裸返回能够降低代码的反复。可是会让我们的代码难以理解。举个样例,假设你没有细致的审查代码。非常难发现前2处return等价于 return 0,0,err(函数的具名返回值会默认初始化为相应类型的零值)。最后一处return等价于 return words。image,nil。基于以上原因,不宜过度使用裸返回。

练习 5.5: 实现countWordsAndImages。(參考练习4.9怎样分词)

练习 5.6: 改动gopl.io/ch3/surface (§3.2) 中的corner函数。将返回值命名,并使用bare return。

Go语言核心之美 4.3-多返回值的更多相关文章

  1. Go语言核心之美-必读

    Go语言核心之美开篇了!.不管你是新手还是一代高人,在这个系列文章中.总能找到你想要的! 博主是计算机领域资深专家并且是英语专8水平,翻译标准仅仅有三个:精确.专业.不晦涩,为此每篇文章可能都要耗费数 ...

  2. Go语言核心之美 3.2-slice切片

    Slice(切片)是长度可变的元素序列(与之相应,上一节中的数组是不可变的),每一个元素都有同样的类型.slice类型写作[]T.T是元素类型.slice和数组写法非常像,差别在于slice没有指定长 ...

  3. Go语言核心之美 1.5-作用域

    变量的作用域是指程序代码中能够有效使用这个变量的范围. 不要将作用域和生命期混在一起. 作用域是代码中的一块区域,是一个编译期的属性:生命期是程序执行期间变量存活的时间段.在此时间段内,变量能够被程序 ...

  4. Go语言核心之美 1.1-命名篇

    命名篇 1.Go的函数.变量.常量.自己定义类型.包(Package)的命名方式遵循以下规则: 1)首字符能够是随意的Unicode字符或者下划线 2)剩余字符能够是Unicode字符.下划线.数字 ...

  5. go语言基础之函数有多个返回值

    1.函数有多个返回值 示例1: package main //必须有一个main包 import "fmt" //go推荐用法 func myfunc01() (int, int, ...

  6. 013_go语言中的函数多返回值

    代码演示 package main import "fmt" func vals() (int, int) { return 3, 7 } func main() { a, b : ...

  7. JS 语言核心(JavaScript权威指南第六版)(阅读笔记)

    前言: 对于程序员,学习是无止境的,知识淘换非常快,能够快速稳固掌握一门新技术,是一个程序员应该具备的素质.这里将分享本人一点点不成熟的心得. 了解一门语言,了解它的概念非常重要,但是一些优秀的设计思 ...

  8. [程序设计语言]-[核心概念]-02:名字、作用域和约束(Bindings)

    本系列导航 本系列其他文章目录请戳这里. 1.名字.约束时间(Binding Time) 在本篇博文开始前先介绍两个约定:第一个是“对象”,除非在介绍面向对象语言时,本系列中出现的对象均是指任何可以有 ...

  9. 第一章:Javascript语言核心

    本节是javascript语言的一个快速预览,也是本书的第一部分快速预览. 读此书之前,感谢淘宝技术团队对此javascript核心的翻译,感谢弗拉纳根写出此书.感谢你们无私的分享,仅以此笔记献给你们 ...

随机推荐

  1. bionase

    BIONASE BIONASE是一个革命性的新设备,针对过敏性鼻炎(花粉病或枯草热)以及大多其他类型的鼻炎.BIONASE能够缓解以及有效阻止与过敏性鼻炎相关的临床症状,例如:鼻塞,打喷嚏,头疼以及流 ...

  2. 登入爱丽网后台(非JS绕过、非盲打、非IP欺骗)

    后台: http://wed.27.cn/marry/marryadmin/web/login.php 不难猜解到后台管理的相关页面名称(不存在的页面服务器返回404,而存在的页面会直接跳转到上面的登 ...

  3. hdu5297 Y sequence(容斥原理+迭代)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5297 题意:给定整数n和整数r,在1.2.3.4.5.......的序列中删掉能够开2次方的数,3次方的数 ...

  4. [置顶] All about control file in Oracle Database

    --数据库实例启动的三个阶段: NOMOUNT(START):打开初始化参数文件 MOUNT:打开控制文件 OPEN:打开数据文件和日志文件 --控制文件 控制文件的作用:管理数据库的状态和描述数据库 ...

  5. Iocomp控件教程之Pie Chart——饼状图控件

    Pie Chart--饼状图控件(Pie Chart)以饼状图形式显示每一个项目内容所占的百分比比重.在设计时.能够使用属性编辑器加入或者移除项目以及更改属性值.在执行时.使用AddItem,Remo ...

  6. .NET反编译之manager,base.AutoScaleMode修复

    使用反编译软件导出项目时,出现警告:设计器无法处理第X 行的代码:this.AutoScaleMode = AutoScaleMode.Font;方法"InitializeComponent ...

  7. T-SQL 之 存储过程

    当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句.这样就可以提高存储过程的性能. 一.存储过程的概念 存储过程Procedure是一组为了完成特定功能的SQL语句集合,经 ...

  8. RMSE均方根误差学习笔记

    1.均方根误差,它是观测值与真值偏差的平方和观测次数n比值的平方根,在实际测量中,观测次数n总是有限的,真值只能用最可信赖(最佳)值来代替.方根误差对一组测量中的特大或特小误差反映非常敏感,所以,均方 ...

  9. CSS中的margin、border和padding的区别

    aaarticlea/gif;base64,R0lGODlhuQEbAbMAAP8AM8zMzGZmYszMmZmZZkIP/5qE/8zM/wICApmZmf//zP///wAAAAAAAAAAAA

  10. Android Bluetooth模块学习笔记

    一.蓝牙基础知识 1.蓝牙( Bluetooth )是一种无线技术标准,可实现固定设备.移动设备和楼宇个人域网之间的短距离数据交换.蓝牙基于设备低成本的收发器芯片,传输距离近.低功耗. 2.微波频段: ...