写在前面
上节我写了个bug,粗心大意肉眼没看出来,所以我们祭出golang的单步调试神器delve来帮我解决问题。
Delve也是单步执行工具,和GDB很像,但是他更方便安装,本身也是go的包之一,安装方法如下:
#设置代理
export https_proxy=socks5://192.168.88.1:1080
export http_proxy=socks5://192.168.88.1:1080
#安装dlv
go get -u -v github.com/go-delve/delve/cmd/dlv
dlv帮助:
[root@localhost tail]# dlv -h
Usage:
dlv [command]
Available Commands:
attach Attach to running process and begin debugging.
connect Connect to a headless debug server.
core Examine a core dump.
debug Compile and begin debugging main package in current directory, or the package specified.
exec Execute a precompiled binary, and begin a debug session.
help Help about any command
run Deprecated command. Use 'debug' instead.
test Compile test binary and begin debugging program.
trace Compile and begin tracing program.
version Prints version.
Flags:
--accept-multiclient Allows a headless server to accept multiple client connections.
--api-version int Selects API version when headless. (default 1)
--backend string Backend selection (see 'dlv help backend'). (default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "127.0.0.1:0")
--log Enable debugging server logging.
--log-dest string Writes logs to the specified file or file descriptor (see 'dlv help log').
--log-output string Comma separated list of components that should produce debug output (see 'dlv help log')
--wd string Working directory for running the program. (default ".")
Additional help topics:
dlv backend Help about the --backend flag.
dlv log Help about logging flags
帮助写的很详细,比较常用的是debug执行go文件,和attach pid。
然后我们执行dlv debug wscat.go,添加参数的话,用“--”两个横线来表示
[root@localhost tail]# dlv debug wscat.go -- ws://127.0.0.1:8888/watch/clusterlog?clusterid=cb63a0bc-8273-45ef-a966-67b46968e518 http://127.0.0.1:8888
Type 'help' for list of commands.
(dlv) help
The following commands are available:
args ------------------------ Print function arguments.
break (alias: b) ------------ Sets a breakpoint.
breakpoints (alias: bp) ----- Print out info for active breakpoints.
call ------------------------ Resumes process, injecting a function call (EXPERIMENTAL!!!)
clear ----------------------- Deletes breakpoint.
clearall -------------------- Deletes multiple breakpoints.
condition (alias: cond) ----- Set breakpoint condition.
config ---------------------- Changes configuration parameters.
continue (alias: c) --------- Run until breakpoint or program termination.
deferred -------------------- Executes command in the context of a deferred call.
disassemble (alias: disass) - Disassembler.
down ------------------------ Move the current frame down.
edit (alias: ed) ------------ Open where you are in $DELVE_EDITOR or $EDITOR
exit (alias: quit | q) ------ Exit the debugger.
frame ----------------------- Set the current frame, or execute command on a different frame.
funcs ----------------------- Print list of functions.
goroutine (alias: gr) ------- Shows or changes current goroutine
goroutines (alias: grs) ----- List program goroutines.
help (alias: h) ------------- Prints the help message.
libraries ------------------- List loaded dynamic libraries
list (alias: ls | l) -------- Show source code.
locals ---------------------- Print local variables.
next (alias: n) ------------- Step over to next source line.
on -------------------------- Executes a command when a breakpoint is hit.
print (alias: p) ------------ Evaluate an expression.
regs ------------------------ Print contents of CPU registers.
restart (alias: r) ---------- Restart process.
set ------------------------- Changes the value of a variable.
source ---------------------- Executes a file containing a list of delve commands
sources --------------------- Print list of source files.
stack (alias: bt) ----------- Print stack trace.
step (alias: s) ------------- Single step through program.
step-instruction (alias: si) Single step a single cpu instruction.
stepout (alias: so) --------- Step out of the current function.
thread (alias: tr) ---------- Switch to the specified thread.
threads --------------------- Print out info for every traced thread.
trace (alias: t) ------------ Set tracepoint.
types ----------------------- Print list of types
up -------------------------- Move the current frame up.
vars ------------------------ Print package variables.
whatis ---------------------- Prints type of an expression.
Type help followed by a command for full documentation.
都是一些常用的命令,首先为main函数打个断点
(dlv) b main.main
Breakpoint 1 set at 0x7041cb for main.main() ./wscat.go:20
也可以通过行号来打断点:
(dlv) b wscat.go:20
Breakpoint 1 set at 0x7041cb for main.main() ./wscat.go:20
两者是一样的,接下来我们执行c: continue执行到main函数
[root@localhost tail]# dlv debug wscat.go -- ws://127.0.0.1:8888/watch/clusterlog?clusterid=cb63a0bc-8273-45ef-a966-67b46968e518 http://127.0.0.1:8888
Type 'help' for list of commands.
(dlv) b wscat.go:32
Breakpoint 1 set at 0x704711 for main.main.func1() ./wscat.go:32
(dlv) c
Dial url: ws://127.0.0.1:8888/watch/clusterlog?clusterid=cb63a0bc-8273-45ef-a966-67b46968e518 ,origin: http://127.0.0.1:8888
> main.main.func1() ./wscat.go:32 (hits goroutine(7):1 total:1) (PC: 0x704711)
27: }
28:
29: var msg = make([]byte, 512)
30: go func() {
31: for {
=> 32: ws.Read(msg)
33: m, err := ws.Read(msg)
34: if err != nil {
35: log.Fatal(err)
36: }
37: fmt.Printf("Receive: %s\n", msg[:m])
(dlv)
b 打断点到32行
n 是执行下一步
s 是执行step
p 是打印
set 是设置变量
然后发现了代码的出错地方:
ws.Read调用了两遍:
31: for {
=> 32: ws.Read(msg)
33: m, err := ws.Read(msg)
34: if err != nil {
dlv很好用,大家动手用一下就了解了。
以上↑
有疑问加站长微信联系(非本文作者)