Skip to content

Commit 54142b1

Browse files
committed
Merge pull request astaxie#136 from chenwenli/master
修正一些单词错误,减少语句罗嗦之处
2 parents 15d5a63 + a8da551 commit 54142b1

File tree

2 files changed

+128
-126
lines changed

2 files changed

+128
-126
lines changed

11.1.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ Go语言主要的设计准则是:简洁、明白,简洁是指语法和C类
1010
log.Fatal(err)
1111
}
1212

13-
类似于`os.Open`函数,标准包中所有可能出错的API都返回了一个error变量,以方便错误处理,这个小节将将详细的介绍error类型的设计,以及在设计的Web应用中如何更好的处理error
13+
类似于`os.Open`函数,标准包中所有可能出错的API都会返回一个error变量,以方便错误处理,这个小节将详细地介绍error类型的设计,和讨论开发Web应用中如何更好地处理error
1414
## Error类型
1515
error类型是一个接口类型,这是它的定义:
1616

1717
type error interface {
1818
Error() string
1919
}
2020

21-
error是一个内置的类型变量,我们可以在/builtin/包下面找到相应的定义。而我们在很多内部包里面用到的 error是errors包下面的实现的非导出结构errorString
21+
error是一个内置的类型变量,我们可以在/builtin/包下面找到相应的定义。而我们在很多内部包里面用到的 error是errors包下面的实现的私有结构errorString
2222

2323
// errorString is a trivial implementation of error.
2424
type errorString struct {
@@ -38,10 +38,10 @@ error是一个内置的类型变量,我们可以在/builtin/包下面找到相
3838
下面这个例子演示了如何使用`errors.New`:
3939

4040
func Sqrt(f float64) (float64, error) {
41-
if f < 0 {
42-
return 0, errors.New("math: square root of negative number")
43-
}
44-
// implementation
41+
if f < 0 {
42+
return 0, errors.New("math: square root of negative number")
43+
}
44+
// implementation
4545
}
4646

4747
在下面的例子中,我们在调用Sqrt的时候传递的一个负数,然后就得到了non-nil的error对象,将此对象与nil比较,结果为true,所以fmt.Println(fmt包在处理error时会调用Error方法)被调用,以输出错误,请看下面调用的示例代码:
@@ -61,7 +61,7 @@ error是一个内置的类型变量,我们可以在/builtin/包下面找到相
6161

6262
func (e *SyntaxError) Error() string { return e.msg }
6363

64-
offset字段在调用Error的时候不会被打印,但是我们可以通过类型断言获取错误类型,然后可以打印相应的错误信息,请看下面的例子:
64+
Offset字段在调用Error的时候不会被打印,但是我们可以通过类型断言获取错误类型,然后可以打印相应的错误信息,请看下面的例子:
6565

6666
if err := dec.Decode(&val); err != nil {
6767
if serr, ok := err.(*json.SyntaxError); ok {

11.2.md

Lines changed: 121 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,98 @@
1-
# 11.2 使用GDB调试
2-
开发程序过程中调试代码是开发者经常要做的一件事情,Go语言不像PHP、Python等动态语言,只要修改不需要编译就可以直接输出,而且可以动态的在运行环境下打印数据。当然Go语言也可以通过Println之类的打印数据来调试,但是每次都需要重新编译,这是一件相当麻烦的事情。我们知道在Python中有pdb/ipdb之类的工具调试,Javascript也有类似工具,这些工具都能够动态的显示变量信息,单步调试等。不过庆幸的是Go也有类似的工具支持:GDB。Go内部已经内置支持了GDB,所以,我们可以通过GDB来进行调试,那么本小节就来介绍一下如何通过GDB来调试Go程序。
3-
4-
## GDB调试简介
5-
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。使用GDB可以做如下事情:
6-
7-
1. 启动你的程序,可以按照你的自定义的要求随心所欲的运行程序
8-
2. 可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
9-
3. 当程序被停住时,可以检查此时你的程序中所发生的事
10-
4. 动态的改变你程序的执行环境
11-
12-
目前支持调试Go程序的GDB版本必须大于7.1。
13-
14-
编译Go程序的时候需要注意以下几点
15-
16-
1. 传递参数-ldflags "-s",忽略debug的打印信息
17-
2. 传递-gcflags "-N -l" 参数,这样可以忽略Go内部做的一些优化,聚合变量和函数等优化,这样对于GDB调试来说非常困难,所以在编译的时候加入者两个参数避免这些优化。
18-
19-
## 常用命令
20-
GDB的一些常用命令如下所示
21-
22-
- list
23-
24-
简写命令`l`,用来显示源代码,默认显示十行代码,后面可以带上参数显示的具体行,例如:`list 15`,显示十行代码,其中15行在显示的十行里面的中间,如下所示。
25-
26-
10 time.Sleep(2 * time.Second)
27-
11 c <- i
28-
12 }
29-
13 close(c)
30-
14 }
31-
15
32-
16 func main() {
33-
17 msg := "Starting main"
34-
18 fmt.Println(msg)
35-
19 bus := make(chan int)
36-
37-
38-
- break
39-
40-
简写命令`b`,用来设置断点,后面跟上参数设置断点的行数,例如`b 10`在第十行设置断点。
41-
- delete
42-
43-
简写命令`d`,用来删除断点,后面跟上断点设置的序号,这个序号可以通过`info breakpoints`获取相应的设置的断点序号,如下是显示的设置断点序号。
44-
45-
Num Type Disp Enb Address What
46-
2 breakpoint keep y 0x0000000000400dc3 in main.main at /home/xiemengjun/gdb.go:23
47-
breakpoint already hit 1 time
48-
49-
- backtrace
50-
51-
简写命令`bt`,用来打印执行的代码过程,如下所示:
52-
53-
#0 main.main () at /home/xiemengjun/gdb.go:23
54-
#1 0x000000000040d61e in runtime.main () at /home/xiemengjun/go/src/pkg/runtime/proc.c:244
55-
#2 0x000000000040d6c1 in schedunlock () at /home/xiemengjun/go/src/pkg/runtime/proc.c:267
56-
#3 0x0000000000000000 in ?? ()
57-
- info
58-
59-
info命令用来显示信息,后面有几种参数,我们常用的有如下几种:
60-
61-
- `info locals`
62-
63-
显示当前执行的程序中的变量值
64-
- `info breakpoints`
65-
66-
显示当前设置的断点列表
67-
- `info goroutines`
68-
69-
显示当前执行的goroutine列表,如下代码所示,带*的表示当前执行的
70-
71-
* 1 running runtime.gosched
72-
* 2 syscall runtime.entersyscall
73-
3 waiting runtime.gosched
74-
4 runnable runtime.gosched
75-
- print
76-
77-
简写命令`p`,用来打印变量或者其他信息,后面跟上需要打印的变量名,当然还有一些很有用的函数$len()和$cap(),用来返回当前string、slices或者maps的长度和容量。
78-
79-
- whatis
80-
81-
用来显示当前变量的类型,后面跟上变量名,例如`whatis msg`,显示如下:
82-
83-
type = struct string
84-
- next
85-
86-
简写命令`n`,用来单步调试,跳到下一步,当有断点之后,可以输入`n`跳转到下一步继续执行
87-
- countinue
88-
89-
简称命令`c`,用来跳出当前断点处,后面可以跟参数N,跳过多少次断点
90-
91-
- set variable
92-
93-
该命令用来改变运行过程中的变量值,格式如:`set variable <var>=<value>`
94-
95-
## 调试过程
1+
# 11.2 使用GDB调试
2+
开发程序过程中调试代码是开发者经常要做的一件事情,Go语言不像PHP、Python等动态语言,只要修改不需要编译就可以直接输出,而且可以动态的在运行环境下打印数据。当然Go语言也可以通过Println之类的打印数据来调试,但是每次都需要重新编译,这是一件相当麻烦的事情。我们知道在Python中有pdb/ipdb之类的工具调试,Javascript也有类似工具,这些工具都能够动态的显示变量信息,单步调试等。不过庆幸的是Go也有类似的工具支持:GDB。Go内部已经内置支持了GDB,所以,我们可以通过GDB来进行调试,那么本小节就来介绍一下如何通过GDB来调试Go程序。
3+
4+
## GDB调试简介
5+
GDB是GNU开源组织发布的一个强大的类UNIX系统下的程序调试工具。使用GDB可以做如下事情:
6+
7+
1. 启动程序,可以按照开发者的自定义要求运行程序
8+
2. 可让被调试的程序在开发者设定的调置的断点处停住。(断点可以是条件表达式)
9+
3. 当程序被停住时,可以检查此时程序中所发生的事
10+
4. 动态的改变当前程序的执行环境
11+
12+
目前支持调试Go程序的GDB版本必须大于7.1。
13+
14+
编译Go程序的时候需要注意以下几点
15+
16+
1. 传递参数-ldflags "-s",忽略debug的打印信息
17+
2. 传递-gcflags "-N -l" 参数,这样可以忽略Go内部做的一些优化,聚合变量和函数等优化,这样对于GDB调试来说非常困难,所以在编译的时候加入者两个参数避免这些优化。
18+
19+
## 常用命令
20+
GDB的一些常用命令如下所示
21+
22+
- list
23+
24+
简写命令`l`,用来显示源代码,默认显示十行代码,后面可以带上参数显示的具体行,例如:`list 15`,显示十行代码,其中15行在显示的十行里面的中间,如下所示。
25+
26+
10 time.Sleep(2 * time.Second)
27+
11 c <- i
28+
12 }
29+
13 close(c)
30+
14 }
31+
15
32+
16 func main() {
33+
17 msg := "Starting main"
34+
18 fmt.Println(msg)
35+
19 bus := make(chan int)
36+
37+
38+
- break
39+
40+
简写命令 `b`,用来设置断点,后面跟上参数设置断点的行数,例如`b 10`在第十行设置断点。
41+
42+
- delete
43+
简写命令 `d`,用来删除断点,后面跟上断点设置的序号,这个序号可以通过`info breakpoints`获取相应的设置的断点序号,如下是显示的设置断点序号。
44+
45+
Num Type Disp Enb Address What
46+
2 breakpoint keep y 0x0000000000400dc3 in main.main at /home/xiemengjun/gdb.go:23
47+
breakpoint already hit 1 time
48+
49+
- backtrace
50+
51+
简写命令 `bt`,用来打印执行的代码过程,如下所示:
52+
53+
#0 main.main () at /home/xiemengjun/gdb.go:23
54+
#1 0x000000000040d61e in runtime.main () at /home/xiemengjun/go/src/pkg/runtime/proc.c:244
55+
#2 0x000000000040d6c1 in schedunlock () at /home/xiemengjun/go/src/pkg/runtime/proc.c:267
56+
#3 0x0000000000000000 in ?? ()
57+
- info
58+
59+
info命令用来显示信息,后面有几种参数,我们常用的有如下几种:
60+
61+
- `info locals`
62+
63+
显示当前执行的程序中的变量值
64+
- `info breakpoints`
65+
66+
显示当前设置的断点列表
67+
- `info goroutines`
68+
69+
显示当前执行的goroutine列表,如下代码所示,带*的表示当前执行的
70+
71+
* 1 running runtime.gosched
72+
* 2 syscall runtime.entersyscall
73+
3 waiting runtime.gosched
74+
4 runnable runtime.gosched
75+
- print
76+
77+
简写命令`p`,用来打印变量或者其他信息,后面跟上需要打印的变量名,当然还有一些很有用的函数$len()和$cap(),用来返回当前string、slices或者maps的长度和容量。
78+
79+
- whatis
80+
81+
用来显示当前变量的类型,后面跟上变量名,例如`whatis msg`,显示如下:
82+
83+
type = struct string
84+
- next
85+
86+
简写命令 `n`,用来单步调试,跳到下一步,当有断点之后,可以输入`n`跳转到下一步继续执行
87+
- coutinue
88+
89+
简称命令 `c`,用来跳出当前断点处,后面可以跟参数N,跳过多少次断点
90+
91+
- set variable
92+
93+
该命令用来改变运行过程中的变量值,格式如:`set variable <var>=<value>`
94+
95+
## 调试过程
9696
我们通过下面这个代码来演示如何通过GDB来调试Go程序,下面是将要演示的代码:
9797

9898
package main
@@ -119,17 +119,17 @@ GDB的一些常用命令如下所示
119119
for count := range bus {
120120
fmt.Println("count:", count)
121121
}
122-
}
123-
124-
编译文件,生成可执行文件gdbfile:
125-
126-
go build -gcflags "-N -l" -ldflags "-s" gdbfile.go
127-
128-
通过gdb命令启动调试:
129-
122+
}
123+
124+
编译文件,生成可执行文件gdbfile:
125+
126+
go build -gcflags "-N -l" -ldflags "-s" gdbfile.go
127+
128+
通过gdb命令启动调试:
129+
130130
gdb gdbfile
131131

132-
启动之后我们首先看看是不是可以运行起来,输入`run`命令之后程序就开始运行,我们可以看到程序输出如下,和我们在命令行直接执行程序输出是一样的:
132+
启动之后首先看看这个程序是不是可以运行起来,只要输入`run`命令回车后程序就开始运行,程序正常的话可以看到程序输出如下,和我们在命令行直接执行程序输出是一样的:
133133

134134
(gdb) run
135135
Starting program: /home/xiemengjun/gdbfile
@@ -145,8 +145,8 @@ GDB的一些常用命令如下所示
145145
count: 8
146146
count: 9
147147
[LWP 2771 exited]
148-
[Inferior 1 (process 2771) exited normally]
149-
好了,现在我们知道怎么让程序跑起来了,接下来我们开始设置断点
148+
[Inferior 1 (process 2771) exited normally]
149+
好了,现在我们已经知道怎么让程序跑起来了,接下来开始给代码设置断点
150150

151151
(gdb) b 23
152152
Breakpoint 1 at 0x400d8d: file /home/xiemengjun/gdbfile.go, line 23.
@@ -157,9 +157,9 @@ GDB的一些常用命令如下所示
157157
[Switching to LWP 3284]
158158

159159
Breakpoint 1, main.main () at /home/xiemengjun/gdbfile.go:23
160-
23 fmt.Println("count:", count)
161-
162-
上面我们可以看到我们在第23行设置了断点,然后运行,我们可以看到在我们设置断点的地方程序停住了,我们可以查看相应的源码,我们可以看到显示的原始是当前停止行之前的五行开始显示
160+
23 fmt.Println("count:", count)
161+
162+
上面例子`b 23`表示在第23行设置了断点,之后输入`run`开始运行程序。现在程序在前面设置断点的地方停住了,我们需要查看断点相应上下文的源码,输入`list`就可以看到源码显示从当前停止行的前五行开始
163163

164164
(gdb) list
165165
18 fmt.Println(msg)
@@ -171,7 +171,7 @@ GDB的一些常用命令如下所示
171171
24 }
172172
25 }
173173

174-
现在我们可以查看所有的变量信息,然后打印相应的变量,查看相应变量的类型
174+
现在GDB在运行当前的程序的环境中已经保留了一些有用的调试信息,我们只需打印出相应的变量,查看相应变量的类型及值
175175

176176
(gdb) info locals
177177
count = 0
@@ -183,7 +183,7 @@ GDB的一些常用命令如下所示
183183
(gdb) whatis bus
184184
type = chan int
185185

186-
接下来我们如何让程序继续往下执行呢?请看下面的命令
186+
接下来该让程序继续往下执行,请继续看下面的命令
187187

188188
(gdb) c
189189
Continuing.
@@ -201,7 +201,9 @@ GDB的一些常用命令如下所示
201201
Breakpoint 1, main.main () at /home/xiemengjun/gdbfile.go:23
202202
23 fmt.Println("count:", count)
203203

204-
我们可以看到每次输入c之后都会执行一次,执行到下一次for循环,打印出来相应的信息,接下来我们来改变变量的信息,然后继续执行到下一步,我们可以看到我们可以修改相应的变量值:
204+
每次输入`c`之后都会执行一次代码,又跳到下一次for循环,继续打印出来相应的信息。
205+
206+
设想目前需要改变上下文相关变量的信息,跳过一些过程,并继续执行下一步,得出修改后想要的结果:
205207

206208
(gdb) info locals
207209
count = 2
@@ -218,7 +220,7 @@ GDB的一些常用命令如下所示
218220
Breakpoint 1, main.main () at /home/xiemengjun/gdbfile.go:23
219221
23 fmt.Println("count:", count)
220222

221-
最后我们来看一下,这整个的过程中起了多少个goroutine,每个goroutine都是在做什么
223+
最后稍微思考一下,前面整个程序运行的过程中到底创建了多少个goroutine,每个goroutine都在做什么
222224

223225
(gdb) info goroutines
224226
* 1 running runtime.gosched
@@ -236,12 +238,12 @@ GDB的一些常用命令如下所示
236238
#5 0x000000000040d16a in schedunlock () at /home/xiemengjun/go/src/pkg/runtime/proc.c:267
237239
#6 0x0000000000000000 in ?? ()
238240

239-
通过gotoutine的命令我们清楚的知道go内部是怎么执行的,每个函数的调用顺序都非常清楚的显示出来了
241+
通过查看goroutines的命令我们可以清楚地了解goruntine内部是怎么执行的,每个函数的调用顺序已经明明白白地显示出来了
240242

241243
## 小结
242-
本小节我们介绍了GDB调试Go程序的一些基本命令,包括`run``print``info``set variable``coutinue``list``break`等一些经常用到的调试命令,通过上面的例子演示,我相信读者已经对于通过GDB调试Go程序有了基本的理解,如果你想获取更多的调试技巧请参考官方网站的GDB调试手册,还有GDB官方网站的手册。
243-
244-
## links
245-
* [目录](<preface.md>)
246-
* 上一节: [错误处理](<11.1.md>)
244+
本小节我们介绍了GDB调试Go程序的一些基本命令,包括`run``print``info``set variable``coutinue``list``break`等经常用到的调试命令,通过上面的例子演示,我相信读者已经对于通过GDB调试Go程序有了基本的理解,如果你想获取更多的调试技巧请参考官方网站的GDB调试手册,还有GDB官方网站的手册。
245+
246+
## links
247+
* [目录](<preface.md>)
248+
* 上一节: [错误处理](<11.1.md>)
247249
* 下一节: [Go怎么写测试用例](<11.3.md>)

0 commit comments

Comments
 (0)