Go语言核心之美 4.3-多返回值
2018-04-06 08:44
417 查看
在Go语言中。函数能够有多个返回值,这个特性我们已经在之前的样例见过非常多,非常多标准库函数都会返回两个值,一个是期望得到的函数执行结果,另外一个是函数出错时的错误值。
以下的程序是findlinks的改进版本号,它能够自己发起HTTP请求,这样就不必再执行fetch。由于HTTP请求和解析操作都可能会失败。因此findlinks声明了两个返回值:存储链接的列表和错误值。一般而言。HTML的解析器当遇到错误时,会构造出错误的HTML节点,因此解析HTML非常少失败。一旦失败。非常可能是由于IO错误导致的。
gopl.io/ch5/findlinks2
假设findlinks成功结束,最后的return语句将解析获得的链接列表返回给用户。这时的错误信息是nil。
在finallinks中,我们必须确保resp.Body被关闭,然后释放网络资源,甚至当错误发生时。
尽管Go的垃圾回收机制会回收不再使用的内存,可是不要该假定未使用的操作系统资源也会被回收。比如打开的文件、网络连接等,我们应该进行显式的回收!
多返回值函数返回给调用者的是一组值,因此调用者必须显式的将这些值赋给相应的变量(假设这些变量会在后面被使用):
比方,依照惯例,函数的最后一个bool类型的返回值表示函数是否执行成功,error类型的返回值代表函数的错误信息,对于这些相似的惯例。我们不必思考合适的命名。
假设一个函数的全部返回值都是具名的,那么该函数的return语句能够省略操作数,这样的称之为裸返回(bare return)。
练习 5.5: 实现countWordsAndImages。(參考练习4.9怎样分词)
练习 5.6: 改动gopl.io/ch3/surface (§3.2) 中的corner函数。将返回值命名,并使用bare return。
以下的程序是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-多返回值
- Go语言核心之美 2.4-布尔值
- Go语言核心之美 3.4-Struct结构体
- Go语言核心之美 3.4-Struct结构体
- Go语言服务器开发之客户端向服务器发送数据并接收返回数据的方法
- Go语言核心之美 2.6-常量
- Go语言核心之美 1.3-赋值及类型声明篇
- Go语言核心之美 2.5-字符串
- Go语言核心之美 1.2-变量及声明篇
- Go语言示例-函数返回多个值
- Go语言核心之美 1.1-命名篇
- Go语言核心之美 2.2-浮点数
- Go语言核心之美 3.2-slice切片
- Go语言核心之美 1.5-作用域
- Go语言核心之美 3.5-JSON
- go语言form表单提交以及后台如何接收并返回做一个简单的解释
- Go语言核心之美 3.3-Map
- go语言学习-多重返回和匿名变量
- Go语言核心之美 3.6-template模版
- Go语言学习记录之一(返回指针与返回值的区别)