您现在的位置是:首页 >其他 >Go并发情况下debug调试无法进入所需调试goroutine,附带并发测试代码网站首页其他

Go并发情况下debug调试无法进入所需调试goroutine,附带并发测试代码

furfur-jiang 2024-06-17 10:13:52
简介Go并发情况下debug调试无法进入所需调试goroutine,附带并发测试代码

大部分情况
问题
在使用go语法的时候,由于并发情况,只能调试一个goroutine,但存在随机性,难指定
在这里插入图片描述
找到你所需的线程直接切换即可跳转。没有找到同时调试多个的办法,理论上是不行的,不然就不叫并发了。


特殊情况:此线程监控某事件,执行一半

首先断点打到用go修饰的函数,在go修饰的函数里面打个断点
执行debug的时候,在到了go修饰函数的时候使用resume program直接进入修饰函数里面(step into 进不去,run to cursor也可以,鼠标放在所需位置即可)
在这里插入图片描述
此时,线程会切换到你的go函数线程
在这里插入图片描述
多次尝试都能进入此断点

测试代码

go黑皮书《The Go Programming Language》回声案例
reverb.go模拟服务端,即山谷
netcat.go模拟客户端,即人

如果要测试并发,先跑起来reverb.go,然后netcat执行go build netcat.go打包二进制文件,然后.netcat执行,执行两个以上测试

使用

reverb.go

// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/

// See page 224.

// Reverb2 is a TCP server that simulates an echo.
package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"strings"
	"time"
)

func echo(c net.Conn, shout string, delay time.Duration) {
	fmt.Fprintln(c, "	", strings.ToUpper(shout))
	time.Sleep(delay)
	fmt.Fprintln(c, "	", shout)
	time.Sleep(delay)
	fmt.Fprintln(c, "	", strings.ToLower(shout))
}

// !+
func handleConn(c net.Conn) {
	input := bufio.NewScanner(c)
	for input.Scan() {
		go echo(c, input.Text(), 3*time.Second)
	}
	// NOTE: ignoring potential errors from input.Err()
	c.Close()
}

//!-

func main() {
	l, err := net.Listen("tcp", "localhost:8000")
	if err != nil {
		log.Fatal(err)
	}
	for {
		conn, err := l.Accept()
		if err != nil {
			log.Print(err) // e.g., connection aborted
			continue
		}
		go handleConn(conn)
	}
}

netcat.go

package main

import (
	"io"
	"log"
	"net"
	"os"
)

func main() {
	conn, err := net.Dial("tcp", "localhost:8000")
	if err != nil {
		log.Fatal(err)
	}
	done := make(chan struct{})
	go readFromConn(conn, done)
	mustCopy(conn, os.Stdin)
	go mygoroutine()
	conn.Close()
	<-done // wait for background goroutine to finish
	log.Println("end")
}

func mustCopy(dst io.Writer, src io.Reader) {
	if _, err := io.Copy(dst, src); err != nil {
		log.Fatal(err)
	}
}
func mygoroutine() {
	log.Println("okkk")
}
func readFromConn(conn net.Conn, done chan struct{}) {
	log.Println("done1")
	io.Copy(os.Stdout, conn) // NOTE: ignoring errors
	log.Println("done")
	done <- struct{}{} // signal the main goroutine
}

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。