打印输出、日志输出
利用 fmt
和 log
在程序里输出相关信息是比较传统的调试手不详述了。
唯一要提的是如何把结构体连带字段名一起输出出来,否则看起来还是比较难受。这个可以通过fmt 的内置的 %#v
格式来输出完整字段:
type S struct {
A int
B int
}
func main() {
a := S{3, 4}
fmt.Printf("%v, %#v", a, a)
}
$ go run main.go
{3 4}, main.S{A:3, B:4}
另外还有一些第三方的封装:
GDB
- 安装 gdb:
brew install gdb
- macOS 上需要关闭 DWARF debug 信息的压缩:
export GOFLAGS="-ldflags=-compressdwarf=false"
- macOS 上以普通用户运行
gdb <executable-binary>
后在内部调用run
之后报错Unable to find Mach task port for process-id 42061: (os/kern) failure (0x5). (please check gdb is codesigned - see taskgated(8))
,在依照这个回答 执行后依然没有解决 倒是通过sudo
以管理员权限运行可以解决这个报错,然后通过run
命令运行程序,但。。然后就卡住没有新的提示符输出了???
最后通过 –entitlements gdb.xml 参数可以解决这个问题,并且不需要通过sudo
运行!
gdb.xml
内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.debugger</key>
<true/>
<key>com.apple.security.get-task-allow</key>
<true/>
</dict>
</plist>
具体使用可参考视频 使用GDB调试Go程序 - YouTube 和查看 Go使用gdb调试
常见命令:
- list。列出代码,输入第一次后如果输入回车,那么就会重复以上命令
- break。加断点,一般是list之后,break 行号来加断点
- bt。打印调用链
- info files。打印调试文件信息
- run。运行所要调试的代码
- up 和 down。在frame里跳来跳去
- info args 和 info locals 打印参数和本地变量
- whatis 和 p。打印变量和想要看的值,例如数组啊,函数啊,都可以
- info goroutines。查看所有的goroutine及其ID
- goroutine 命令。对对应的goroutine执行命令。
- q。退出
- help。打印帮助文档
CGDB
CGDB: Curses-based interface to the GNU Debugger.
可以参考这个视频 Easier Go debugging on the command line with CGDB。
- esc: goto source code separate window
- i: insert, goto the console window
- c: continue
- r: run
- s: step into function
- n: next
- print: print variables
Delve 调试
安装:
# 确保编译工具链
xcode-select --install
# 安装 dlv
go get github.com/go-delve/delve/cmd/dlv
# 开启开发者模式
sudo /usr/sbin/DevToolsSecurity -enable
通过dlv debug *.go
启动,进入一个交互界面,在这个界面里我们就可以进行调试操作了。
可观看短视频 Debugging Go applications with Delve,以及 delve 开发者的演讲 Advanced Go debugging with Delve和所有演讲。
(dlv) help
The following commands are available:
Running the program:
call ------------------------ Resumes process, injecting a function call (EXPERIMENTAL!!!)
continue (alias: c) --------- Run until breakpoint or program termination.
next (alias: n) ------------- Step over to next source line.
restart (alias: r) ---------- Restart process.
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.
Manipulating breakpoints:
break (alias: b) ------- Sets a breakpoint.
breakpoints (alias: bp) Print out info for active breakpoints.
clear ------------------ Deletes breakpoint.
clearall --------------- Deletes multiple breakpoints.
condition (alias: cond) Set breakpoint condition.
on --------------------- Executes a command when a breakpoint is hit.
trace (alias: t) ------- Set tracepoint.
Viewing program variables and memory:
args ----------------- Print function arguments.
display -------------- Print value of an expression every time the program stops.
examinemem (alias: x) Examine memory:
locals --------------- Print local variables.
print (alias: p) ----- Evaluate an expression.
regs ----------------- Print contents of CPU registers.
set ------------------ Changes the value of a variable.
vars ----------------- Print package variables.
whatis --------------- Prints type of an expression.
Listing and switching between threads and goroutines:
goroutine (alias: gr) -- Shows or changes current goroutine
goroutines (alias: grs) List program goroutines.
thread (alias: tr) ----- Switch to the specified thread.
threads ---------------- Print out info for every traced thread.
Viewing the call stack and selecting frames:
deferred --------- Executes command in the context of a deferred call.
down ------------- Move the current frame down.
frame ------------ Set the current frame, or execute command on a different frame.
stack (alias: bt) Print stack trace.
up --------------- Move the current frame up.
Other commands:
config --------------------- Changes configuration parameters.
disassemble (alias: disass) Disassembler.
edit (alias: ed) ----------- Open where you are in $DELVE_EDITOR or $EDITOR
exit (alias: quit | q) ----- Exit the debugger.
funcs ---------------------- Print list of functions.
help (alias: h) ------------ Prints the help message.
libraries ------------------ List loaded dynamic libraries
list (alias: ls | l) ------- Show source code.
source --------------------- Executes a file containing a list of delve commands
sources -------------------- Print list of source files.
types ---------------------- Print list of types
Type help followed by a command for full documentation.
IDE 调试
Goland
参见 Debugging - Help | GoLand。它的优点是可以动态加载代码更新。
几个概念分别是 breakpoints,debug mode,debug configurations。
VSCode
- How to debug Golang application with VS Code
- Debugging in Visual Studio Code
⇧⌘D
左栏视图切换到Show Run and Debug
- 在源码行数显示位置单击可添加 breakpoints
⇧⌘P
打开命令搜索,搜索到 “Debug: Select and Start Debugging” 就可以开启- Continue: F5
- Step Over: F10
- Step Into: F11
- Step Out:
⇧F11
- Restart:
⇧⌘F5
- Stop:
⇧F5
单元测试
- go 的单元测试文件必须是
xxx_test.go
格式,而且函数名必须是TestXXX(t *testing.T)
格式 testing
库- 使用内置
testing
库,并通过调用*testing.T.Error()
触发测试失败 - 另外可通过
*testing.T.Log()
和*tesing.T.Logf()
输更多信息
- 使用内置
go test
运行测试-v
输出详细信息,包含 Log 输出的信息-cover
参数可以输出覆盖率信息-json
参数可以输出 JSON 格式,用于程序自动化处理go test ./...
分别运行每个包里的测试-c
单独的测试可执行文件
- 第三方库
另外,测试里还有Mock, Stub, Spy的概念。
Benchmarks
- test#Benchmarks
- 函数名必须是
BenchmarkXXX(b *testing.B)
格式 go test -bench=. -v
运行性能测试
- 函数名必须是