|
@@ -4,7 +4,9 @@ Go 语言的函数经常使用两个返回值来表示执行是否成功:返
|
|
|
|
|
|
|
|
在第 4.7 节的程序 `string_conversion.go` 中,函数 `strconv.Atoi` 的作用是将一个字符串转换为一个整数。之前我们忽略了相关的错误检查:
|
|
在第 4.7 节的程序 `string_conversion.go` 中,函数 `strconv.Atoi` 的作用是将一个字符串转换为一个整数。之前我们忽略了相关的错误检查:
|
|
|
|
|
|
|
|
- anInt, _ = strconv.Atoi(origStr)
|
|
|
|
|
|
|
+```go
|
|
|
|
|
+anInt, _ = strconv.Atoi(origStr)
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
如果 origStr 不能被转换为整数,anInt 的值会变成 0 而 `_` 无视了错误,程序会继续运行。
|
|
如果 origStr 不能被转换为整数,anInt 的值会变成 0 而 `_` 无视了错误,程序会继续运行。
|
|
|
|
|
|
|
@@ -12,46 +14,51 @@ Go 语言的函数经常使用两个返回值来表示执行是否成功:返
|
|
|
|
|
|
|
|
我们在第二个版本中对代码进行了改进:
|
|
我们在第二个版本中对代码进行了改进:
|
|
|
|
|
|
|
|
|
|
+
|
|
|
示例 1:
|
|
示例 1:
|
|
|
|
|
|
|
|
-Example 5.3 [string_conversion2.go](examples/chapter_5/string_conversion2.go)
|
|
|
|
|
|
|
+示例 5.3 [string_conversion2.go](examples/chapter_5/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)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+```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`。这样一来,函数的调用者就可以检查函数执行过程中是否存在错误了。
|
|
这是测试 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
|
|
|
|
|
- }
|
|
|
|
|
- // 未发生错误,继续执行:
|
|
|
|
|
|
|
+```go
|
|
|
|
|
+value, err := pack1.Function1(param1)
|
|
|
|
|
+if err!=nil {
|
|
|
|
|
+ fmt.Printf("An error occured in pack1.Function1 with parameter %v", param1)
|
|
|
|
|
+ return err
|
|
|
|
|
+}
|
|
|
|
|
+// 未发生错误,继续执行:
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
由于本例的函数调用者属于 main 函数,所以程序会直接停止运行。
|
|
由于本例的函数调用者属于 main 函数,所以程序会直接停止运行。
|
|
|
|
|
|
|
@@ -59,10 +66,12 @@ Example 5.3 [string_conversion2.go](examples/chapter_5/string_conversion2.go)
|
|
|
|
|
|
|
|
**习惯用法**
|
|
**习惯用法**
|
|
|
|
|
|
|
|
- if err !=nil {
|
|
|
|
|
- fmt.Printf("Program stopping with error %v", err)
|
|
|
|
|
- os.Exit(1)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+```go
|
|
|
|
|
+if err !=nil {
|
|
|
|
|
+ fmt.Printf("Program stopping with error %v", err)
|
|
|
|
|
+ os.Exit(1)
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
(此处的退出代码 1 可以使用外部脚本获取到)
|
|
(此处的退出代码 1 可以使用外部脚本获取到)
|
|
|
|
|
|
|
@@ -72,12 +81,14 @@ Example 5.3 [string_conversion2.go](examples/chapter_5/string_conversion2.go)
|
|
|
|
|
|
|
|
示例 2:我们尝试通过 `os.Open` 方法打开一个名为 `name` 的只读文件:
|
|
示例 2:我们尝试通过 `os.Open` 方法打开一个名为 `name` 的只读文件:
|
|
|
|
|
|
|
|
- f, err := os.Open(name)
|
|
|
|
|
- if err !=nil {
|
|
|
|
|
- return err
|
|
|
|
|
- }
|
|
|
|
|
- doSomething(f) // 当没有错误发生时,文件对象被传入到某个函数中
|
|
|
|
|
- doSomething
|
|
|
|
|
|
|
+```go
|
|
|
|
|
+f, err := os.Open(name)
|
|
|
|
|
+if err !=nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+}
|
|
|
|
|
+doSomething(f) // 当没有错误发生时,文件对象被传入到某个函数中
|
|
|
|
|
+doSomething
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
**练习 5.1** 尝试改写 [string_conversion2.go](examples/chapter_5/string_conversion2.go) 中的代码,要求使用 `:=` 方法来对 err 进行赋值,哪些地方可以被修改?
|
|
**练习 5.1** 尝试改写 [string_conversion2.go](examples/chapter_5/string_conversion2.go) 中的代码,要求使用 `:=` 方法来对 err 进行赋值,哪些地方可以被修改?
|
|
|
|
|
|
|
@@ -85,54 +96,66 @@ Example 5.3 [string_conversion2.go](examples/chapter_5/string_conversion2.go)
|
|
|
|
|
|
|
|
**习惯用法**
|
|
**习惯用法**
|
|
|
|
|
|
|
|
- if err := file.Chmod(0664); err !=nil {
|
|
|
|
|
- fmt.Println(err)
|
|
|
|
|
- return err
|
|
|
|
|
- }
|
|
|
|
|
|
|
+```go
|
|
|
|
|
+if err := file.Chmod(0664); err !=nil {
|
|
|
|
|
+ fmt.Println(err)
|
|
|
|
|
+ return err
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
示例 4:或者将 ok-pattern 的获取放置在 if 语句的初始化部分,然后进行判断:
|
|
示例 4:或者将 ok-pattern 的获取放置在 if 语句的初始化部分,然后进行判断:
|
|
|
|
|
|
|
|
**习惯用法**
|
|
**习惯用法**
|
|
|
|
|
|
|
|
- if value, ok := readData(); ok {
|
|
|
|
|
- …
|
|
|
|
|
- }
|
|
|
|
|
|
|
+```go
|
|
|
|
|
+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)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+```go
|
|
|
|
|
+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`。
|
|
您会得到一个编译错误:`multiple-value mySqrt() in single-value context`。
|
|
|
|
|
|
|
|
正确的做法是:
|
|
正确的做法是:
|
|
|
|
|
|
|
|
- t, ok := mySqrt(25.0)
|
|
|
|
|
- if ok { fmt.Println(t) }
|
|
|
|
|
|
|
+```go
|
|
|
|
|
+t, ok := mySqrt(25.0)
|
|
|
|
|
+if ok { fmt.Println(t) }
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
**注意事项 2**
|
|
**注意事项 2**
|
|
|
|
|
|
|
|
当您将字符串转换为整数时,且确定转换一定能够成功时,可以将 `Atoi` 函数进行一层忽略错误的封装:
|
|
当您将字符串转换为整数时,且确定转换一定能够成功时,可以将 `Atoi` 函数进行一层忽略错误的封装:
|
|
|
|
|
|
|
|
- func atoi (s string) (n int) {
|
|
|
|
|
- n, _ = strconv.Atoi(s)
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
|
|
+```go
|
|
|
|
|
+func atoi (s string) (n int) {
|
|
|
|
|
+ n, _ = strconv.Atoi(s)
|
|
|
|
|
+ return
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
实际上,`fmt` 包(第 4.4.3 节)最简单的打印函数也有 2 个返回值:
|
|
实际上,`fmt` 包(第 4.4.3 节)最简单的打印函数也有 2 个返回值:
|
|
|
|
|
|
|
|
- count, err := fmt.Println(x) // number of bytes printed, nil or 0, error
|
|
|
|
|
|
|
+```go
|
|
|
|
|
+count, err := fmt.Println(x) // number of bytes printed, nil or 0, error
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
-当打印到控制台时,可以将该函数返回的错误忽略;但当输出到文件流、网络流等具有不确定因素的输出对象时,应该始终检查是否有错误发生(另见 练习 6.1b)。
|
|
|
|
|
|
|
+当打印到控制台时,可以将该函数返回的错误忽略;但当输出到文件流、网络流等具有不确定因素的输出对象时,应该始终检查是否有错误发生(另见练习 6.1b)。
|
|
|
|
|
|
|
|
## 链接
|
|
## 链接
|
|
|
|
|
|