使用 dlv 调试 go 程序【案例】

使用 dlv 调试 go 程序

虽然使用 Goland 在 Windows 上开发 go 程序非常方便,但是有些场景,必须在 Linux 环境上进行调试,所以抽会研究了一下,还是非常方便的。不了解的小伙伴,可以按照我的方法尝试一下。

代码

这是一个通过 go-micro broker 使用 kafka 的 demo

!!!<-time.After(time.Second * 360)!!!, 由于 main 函数中启动了两个 goroutine, 若此处 sleep 的时间不够长,我们的 debug 很容易会因为 main 所在的 goroutine 而退出。可能对 debug 造成比较大的困惑,请注意。

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/micro/go-micro/v2/broker"
	"github.com/micro/go-micro/v2/config/cmd"
	_ "github.com/micro/go-plugins/broker/kafka/v2"
)

var (
	topic = "go.micro.topic.foo"
)

func pub() {
	tick := time.NewTicker(time.Second)
	i := 0
	for _ = range tick.C {
		msg := &broker.Message{
			Header: map[string]string{
				"id": fmt.Sprintf("%d", i),
			},
			Body: []byte(fmt.Sprintf("%d: %s", i, time.Now().String())),
		}
		if err := broker.Publish(topic, msg); err != nil {
			log.Printf("[pub] failed: %v", err)
		} else {
			fmt.Println("[pub] pubbed message:", string(msg.Body))
		}
		i++
	}
}

func sub() {
	_, err := broker.Subscribe(topic, func(p broker.Event) error {
		fmt.Println("[sub] received message:", string(p.Message().Body), "header", p.Message().Header)
		return nil
	})
	if err != nil {
		fmt.Println(err)
	}
}

func main() {
	cmd.Init()

	if err := broker.Init(); err != nil {
		log.Fatalf("Broker Init error: %v", err)
	}
	if err := broker.Connect(); err != nil {
		log.Fatalf("Broker Connect error: %v", err)
	}

	go pub()
	go sub()

	<-time.After(time.Second * 360)
}

go.mod

module demo1

go 1.13

编译

go build -gcflags=all="-N -l"  ## 必须这样编译,才能用gdb打印出变量,第二个是小写的L,不是大写的i

启动

启动报错

由于 main.go 中与引用库中冲突,重新修改

$ dlv exec ./demo1 -- -broker kafka -broker_address 192.168.0.111:9092
Type 'help' for list of commands.
(dlv) b main.go:47
Command failed: Location "main.go:47" ambiguous: /home/luojie/gopath/pkg/mod/github.com/nats-io/[email protected]/main.go, /home/luojie/test/go/go-micro-kafka/demo1/main.go…

调整

加上路径之后,就可以解决文件名冲突的问题

(dlv) b demo1/main.go:47
Breakpoint 1 set at 0xe9ab98 for main.main() ./main.go:47

开始执行

(dlv) c
> main.main() ./main.go:47 (hits goroutine(1):1 total:1) (PC: 0x131c59f)
    42:			fmt.Println(err)
    43:		}
    44:	}
    45:	
    46:	func main() {
=>  47:		cmd.Init()
    48:	
    49:		if err := broker.Init(); err != nil {
    50:			log.Fatalf("Broker Init error: %v", err)
    51:		}
    52:		if err := broker.Connect(); err != nil {

增加其它断点

可以看到测试断点可以正常工作,此时我要增加其它断点,我真正关注的位置: 我想了解怎么从 kafka 中取出数据的

(dlv) b consumer_group.go:552
Breakpoint 2 set at 0x12b71bb for github.com/Shopify/sarama.newConsumerGroupSession() /home/luojie/gopath/pkg/mod/github.com/!shopify/[email protected]/consumer_group.go:552

继续往下走

使用 bt 指令可以非常方便看到调用顺序,非常方便研究源码

> github.com/Shopify/sarama.newConsumerGroupSession() /home/luojie/gopath/pkg/mod/github.com/!shopify/[email protected]/consumer_group.go:552 (hits goroutine(31):1 total:1) (PC: 0x12b71bb)
   547:		waitGroup       sync.WaitGroup
   548:		releaseOnce     sync.Once
   549:		hbDying, hbDead chan none
   550:	}
   551:	
=> 552:	func newConsumerGroupSession(ctx context.Context, parent *consumerGroup, claims map[string][]int32, memberID string, generationID int32, handler ConsumerGroupHandler) (*consumerGroupSession, error) {
   553:		// init offset manager
   554:		offsets, err := newOffsetManagerFromClient(parent.groupID, memberID, generationID, parent.client)
   555:		if err != nil {
   556:			return nil, err
   557:		}
(dlv) bt
0  0x00000000012b71bb in github.com/Shopify/sarama.newConsumerGroupSession
   at /home/luojie/gopath/pkg/mod/github.com/!shopify/[email protected]/consumer_group.go:552
1  0x00000000012b3fa1 in github.com/Shopify/sarama.(*consumerGroup).newSession
   at /home/luojie/gopath/pkg/mod/github.com/!shopify/[email protected]/consumer_group.go:298
2  0x00000000012b2e71 in github.com/Shopify/sarama.(*consumerGroup).Consume
   at /home/luojie/gopath/pkg/mod/github.com/!shopify/[email protected]/consumer_group.go:169
3  0x000000000131b484 in github.com/micro/go-plugins/broker/kafka.(*kBroker).Subscribe.func1
   at /home/luojie/gopath/pkg/mod/github.com/micro/go-plugins/broker/[email protected]/kafka.go:200
4  0x0000000000465e71 in runtime.goexit
   at /home/luojie/go/src/runtime/asm_amd64.s:1357

你可能感兴趣的:(go-micro,golang,dlv)