This commit is contained in:
Unknown
2014-09-22 19:50:26 -04:00
parent a35cd9a639
commit d480e2db2d
3 changed files with 237 additions and 18 deletions

View File

@@ -9,11 +9,11 @@
## 翻译进度 ## 翻译进度
6.3 [传递变长参数](eBook/06.3.md) 6.4 [defer 和追踪](eBook/06.4.md)
## 支持本书 ## 支持本书
如果你喜欢本书 《Go入门指南》你可以参与到本书的翻译或纠正工作中来具体请联系【无闻 E-mailjoe2010xtmf#163.com】,一同完善本书并帮助壮大 Go 语言在国内的学习群体,给大家提供更好的学习资源。 如果你喜欢本书 《Go入门指南》你可以参与到本书的翻译或纠正工作中来具体请联系【无闻 E-mailu#gogs.io】,一同完善本书并帮助壮大 Go 语言在国内的学习群体,给大家提供更好的学习资源。
## 交流社区 ## 交流社区
@@ -23,14 +23,11 @@
- 2012 年 3 月 28 日以前的博文中的内容基本过时,不要再看 - 2012 年 3 月 28 日以前的博文中的内容基本过时,不要再看
- 符合等式 ***百度+思考+失败+翻墙+谷歌+尝试=解决*** 的问题最好不要发问 - 符合等式 ***百度+思考+失败+翻墙+谷歌+尝试=解决*** 的问题最好不要发问
- 不要问 Go 现在的发展前景如何
- 不要问学习 Go 语言能不能找到工作
- 不要问现在 Go 语言有哪些实际应用
## 致谢 ## 致谢
- 本书原作者Ivo Balbaert - 本书原作者Ivo Balbaert
- 协助或参与翻译: - 参与翻译人员
- [zhanming](https://github.com/zhanming) - [zhanming](https://github.com/zhanming)
- [themorecolor](https://github.com/themorecolor) - [themorecolor](https://github.com/themorecolor)
- [everyx](https://github.com/everyx) - [everyx](https://github.com/everyx)

View File

@@ -1,18 +1,237 @@
## 啊哦,亲,你看得也太快了。。。还没翻译完呢 0 0 # 6.4 defer 和追踪
要不等到 **2014 年 8 月 4 日** 再来看看吧~~ 关键字 defer 允许我们推迟到函数返回之前(或任意位置执行 `return` 语句之后)一刻才执行某个语句或函数(为什么要在返回之后才执行这些语句?因为 `return` 语句同样可以包含一些操作,而不是单纯地返回某个值)。
这里还有一些其它的学习资源噢~ 关键字 defer 的用法类似于面向对象编程语言 Java 和 C# 的 `finally` 语句块,它一般用于释放某些已分配的资源。
- [《Go编程基础》](https://github.com/Unknwon/go-fundamental-programming) 下面这个示例很好地解释了它的用法Listing 6.8 defer.go
- [《Go Web编程》](https://github.com/astaxie/build-web-application-with-golang)
- [《Go名库讲解》](https://github.com/Unknwon/go-rock-libraries-showcases)
神马?你说你不想学习?那好吧,去逛逛看看行情也行~ ```go
package main
import fmt
- [Go Walker](https://gowalker.org) **Go 项目 API 文档在线浏览工具** func main() {
- [Golang Home](http://golanghome.com) Function1()
- [Go 语言学习园地](http://studygolang.com/) }
- [Golang 中国](http://golangtc.com)
# 6.4 defer 和追踪 func Function1() {
fmt.Printf("In Function1 at the top\n")
defer Function2()
fmt.Printf("In Function1 at the bottom!\n")
}
func Function2() {
fmt.Printf("Function2: Deferred until the end of the calling function!")
}
```
输出:
```
In Function1 at the top
In Function1 at the bottom!
Function2: Deferred until the end of the calling function!
```
请将 defer 关键字去掉并对比输出结果。
使用 defer 的语句同样可以接受参数,下面这个例子就会在执行 defer 语句时打印 `0`
```go
func a() {
i := 0
defer fmt.Println(i)
i++
return
}
```
当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出):
```go
func f() {
for i := 0; i < 5; i++ {
defer fmt.Printf(%d , i)
}
}
```
上面的代码将会输出:`4 3 2 1 0`
关键字 defer 允许我们进行一些函数执行完成后的收尾工作,例如:
1. 关闭文件流:
// open a file
defer file.Close() (详见第 12.2 节)
2. 解锁一个加锁的资源
mu.Lock()
defer mu.Unlock() (详见第 9.3 节)
3. 打印最终报告
printHeader()
defer printFooter()
4. 关闭数据库链接
// open a database connection
defer disconnectFromDB()
合理使用 defer 语句能够使得代码更加简洁。
以下代码模拟了上面描述的第 4 种情况:
```go
package main
import "fmt"
func main() {
doDBOperations()
}
func connectToDB() {
fmt.Println("ok, connected to db")
}
func disconnectFromDB() {
fmt.Println("ok, disconnected from db")
}
func doDBOperations() {
connectToDB()
fmt.Println("Defering the database disconnect.")
defer disconnectFromDB() //function called here with defer
fmt.Println("Doing some DB operations ...")
fmt.Println("Oops! some crash or network error ...")
fmt.Println("Returning from function here!")
return //terminate the program
// deferred function executed here just before actually returning, even if
// there is a return or abnormal termination before
}
```
输出:
```
ok, connected to db
Defering the database disconnect.
Doing some DB operations ...
Oops! some crash or network error ...
Returning from function here!
ok, disconnected from db
```
**使用 defer 语句实现代码追踪**
一个基础但十分实用的实现代码执行追踪的方案就是在进入和离开某个函数打印相关的消息,即可以提炼为下面两个函数:
```go
func trace(s string) { fmt.Println("entering:", s) }
func untrace(s string) { fmt.Println("leaving:", s) }
```
以下代码展示了何时调用两个函数:
Listing 6.10—_defer_tracing.go:
```go
package main
import "fmt"
func trace(s string) { fmt.Println("entering:", s) }
func untrace(s string) { fmt.Println("leaving:", s) }
func a() {
trace("a")
defer untrace("a")
fmt.Println("in a")
}
func b() {
trace("b")
defer untrace("b")
fmt.Println("in b")
a()
}
func main() {
b()
}
```
输出:
```
entering: b
in b
entering: a
win a
leaving: a
leaving: b
```
上面的代码还可以修改为更加简便的版本Listing 6.11—_defer_tracing2.go
```go
package main
import "fmt"
func trace(s string) string {
fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func a() {
defer un(trace("a"))
fmt.Println("in a")
}
func b() {
defer un(trace("b"))
fmt.Println("in b")
a()
}
func main() {
b()
}
```
**使用 defer 语句来记录函数的参数与返回值**
下面的代码展示了另一种在调试时使用 defer 语句的手法Listing 6.12—_defer_logvalues.go
```go
package main
import (
"io"
"log"
)
func func1(s string) (n int, err error) {
defer func() {
log.Printf("func1(%q) = %d, %v", s, n, err)
}()
return 7, io.EOF
}
func main() {
func1("Go")
}
```
输出:
Output: 2011/10/04 10:46:11 func1(“Go”) = 7, EOF

3
eBook/06.5.md Normal file
View File

@@ -0,0 +1,3 @@
# 6.5 内置函数
142