Go学习笔记-代码调试工具 dlv

简介: Go学习笔记-代码调试工具 dlv

1.dlv 简介

  • dlv(delve 的简写) 是一个用于 Go 源代码级调试器。
  • dlv 通过控制进程的执行、计算变量、提供线程/协程的状态、CPU寄存器状态等信息,可以方便地与程序进行交互。
  • 这个工具的目标是为调试 Go 程序提供一个简单但功能强大的界面。
  • dlv 将标志传递给正在调试的程序,例如:
dlv exec ./hello -- server --config conf/config.toml
  • macOs 使用 brew install dlv 命令下载安装即可。

2.dlv 调试代码

2.1 dlv 剖析 strings.Contains 函数

新建 a.go 文件,文件内容如下:

package main
import (
    "fmt"
    "strings"
)
func main()  {
    str := "Go语言是世界上最好的语言"
    if strings.Contains(str,"世界") {
        fmt.Println("字符串中包含","世界")
    }else {
        fmt.Println("字符串中不包含","世界")
    }
}

使用 dlv debug a.go 命令可以开始对上述代码进行断点调试:

qinshixian@qinshixiandeMacBook-Pro qinshixian % dlv debug a.go
Type 'help' for list of commands.
(dlv) b main.main
Breakpoint 1 set at 0x10acd6f for main.main() ./a.go:8
(dlv) c
> main.main() ./a.go:8 (hits goroutine(1):1 total:1) (PC: 0x10acd6f)
     3:    import (
     4:        "fmt"
     5:        "strings"
     6:    )
     7:
=>   8:    func main()  {
     9:        str := "Go语言是世界上最好的语言"
    10:        if strings.Contains(str,"世界") {
    11:            fmt.Println("字符串中包含","世界")
    12:        }else {
    13:            fmt.Println("字符串中不包含","世界")
(dlv) n
> main.main() ./a.go:9 (PC: 0x10acd86)
     4:        "fmt"
     5:        "strings"
     6:    )
     7:
     8:    func main()  {
=>   9:        str := "Go语言是世界上最好的语言"
    10:        if strings.Contains(str,"世界") {
    11:            fmt.Println("字符串中包含","世界")
    12:        }else {
    13:            fmt.Println("字符串中不包含","世界")
    14:        }
(dlv) n
> main.main() ./a.go:10 (PC: 0x10acd9b)
     5:        "strings"
     6:    )
     7:
     8:    func main()  {
     9:        str := "Go语言是世界上最好的语言"
=>  10:        if strings.Contains(str,"世界") {
    11:            fmt.Println("字符串中包含","世界")
    12:        }else {
    13:            fmt.Println("字符串中不包含","世界")
    14:        }
    15:    }
(dlv) p str
"Go语言是世界上最好的语言"
(dlv) s strings.Contains
> strings.Contains() /Users/qinshixian/.g/go/src/strings/strings.go:61 (PC: 0x10ac1e6)
    56:            s = s[i+len(substr):]
    57:        }
    58:    }
    59:
    60:    // Contains reports whether substr is within s.
=>  61:    func Contains(s, substr string) bool {
    62:        return Index(s, substr) >= 0
    63:    }
    64:
    65:    // ContainsAny reports whether any Unicode code points in chars are within s.
    66:    func ContainsAny(s, chars string) bool {
(dlv) n
> strings.Contains() /Users/qinshixian/.g/go/src/strings/strings.go:62 (PC: 0x10ac20d)
    57:        }
    58:    }
    59:
    60:    // Contains reports whether substr is within s.
    61:    func Contains(s, substr string) bool {
=>  62:        return Index(s, substr) >= 0
    63:    }
    64:
    65:    // ContainsAny reports whether any Unicode code points in chars are within s.
    66:    func ContainsAny(s, chars string) bool {
    67:        return IndexAny(s, chars) >= 0
(dlv) b Contains
Breakpoint 2 set at 0x10ac1e6 for strings.Contains() /Users/qinshixian/.g/go/src/strings/strings.go:61
(dlv) p s
"Go语言是世界上最好的语言"
(dlv) p substr
"世界"
(dlv) s Index
> strings.Index() /Users/qinshixian/.g/go/src/strings/strings.go:1024 (PC: 0x10ac32f)
  1019:        // One string is empty. Are both?
  1020:        return s == t
  1021:    }
  1022:
  1023:    // Index returns the index of the first instance of substr in s, or -1 if substr is not present in s.
=>1024:    func Index(s, substr string) int {
  1025:        n := len(substr)
  1026:        switch {
  1027:        case n == 0:
  1028:            return 0
  1029:        case n == 1:
(dlv) n
> strings.Index() /Users/qinshixian/.g/go/src/strings/strings.go:1025 (PC: 0x10ac36f)
  1020:        return s == t
  1021:    }
  1022:
  1023:    // Index returns the index of the first instance of substr in s, or -1 if substr is not present in s.
  1024:    func Index(s, substr string) int {
=>1025:        n := len(substr)
  1026:        switch {
  1027:        case n == 0:
  1028:            return 0
  1029:        case n == 1:
  1030:            return IndexByte(s, substr[0])
(dlv) n
> strings.Index() /Users/qinshixian/.g/go/src/strings/strings.go:1027 (PC: 0x10ac380)
  1022:
  1023:    // Index returns the index of the first instance of substr in s, or -1 if substr is not present in s.
  1024:    func Index(s, substr string) int {
  1025:        n := len(substr)
  1026:        switch {
=>1027:        case n == 0:
  1028:            return 0
  1029:        case n == 1:
  1030:            return IndexByte(s, substr[0])
  1031:        case n == len(s):
  1032:            if substr == s {
(dlv) p n
6
(dlv) p len(s)
35
(dlv) n
> strings.Index() /Users/qinshixian/.g/go/src/strings/strings.go:1029 (PC: 0x10ac3a4)
  1024:    func Index(s, substr string) int {
  1025:        n := len(substr)
  1026:        switch {
  1027:        case n == 0:
  1028:            return 0
=>1029:        case n == 1:
  1030:            return IndexByte(s, substr[0])
  1031:        case n == len(s):
  1032:            if substr == s {
  1033:                return 0
  1034:            }
(dlv) n
> strings.Index() /Users/qinshixian/.g/go/src/strings/strings.go:1031 (PC: 0x10ac403)
  1026:        switch {
  1027:        case n == 0:
  1028:            return 0
  1029:        case n == 1:
  1030:            return IndexByte(s, substr[0])
=>1031:        case n == len(s):
  1032:            if substr == s {
  1033:                return 0
  1034:            }
  1035:            return -1
  1036:        case n > len(s):
(dlv)
> strings.Index() /Users/qinshixian/.g/go/src/strings/strings.go:1036 (PC: 0x10ac494)
  1031:        case n == len(s):
  1032:            if substr == s {
  1033:                return 0
  1034:            }
  1035:            return -1
=>1036:        case n > len(s):
  1037:            return -1
  1038:        case n <= bytealg.MaxLen:
  1039:            // Use brute force when s and substr both are small
  1040:            if len(s) <= bytealg.MaxBruteForce {
  1041:                return bytealg.IndexString(s, substr)
(dlv) n
> strings.Index() /Users/qinshixian/.g/go/src/strings/strings.go:1038 (PC: 0x10ac4cf)
  1033:                return 0
  1034:            }
  1035:            return -1
  1036:        case n > len(s):
  1037:            return -1
=>1038:        case n <= bytealg.MaxLen:
  1039:            // Use brute force when s and substr both are small
  1040:            if len(s) <= bytealg.MaxBruteForce {
  1041:                return bytealg.IndexString(s, substr)
  1042:            }
  1043:            c0 := substr[0]
(dlv) p bytealg.MaxLen
63
(dlv) n
> strings.Index() /Users/qinshixian/.g/go/src/strings/strings.go:1040 (PC: 0x10ac4e7)
  1035:            return -1
  1036:        case n > len(s):
  1037:            return -1
  1038:        case n <= bytealg.MaxLen:
  1039:            // Use brute force when s and substr both are small
=>1040:            if len(s) <= bytealg.MaxBruteForce {
  1041:                return bytealg.IndexString(s, substr)
  1042:            }
  1043:            c0 := substr[0]
  1044:            c1 := substr[1]
  1045:            i := 0
(dlv) p len(s)
35
(dlv) p bytealg.MaxBruteForce
64
(dlv) n
> strings.Index() /Users/qinshixian/.g/go/src/strings/strings.go:1041 (PC: 0x10ac4ff)
  1036:        case n > len(s):
  1037:            return -1
  1038:        case n <= bytealg.MaxLen:
  1039:            // Use brute force when s and substr both are small
  1040:            if len(s) <= bytealg.MaxBruteForce {
=>1041:                return bytealg.IndexString(s, substr)
  1042:            }
  1043:            c0 := substr[0]
  1044:            c1 := substr[1]
  1045:            i := 0
  1046:            t := len(s) - n + 1
(dlv) s bytealg.IndexString
> internal/bytealg.IndexString() /Users/qinshixian/.g/go/src/internal/bytealg/index_amd64.s:18 (PC: 0x1002840)
Warning: debugging optimized function
    13:        MOVQ DI, R10
    14:        LEAQ ret+48(FP), R11
    15:        JMP  indexbody<>(SB)
    16:
    17:    TEXT ·IndexString(SB),NOSPLIT,$0-40
=>  18:        MOVQ a_base+0(FP), DI
    19:        MOVQ a_len+8(FP), DX
    20:        MOVQ b_base+16(FP), R8
    21:        MOVQ b_len+24(FP), AX
    22:        MOVQ DI, R10
    23:        LEAQ ret+32(FP), R11
(dlv) bp
Breakpoint runtime-fatal-throw (enabled) at 0x1032e20 for runtime.throw() /Users/qinshixian/.g/go/src/runtime/panic.go:1188 (0)
Breakpoint unrecovered-panic (enabled) at 0x1033180 for runtime.fatalpanic() /Users/qinshixian/.g/go/src/runtime/panic.go:1271 (0)
    print runtime.curg._panic.arg
Breakpoint 1 (enabled) at 0x10acd6f for main.main() ./a.go:8 (1)
Breakpoint 2 (enabled) at 0x10ac1e6 for strings.Contains() /Users/qinshixian/.g/go/src/strings/strings.go:61 (0)
(dlv)

3.dlv debug 常用命令

  • b 打断点,例如使用 b main.main 来打断点
  • p 打印变量
  • n: 执行到下一行
  • c: 跳过此断点
  • args: 打印所有的方法参数
  • locals 打印出所有的本地变量
  • l 列出断点最近几行的代码
  • bp: 展示出所有的断点
  • q: 退出


相关文章
|
3月前
|
Cloud Native Go 开发工具
不改一行代码轻松玩转 Go 应用微服务治理
为了更好的进行 Go 应用微服务治理,提高研发效率和系统稳定性,本文将介绍 MSE 微服务治理方案,无需修改业务代码,实现治理能力。
19848 9
|
14天前
|
安全 Go 开发者
代码之美:Go语言并发编程的优雅实现与案例分析
【10月更文挑战第28天】Go语言自2009年发布以来,凭借简洁的语法、高效的性能和原生的并发支持,赢得了众多开发者的青睐。本文通过两个案例,分别展示了如何使用goroutine和channel实现并发下载网页和构建并发Web服务器,深入探讨了Go语言并发编程的优雅实现。
28 2
|
17天前
|
JSON 监控 安全
go语言选择合适的工具和库
【10月更文挑战第17天】
11 2
Go语言的条件控制语句及循环语句的学习笔记
本文是Go语言的条件控制语句和循环语句的学习笔记,涵盖了if语句、if-else语句、if嵌套语句、switch语句、select语句以及for循环和相关循环控制语句的使用方法。
Go语言的条件控制语句及循环语句的学习笔记
|
1月前
|
JSON 搜索推荐 Go
ZincSearch搜索引擎中文文档及在Go语言中代码实现
ZincSearch官网及开发文档均为英文,对非英语用户不够友好。GoFly全栈开发社区将官方文档翻译成中文,并增加实战经验和代码,便于新手使用。本文档涵盖ZincSearch在Go语言中的实现,包括封装工具库、操作接口、统一组件调用及业务代码示例。官方文档https://zincsearch-docs.zinc.dev;中文文档https://doc.goflys.cn/docview?id=41。
|
2月前
|
存储 Go
Go: struct 结构体类型和指针【学习笔记记录】
本文是Go语言中struct结构体类型和指针的学习笔记,包括结构体的定义、成员访问、使用匿名字段,以及指针变量的声明使用、指针数组定义使用和函数传参修改值的方法。
|
3月前
|
缓存 NoSQL 数据库
go-zero微服务实战系列(五、缓存代码怎么写)
go-zero微服务实战系列(五、缓存代码怎么写)
|
2月前
|
人工智能 算法 搜索推荐
Go学习笔记-代码调
近年来,人工智能技术飞速发展,Cody作为由Sourcegraph开发的一款AI驱动编码助手,应运而生。它不仅提供代码预测与补全,还能深度理解代码上下文,为开发者提供准确建议,提升编码效率和质量。Cody能识别潜在错误并提出修复建议,缩短调试时间,同时进行智能代码审查,帮助优化代码结构和风格。未来,随着AI技术进步,Cody将不断学习优化,成为开发者不可或缺的伙伴,推动编程领域的创新与发展。
33 0
|
3月前
|
程序员 测试技术 Go
用 Go 编写简洁代码的最佳实践
用 Go 编写简洁代码的最佳实践
|
3月前
|
缓存 测试技术 Go
使用Singleflight优化Go代码
使用Singleflight优化Go代码