最近golang和区块链火起来了,觉得自己有必要也跟一次风了。
golang的背景啊,优缺点啊就不讲了,网上大把资料,只要有C/C++的基础,这个golang程序猿就可以快速胜任。我就说一下配置过程和调试过程中的坑。golang的安装非常简单,只需要将其解压到制定目录,设置好GOROOT和GOPATH即可,GOROOT是golang的可执行文件,而GOPATH从我理解就是Go Project的所在目录,我们平时go get所下载的工程都会放到$GOPATH/src中。
由于刚开始接触,我手动设置了go编程环境,也使用go run 运行了hello world,但是一直无法调试go程序,在网上找了半天debugger,发现delver可以用来调试go程序,我习惯使用git+make install安装程序,安装完毕之后,我将其安装到go所在目录,方便直接命令行调用。
spider@ubuntu:/usr/lib/go-1.9.2$ ls api AUTHORS bin blog CONTRIBUTING.md CONTRIBUTORS doc favicon.ico lib LICENSE misc PATENTS pkg README.md robots.txt src test VERSION spider@ubuntu:/usr/lib/go-1.9.2$ cd bin/ spider@ubuntu:/usr/lib/go-1.9.2/bin$ ls dlv go godoc gofmt
只要用过gdb的童靴,这个就非常简单了,比如break,continue,print 等,如下所示:
spider@ubuntu:/tmp$ dlv debug test.go Type 'help' for list of commands. (dlv) l > _rt0_amd64_linux() /usr/lib/go-1.9.2/src/runtime/rt0_linux_amd64.s:8 (PC: 0x4571b0) Warning: debugging optimized function 3: // license that can be found in the LICENSE file. 4: 5: #include "textflag.h" 6: 7: TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8 => 8: LEAQ 8(SP), SI // argv 9: MOVQ 0(SP), DI // argc 10: MOVQ $main(SB), AX 11: JMP AX 12: 13: // When building with -buildmode=c-shared, this symbol is called when the shared (dlv) b main.main Breakpoint 1 set at 0x4a08d8 for main.main() ./test.go:12 (dlv) c > main.main() ./test.go:12 (hits goroutine(1):1 total:1) (PC: 0x4a08d8) Warning: debugging optimized function 7: return n 8: } 9: return fibonacci(n-2) + fibonacci(n-1) 10: } 11: => 12: func main() { 13: var i int 14: for i = 0; i < 10; i++ { 15: fmt.Printf("%d\t", fibonacci(i)) 16: } 17: } (dlv) n > main.main() ./test.go:13 (PC: 0x4a08ef) Warning: debugging optimized function 8: } 9: return fibonacci(n-2) + fibonacci(n-1) 10: } 11: 12: func main() { => 13: var i int 14: for i = 0; i < 10; i++ { 15: fmt.Printf("%d\t", fibonacci(i)) 16: } 17: } (dlv) > main.main() ./test.go:14 (PC: 0x4a08f8) Warning: debugging optimized function 9: return fibonacci(n-2) + fibonacci(n-1) 10: } 11: 12: func main() { 13: var i int => 14: for i = 0; i < 10; i++ { 15: fmt.Printf("%d\t", fibonacci(i)) 16: } 17: } (dlv) > main.main() ./test.go:15 (PC: 0x4a0913) Warning: debugging optimized function 10: } 11: 12: func main() { 13: var i int 14: for i = 0; i < 10; i++ { => 15: fmt.Printf("%d\t", fibonacci(i)) 16: } 17: } (dlv) p i 0 (dlv) n 0 > main.main() ./test.go:14 (PC: 0x4a0a02) Warning: debugging optimized function 9: return fibonacci(n-2) + fibonacci(n-1) 10: } 11: 12: func main() { 13: var i int => 14: for i = 0; i < 10; i++ { 15: fmt.Printf("%d\t", fibonacci(i)) 16: } 17: } (dlv) > main.main() ./test.go:15 (PC: 0x4a0913) Warning: debugging optimized function 10: } 11: 12: func main() { 13: var i int 14: for i = 0; i < 10; i++ { => 15: fmt.Printf("%d\t", fibonacci(i)) 16: } 17: } (dlv) p i 1
另外我们也可以使用dlv attach pid的方式进行调试,当然我们必须开启/proc/sys/kernel/yama/ptrace_scope to 0。然而我gdb、dlv再怎么强大,还是没有IDE方便,尤其是断点调试,经过调研VSCode、Gogland、Atom满足我们需求,由于之前我一直是用JetBrain系产品进行开发,毫无疑问,我是用Gogland作为IDE。我着重说一下他的调试,当debug某个程序时候,Gogland会打印信息:
GOROOT=/usr/lib/go-1.9.2 #gosetup GOPATH=/home/spider/go #gosetup /usr/lib/go-1.9.2/bin/go build -o /tmp/___go_build_main_go -gcflags "-N -l" -a /home/spider/go/src/awesomeProject/main.go #gosetup /opt/GoLand/plugins/intellij-go-plugin/lib/dlv/linux/dlv --listen=localhost:41151 --headless=true --api-version=2 --backend=default exec /tmp/___go_build_main_go -- #gosetup
可以看到第一行、第二行是打印GOROOT和GOPATH,第三行是打印进行编译,添加-gcflags “-N -l”,是为了去掉编译优化,方便调试,这行执行完毕会把程序放到/tmp/___go_build_main_go中,第四行就是使用gogland中的dlv插件的debug server,后端就是我们编译的/tmp/___go_build_main_go程序。