go语言笔记——多值函数,本质上和nodejs的回调很像,不过nodejs是回调的第一个参数是err,而golang里是第二个!

简介:

5.2 测试多返回值函数的错误

Go 语言的函数经常使用两个返回值来表示执行是否成功:返回某个值以及 true 表示成功;返回零值(或 nil)和 false 表示失败(第 4.4 节)。当不使用 true 或 false 的时候,也可以使用一个 error 类型的变量来代替作为第二个返回值:成功执行的话,error 的值为 nil,否则就会包含相应的错误信息(Go 语言中的错误类型为 error: var err error,我们将会在第 13 章进行更多地讨论)。这样一来,就很明显需要用一个 if 语句来测试执行结果;由于其符号的原因,这样的形式又称之为 comma,ok 模式(pattern)。

在第 4.7 节的程序 string_conversion.go 中,函数 strconv.Atoi 的作用是将一个字符串转换为一个整数。之前我们忽略了相关的错误检查:

anInt, _ = strconv.Atoi(origStr)

如果 origStr 不能被转换为整数,anInt 的值会变成 0 而 _ 无视了错误,程序会继续运行。

这样做是非常不好的:程序应该在最接近的位置检查所有相关的错误,至少需要暗示用户有错误发生并对函数进行返回,甚至中断程序。

我们在第二个版本中对代码进行了改进:

示例 1:

示例 5.3 string_conversion2.go

package main

import (
	"fmt"
	"strconv" ) func main() { var orig string = "ABC" // var an int var newS string // var err error fmt.Printf("The size of ints is: %d\n", strconv.IntSize) // anInt, err = strconv.Atoi(origStr) an, err := strconv.Atoi(orig) if err != nil { fmt.Printf("orig %s is not an integer - exiting with error\n", orig) return } fmt.Printf("The integer is %d\n", an) an = an + 5 newS = strconv.Itoa(an) fmt.Printf("The new string is: %s\n", newS) }

这是测试 err 变量是否包含一个真正的错误(if err != nil)的习惯用法。如果确实存在错误,则会打印相应的错误信息然后通过 return 提前结束函数的执行。我们还可以使用携带返回值的 return 形式,例如 return err。这样一来,函数的调用者就可以检查函数执行过程中是否存在错误了。

习惯用法

value, err := pack1.Function1(param1)
if err != nil { fmt.Printf("An error occured in pack1.Function1 with parameter %v", param1) return err } // 未发生错误,继续执行:

由于本例的函数调用者属于 main 函数,所以程序会直接停止运行。

如果我们想要在错误发生的同时终止程序的运行,我们可以使用 os 包的 Exit 函数:

习惯用法

if err != nil {
	fmt.Printf("Program stopping with error %v", err) os.Exit(1) }

(此处的退出代码 1 可以使用外部脚本获取到)

有时候,你会发现这种习惯用法被连续重复地使用在某段代码中。

当没有错误发生时,代码继续运行就是唯一要做的事情,所以 if 语句块后面不需要使用 else 分支。

示例 2:我们尝试通过 os.Open 方法打开一个名为 name 的只读文件:

f, err := os.Open(name)
if err != nil { return err } doSomething(f) // 当没有错误发生时,文件对象被传入到某个函数中 doSomething

练习 5.1 尝试改写 string_conversion2.go 中的代码,要求使用 := 方法来对 err 进行赋值,哪些地方可以被修改?

示例 3:可以将错误的获取放置在 if 语句的初始化部分:

习惯用法

if err := file.Chmod(0664); err != nil { fmt.Println(err) return err }

示例 4:或者将 ok-pattern 的获取放置在 if 语句的初始化部分,然后进行判断:

习惯用法

if value, ok := readData(); ok {
…
}

注意事项

如果您像下面一样,没有为多返回值的函数准备足够的变量来存放结果:

func mySqrt(f float64) (v float64, ok bool) { if f < 0 { return } // error case return math.Sqrt(f),true } func main() { t := mySqrt(25.0) fmt.Println(t) }

您会得到一个编译错误:multiple-value mySqrt() in single-value context

正确的做法是:

t, ok := mySqrt(25.0)
if ok { fmt.Println(t) }

注意事项 2

当您将字符串转换为整数时,且确定转换一定能够成功时,可以将 Atoi 函数进行一层忽略错误的封装:

func atoi (s string) (n int) {
	n, _ = strconv.Atoi(s)
	return }

实际上,fmt 包(第 4.4.3 节)最简单的打印函数也有 2 个返回值:

count, err := fmt.Println(x) // number of bytes printed, nil or 0, error

当打印到控制台时,可以将该函数返回的错误忽略;但当输出到文件流、网络流等具有不确定因素的输出对象时,应该始终检查是否有错误发生(另见练习 6.1b)。

 

摘自:https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/05.2.md














本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/bonelee/p/6861509.html,如需转载请自行联系原作者


相关文章
|
1月前
|
JSON Go 开发者
go-carbon v2.5.0 发布,轻量级、语义化、对开发者友好的 golang 时间处理库
carbon 是一个轻量级、语义化、对开发者友好的 Golang 时间处理库,提供了对时间穿越、时间差值、时间极值、时间判断、星座、星座、农历、儒略日 / 简化儒略日、波斯历 / 伊朗历的支持。
39 4
|
16天前
|
Go 数据安全/隐私保护 UED
优化Go语言中的网络连接:设置代理超时参数
优化Go语言中的网络连接:设置代理超时参数
|
1月前
|
存储 Cloud Native Shell
go库介绍:Golang中的Viper库
Viper 是 Golang 中的一个强大配置管理库,支持环境变量、命令行参数、远程配置等多种配置来源。本文详细介绍了 Viper 的核心特点、应用场景及使用方法,并通过示例展示了其强大功能。无论是简单的 CLI 工具还是复杂的分布式系统,Viper 都能提供优雅的配置管理方案。
|
1月前
|
Unix Linux Go
go进阶编程:Golang中的文件与文件夹操作指南
本文详细介绍了Golang中文件与文件夹的基本操作,包括读取、写入、创建、删除和遍历等。通过示例代码展示了如何使用`os`和`io/ioutil`包进行文件操作,并强调了错误处理、权限控制和路径问题的重要性。适合初学者和有经验的开发者参考。
|
1月前
|
JSON 安全 网络协议
go语言使用内置函数和标准库
【10月更文挑战第18天】
21 3
|
3月前
|
Go
Go to Learn Go之命令行参数
Go to Learn Go之命令行参数
36 8
|
3月前
|
Go
go函数
go函数
37 10
|
3月前
|
Go
golang语言之go常用命令
这篇文章列出了常用的Go语言命令,如`go run`、`go install`、`go build`、`go help`、`go get`、`go mod`、`go test`、`go tool`、`go vet`、`go fmt`、`go doc`、`go version`和`go env`,以及它们的基本用法和功能。
93 6
|
3月前
|
存储 Go
Golang语言基于go module方式管理包(package)
这篇文章详细介绍了Golang语言中基于go module方式管理包(package)的方法,包括Go Modules的发展历史、go module的介绍、常用命令和操作步骤,并通过代码示例展示了如何初始化项目、引入第三方包、组织代码结构以及运行测试。
74 3
|
3月前
|
编译器 Go C++
Go to Learn Go之函数
Go to Learn Go之函数
33 0