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月前
|
Go 索引
掌握Go语言:Go语言范围,优雅遍历数据结构,简化代码操作实战解析(24)
掌握Go语言:Go语言范围,优雅遍历数据结构,简化代码操作实战解析(24)
|
2月前
|
算法 程序员 编译器
美丽的代码:规范go应用代码注释
【6月更文挑战第30天】本文介绍注释应与代码同步,避免误导,且关键点解释。使用LLVM构建编译器示例展示Go语言规范。注释虽有局限,但在解释复杂逻辑、业务规则时仍有其价值。程序员需平衡注释与代码的关系,创造更优的代码。
1022 0
美丽的代码:规范go应用代码注释
|
12天前
|
程序员 测试技术 Go
用 Go 编写简洁代码的最佳实践
用 Go 编写简洁代码的最佳实践
|
12天前
|
缓存 测试技术 Go
使用Singleflight优化Go代码
使用Singleflight优化Go代码
|
12天前
|
Shell Go
Go 语言Air 工具使用入门
在Go开发中,频繁的手动重启应用以加载新代码既耗时又低效。为此,我们引入了Air——一款专为Go项目设计的自动重载工具。Air通过监听文件变化,实现代码更改后的自动编译与运行,极大提升了开发效率。本文将指导你完成Air的安装与配置,包括如何启动Air、忽略临时文件以及理解其工作原理,让Go项目开发更加流畅高效。
|
11天前
|
Kubernetes 数据可视化 Java
|
12天前
|
JSON 数据库连接 Go
10个令人惊叹的Go语言技巧,让你的代码更加优雅
10个令人惊叹的Go语言技巧,让你的代码更加优雅
|
17天前
|
关系型数据库 MySQL Go
Go - 代码生成工具
Go - 代码生成工具
23 3
|
17天前
|
JSON Go 数据格式
Go - 使用工具生成易读的 Protocol 文档
Go - 使用工具生成易读的 Protocol 文档
12 1