draveness / blog-comments

面向信仰编程
https://draveness.me
140 stars 6 forks source link

如何调试 Go 语言源代码 | Go 语言设计与实现 · /golang-debug #215

Closed draveness closed 2 years ago

draveness commented 4 years ago

https://draveness.me/golang/docs/part1-prerequisite/ch01-prepare/golang-debug/

如何调试 Go 语言源代码

shuff1e commented 4 years ago

赞,可以出本书了

ZhenhangTung commented 4 years ago

分享在这个过程中我遇到的前置步骤:

  1. 克隆源代码并切到版本分支上
  2. 运行./src/make.bash如果报错make.bash must be run from $GOROOT/src,可以在/src文件夹下运行./make.bash
  3. 我添加println("draven")并没有显示draven字符串,一度以为我自己编译和使用出了问题,最后我添加了Fprintln(os.Stdout, "draven")能够显示确信我编译正确且使用了正确的编译包
draveness commented 4 years ago

分享在这个过程中我遇到的前置步骤:

  1. 克隆源代码并切到版本分支上
  2. 运行./src/make.bash如果报错make.bash must be run from $GOROOT/src,可以在/src文件夹下运行./make.bash
  3. 我添加println("draven")并没有显示draven字符串,一度以为我自己编译和使用出了问题,最后我添加了Fprintln(os.Stdout, "draven")能够显示确信我编译正确且使用了正确的编译包

最后一个你确定么,我是可以打印的,你修改的是哪个函数?

yanjinbin commented 4 years ago

博主 什么时候出书 支持一把

ZhenhangTung commented 4 years ago

分享在这个过程中我遇到的前置步骤:

  1. 克隆源代码并切到版本分支上
  2. 运行./src/make.bash如果报错make.bash must be run from $GOROOT/src,可以在/src文件夹下运行./make.bash
  3. 我添加println("draven")并没有显示draven字符串,一度以为我自己编译和使用出了问题,最后我添加了Fprintln(os.Stdout, "draven")能够显示确信我编译正确且使用了正确的编译包

最后一个你确定么,我是可以打印的,你修改的是哪个函数?

我尝试重复了整个操作,发现之前提供的信息有误。我的修改是否生效取决于我是否对src/cmd/go/main.go进行过修改。

  1. 在我不改src/cmd/go/main.go的时候,我对fmt/print.go文件下的func Sprintln(a ...interface{})改动没有效果。
  2. 修改了src/cmd/go/main.go之后,如我在Sprintln下加了个println("cheers")生效了。

Go版本位于83b181c68b,对应Go1.14.4

没有改动src/cmd/go/main.go

编译:

➜  src git:(83b181c68b) ✗ ./make.bash
Building Go cmd/dist using /usr/local/Cellar/go/1.14.4/libexec. (go1.14.4 darwin/amd64)
Building Go toolchain1 using /usr/local/Cellar/go/1.14.4/libexec.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for darwin/amd64.
---
Installed Go for darwin/amd64 in /Users/guiwu/Go-Code/src/goroot
Installed commands in /Users/guiwu/Go-Code/src/goroot/bin

运行:

➜  learn-go-src cat main.go
package main

import "fmt"

func main()  {
    fmt.Println("yeah!!!")
}
➜  learn-go-src /Users/guiwu/Go-Code/src/goroot/bin/go run main.go
yeah!!!

改动src/cmd/go/main.go

src/cmd/go/main.go:

func main() {
    _ = go11tag
    flag.Usage = base.Usage
    flag.Parse()
    log.SetFlags(0)

    fmt.Println("main function")
    # 剩余逻辑
}

fmt/print.go:

// Println formats using the default formats for its operands and writes to standard output.
// S0paces are always added between operands and a newline is appended.
// It returns the number of bytes written and any write error encountered.
func Println(a ...interface{}) (n int, err error) {
    println("cheers")
    return Fprintln(os.Stdout, a...)
}

编译:

src git:(83b181c68b) ✗ ./make.bash
Building Go cmd/dist using /usr/local/Cellar/go/1.14.4/libexec. (go1.14.4 darwin/amd64)
Building Go toolchain1 using /usr/local/Cellar/go/1.14.4/libexec.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
cheers
main function
Building Go toolchain3 using go_bootstrap and Go toolchain2.
cheers
main function
Building packages and commands for darwin/amd64.
cheers
main function
---
Installed Go for darwin/amd64 in /Users/guiwu/Go-Code/src/goroot
Installed commands in /Users/guiwu/Go-Code/src/goroot/bin

运行

➜  learn-go-src /Users/guiwu/Go-Code/src/goroot/bin/go run main.go
cheers
main function
yeah!!!

出现这个现象的原因我还未调研出来,不影响自己学习的方案就是在src/cmd/go/main.go里保留修改,比如打印一个空字符串,可以让自己学习下去,期间再慢慢深究原因。

hapiman commented 4 years ago

看了其他的几篇文章,非常值得学习。

xiyichan commented 3 years ago

如果要调试go语言源码中的编译器代码,即cmd/compile里面,不知道有何好办法,我用过gc和dlv但是很多过程都调试不出来,不知道如何使用。

draveness commented 3 years ago

如果要调试go语言源码中的编译器代码,即cmd/compile里面,不知道有何好办法,我用过gc和dlv但是很多过程都调试不出来,不知道如何使用。

你试过我这里的方法么,修改源代码然后构建出 Go 的二进制,用新的 Go 二进制编译源码

xiyichan commented 3 years ago

是使用./make.bash吧?这个我试过,但是有时候修改一些源码编译不通过,所以使用debug的方法看看就是什么函数负责什么功能。我现在往go提交PR也是用./make.bash编译好,然后用all.bash来测试。但是这样怎么说呢,我就想一步一步看代码怎么运行。

------------------ 原始邮件 ------------------ 发件人: "Draven"<notifications@github.com>; 发送时间: 2020年9月16日(星期三) 上午8:43 收件人: "draveness/blog-comments"<blog-comments@noreply.github.com>; 抄送: "陈力锋"<2863768433@qq.com>; "Comment"<comment@noreply.github.com>; 主题: Re: [draveness/blog-comments] 如何调试 Go 语言源代码 | Go 语言设计与实现 · /golang-debug (#215)

如果要调试go语言源码中的编译器代码,即cmd/compile里面,不知道有何好办法,我用过gc和dlv但是很多过程都调试不出来,不知道如何使用。

你试过我这里的方法么,修改源代码然后构建出 Go 的二进制,用新的 Go 二进制编译源码

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

draveness commented 3 years ago

@ZhenhangTung 出现这个现象的原因我还未调研出来,不影响自己学习的方案就是在src/cmd/go/main.go里保留修改,比如打印一个空字符串,可以让自己学习下去,期间再慢慢深究原因。

说不定是因为编译缓存,不过我也不能确定

xiyichan commented 3 years ago

行吧,主要是想在cmd/compile这个包里面做点贡献,然后有很多文件的代码很难看懂有什么作用。我还没试过在cmd/go/里面做过修改。

------------------ 原始邮件 ------------------ 发件人: "Draven"<notifications@github.com>; 发送时间: 2020年9月16日(星期三) 中午11:18 收件人: "draveness/blog-comments"<blog-comments@noreply.github.com>; 抄送: "陈力锋"<2863768433@qq.com>; "Comment"<comment@noreply.github.com>; 主题: Re: [draveness/blog-comments] 如何调试 Go 语言源代码 | Go 语言设计与实现 · /golang-debug (#215)

@ZhenhangTung 出现这个现象的原因我还未调研出来,不影响自己学习的方案就是在src/cmd/go/main.go里保留修改,比如打印一个空字符串,可以让自己学习下去,期间再慢慢深究原因。

说不定是因为编译缓存,不过我也不能确定

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

ClockworkTree commented 3 years ago

请教下大佬,想运行标准库的test,但是有的包遇到了use of internal package net/http/internal not allowed的问题。如果包内没有引用internal的包就可以调试test,比如database,这个有什么好的解决方法吗

draveness commented 3 years ago

请教下大佬,想运行标准库的test,但是有的包遇到了use of internal package net/http/internal not allowed的问题。如果包内没有引用internal的包就可以调试test,比如database,这个有什么好的解决方法吗

你从外部引用 internal 包是不允许的

ClockworkTree commented 3 years ago

请教下大佬,想运行标准库的test,但是有的包遇到了use of internal package net/http/internal not allowed的问题。如果包内没有引用internal的包就可以调试test,比如database,这个有什么好的解决方法吗

你从外部引用 internal 包是不允许的

我是直接下载golang/go tag版本压缩文件,用goland直接打开下载的golang/go目录、来运行标准库里自己的test(不是我自己写的,从外部import的test),如果是非internal包,我直接对源码的改动,跑标准库自己的test是可以跑到的,说明test使用了goland打开的我自己下载源码而不是goroot里的sdk,但是遇到有internal的包,编译标准库test就会失败。

image

draveness commented 3 years ago

我是直接下载golang/go tag版本压缩文件,用goland直接打开下载的golang/go目录、来运行标准库里自己的test(不是我自己写的,从外部import的test),如果是非internal包,我直接对源码的改动,跑标准库自己的test是可以跑到的,说明test使用了goland打开的我自己下载源码而不是goroot里的sdk,但是遇到有internal的包,编译标准库test就会失败。

我没有用过 Goland,大概看了下你提出的问题,我有两个疑问:

  1. 使用命令行直接跑测试可以执行么
  2. 编译错误的提示是什么,这里只看到了运行成功的输出
Benjmmi commented 3 years ago

汪明 是你?

draveness commented 3 years ago

汪明 是你?

不是

tangximing commented 3 years ago

@ClockworkTree

请教下大佬,想运行标准库的test,但是有的包遇到了use of internal package net/http/internal not allowed的问题。如果包内没有引用internal的包就可以调试test,比如database,这个有什么好的解决方法吗

你从外部引用 internal 包是不允许的

我是直接下载golang/go tag版本压缩文件,用goland直接打开下载的golang/go目录、来运行标准库里自己的test(不是我自己写的,从外部import的test),如果是非internal包,我直接对源码的改动,跑标准库自己的test是可以跑到的,说明test使用了goland打开的我自己下载源码而不是goroot里的sdk,但是遇到有internal的包,编译标准库test就会失败。

image

试试把GOPATH改一下,指向golang/go

ClockworkTree commented 3 years ago

@tangximing 会报 internal not allowed的错误,需要把所有的internal的前面加个std/ 前缀,但是运行会遇到应该 golink 没有生效会有target找不到的错误

ClockworkTree commented 3 years ago

@tangximing

@ClockworkTree

请教下大佬,想运行标准库的test,但是有的包遇到了use of internal package net/http/internal not allowed的问题。如果包内没有引用internal的包就可以调试test,比如database,这个有什么好的解决方法吗

你从外部引用 internal 包是不允许的

我是直接下载golang/go tag版本压缩文件,用goland直接打开下载的golang/go目录、来运行标准库里自己的test(不是我自己写的,从外部import的test),如果是非internal包,我直接对源码的改动,跑标准库自己的test是可以跑到的,说明test使用了goland打开的我自己下载源码而不是goroot里的sdk,但是遇到有internal的包,编译标准库test就会失败。

image

试试把GOPATH改一下,指向golang/go

试了下,通过make.bash 重新编译后,将GOROOT指向重新编译后的目录是可以滴,GOPATH随意就好

tangximing commented 3 years ago

@ClockworkTree 我这边只设置了GOPATH就可以了 image

gengjiawen commented 3 years ago

出书+1,顺便问下 本网站 有GitHub链接吗?

HeisenbergV commented 3 years ago

用了好几天才勉强看完,写的太好了,谢谢,感觉水平提高了一个档次。

gostudying commented 3 years ago

图能看懂,涉及到源码的部分就看不懂了。我太菜了。

polunzh commented 3 years ago

代码块的高亮好像有问题,我在我浏览器上看不清: image.png

浏览器: Version 87.0.4280.88 (Official Build) (x86_64)

draveness commented 3 years ago

代码块的高亮好像有问题,我在我浏览器上看不清: image.png

浏览器: Version 87.0.4280.88 (Official Build) (x86_64)

这个我也很奇怪,我本地也不行,但是很多人都可以,也不知道是啥问题,我在 Safari 没这个问题

vclwei commented 3 years ago

@draveness

代码块的高亮好像有问题,我在我浏览器上看不清: image.png

浏览器: Version 87.0.4280.88 (Official Build) (x86_64)

这个我也很奇怪,我本地也不行,但是很多人都可以,也不知道是啥问题,我在 Safari 没这个问题

我这里也是黑色的, 可能是 prism 的问题, 作者有时间看看?

shizhz commented 3 years ago

请教博主,有更方便的方式搭建本地环境来进行调试吗?如果只能每次都生成二进制文件的话,感觉整个流程好长啊

Eason-Wan commented 3 years ago

已经看到接口那里了,想问一下能下载到本地吗,方便线下学习

sendme365 commented 3 years ago

平时用vscode debug 但是碰到一个情况就是当然input 输入是类似 (y/n) 时 。在debug steps时到这里后 就卡在这里了。因为找不到地方输入y 或者n 导致 debug steps 没有办法继续往下走。每次我只能hardcode 先。想问一下这样的情况怎么办?

OnTheWay111 commented 3 years ago

MacOS上找不到dumped,也没找到安装方法,有遇到同样问题的小伙伴吗?

draveness commented 3 years ago

平时用vscode debug 但是碰到一个情况就是当然input 输入是类似 (y/n) 时 。在debug steps时到这里后 就卡在这里了。因为找不到地方输入y 或者n 导致 debug steps 没有办法继续往下走。每次我只能hardcode 先。想问一下这样的情况怎么办?

不知道,我没用 Debugger,Hardcode 也没啥问题靠猜

MacOS上找不到dumped,也没找到安装方法,有遇到同样问题的小伙伴吗?

这里不是聊天室,建议给足上下文、清晰描述你的问题

0x1306a94 commented 3 years ago

可以在每一章的尾部添加上一页和下一页的功能吗?

draveness commented 3 years ago

可以在每一章的尾部添加上一页和下一页的功能吗?

已经实现了,可以看一下

guoyuanchao1202 commented 3 years ago

段大师,我编译成功了,但是go run的时候报错了(windows平台下,安装的go版本是1.14,编译的go版本是最新的版本), 代码是这样: package main

import "fmt"

func main() { fmt.Println("just test myGo Run") }

错误大概是这样的:# sync/atomic flag provided but not defined: -p usage: asm [options] file.s ... Flags: -D value predefined symbol with optional simple value -D=identifier=value; can be set multiple times -I value include directory; can be set multiple times -S print assembly and machine code -V print version and exit -debug dump instructions as they are parsed -dynlink support references to Go symbols defined in other shared libraries -e no limit on number of errors reported -gensymabis write symbol ABI information to output file, don't assemble -newobj use new object file format -o string output file; default foo.o for /a/b/c/foo.s as first argument -shared generate code that can be linked into a shared library -trimpath string remove prefix from recorded source file paths

internal/cpu

flag provided but not defined: -p usage: asm [options] file.s ... Flags:

guoyuanchao1202 commented 3 years ago

感觉是不是我编译的版本(git上拉取的最新代码)和机器安装的(Go1.14.1)不兼容的问题?~

lujinzhong commented 3 years ago

突然发现没登录之前是早评论的在前面,登陆之后才是晩评论的在前面哈哈哈

auula commented 3 years ago

本篇已读打卡,继续下一篇,加油

peihongch commented 3 years ago

其实只需要进入src目录执行./make.bash就可以直接编译,使用的是你本机安装的go进行编译

LiangquanLi930 commented 3 years ago

cool

snail2sky commented 3 years ago

看看 make.bash 脚本怎么写的 就知道 是啥问题了,而且这个网站有个问题,就是你写评论的时候,直接写 英文字母 s 会直接跳到搜索栏,咱换个组合键不好吗~~~

snail2sky commented 3 years ago

如果你机器上没有go环境,所以你得先装个go环境1,然后用这个Go去编译你刚修改的go源码

Lincyaw commented 3 years ago

我看不懂,但我大受震撼

DamperHa commented 3 years ago

博主,请问下,我按照你的方式修改了golang源码。但是有这么两个问题:

-=-

iam153 commented 3 years ago

按照博主的方法操作了,啥也没看到。怀疑是go版本更新导致的?

gongluck commented 2 years ago

windows运行GOSSAFUNC=main go build main.go报错:'GOSSAFUNC' 不是内部或外部命令,也不是可运行的程序 或批处理文件。是命令不一样吗?

sch-git commented 2 years ago

@ZhenhangTung

分享在这个过程中我遇到的前置步骤:

  1. 克隆源代码并切到版本分支上
  2. 运行./src/make.bash如果报错make.bash must be run from $GOROOT/src,可以在/src文件夹下运行./make.bash
  3. 我添加println("draven")并没有显示draven字符串,一度以为我自己编译和使用出了问题,最后我添加了Fprintln(os.Stdout, "draven")能够显示确信我编译正确且使用了正确的编译包

最后一个你确定么,我是可以打印的,你修改的是哪个函数?

我尝试重复了整个操作,发现之前提供的信息有误。我的修改是否生效取决于我是否对src/cmd/go/main.go进行过修改。

  1. 在我不改src/cmd/go/main.go的时候,我对fmt/print.go文件下的func Sprintln(a ...interface{})改动没有效果。
  2. 修改了src/cmd/go/main.go之后,如我在Sprintln下加了个println("cheers")生效了。

Go版本位于83b181c68b,对应Go1.14.4

没有改动src/cmd/go/main.go

编译:

➜  src git:(83b181c68b) ✗ ./make.bash
Building Go cmd/dist using /usr/local/Cellar/go/1.14.4/libexec. (go1.14.4 darwin/amd64)
Building Go toolchain1 using /usr/local/Cellar/go/1.14.4/libexec.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for darwin/amd64.
---
Installed Go for darwin/amd64 in /Users/guiwu/Go-Code/src/goroot
Installed commands in /Users/guiwu/Go-Code/src/goroot/bin

运行:

➜  learn-go-src cat main.go
package main

import "fmt"

func main()  {
  fmt.Println("yeah!!!")
}
➜  learn-go-src /Users/guiwu/Go-Code/src/goroot/bin/go run main.go
yeah!!!

改动src/cmd/go/main.go

src/cmd/go/main.go:

func main() {
  _ = go11tag
  flag.Usage = base.Usage
  flag.Parse()
  log.SetFlags(0)

  fmt.Println("main function")
  # 剩余逻辑
}

fmt/print.go:

// Println formats using the default formats for its operands and writes to standard output.
// S0paces are always added between operands and a newline is appended.
// It returns the number of bytes written and any write error encountered.
func Println(a ...interface{}) (n int, err error) {
  println("cheers")
  return Fprintln(os.Stdout, a...)
}

编译:

src git:(83b181c68b) ✗ ./make.bash
Building Go cmd/dist using /usr/local/Cellar/go/1.14.4/libexec. (go1.14.4 darwin/amd64)
Building Go toolchain1 using /usr/local/Cellar/go/1.14.4/libexec.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
cheers
main function
Building Go toolchain3 using go_bootstrap and Go toolchain2.
cheers
main function
Building packages and commands for darwin/amd64.
cheers
main function
---
Installed Go for darwin/amd64 in /Users/guiwu/Go-Code/src/goroot
Installed commands in /Users/guiwu/Go-Code/src/goroot/bin

运行

➜  learn-go-src /Users/guiwu/Go-Code/src/goroot/bin/go run main.go
cheers
main function
yeah!!!

出现这个现象的原因我还未调研出来,不影响自己学习的方案就是在src/cmd/go/main.go里保留修改,比如打印一个空字符串,可以让自己学习下去,期间再慢慢深究原因。

遇上了和你相同的问题,解决方法也一样,go 的版本是1.16.8

018429 commented 2 years ago

谢谢博主,写的太好了~

alpha-baby commented 2 years ago

@gongluck windows运行GOSSAFUNC=main go build main.go报错:'GOSSAFUNC' 不是内部或外部命令,也不是可运行的程序 或批处理文件。是命令不一样吗?

你应该去了解下再 类 unix 系统和 windows 系统中指定环境变量的区别

SnowOnion commented 2 years ago

@OnTheWay111 MacOS上找不到dumped,也没找到安装方法,有遇到同样问题的小伙伴吗?

dumped 那两行不是要执行的命令,是执行 GOSSAFUNC=main go build main.go 之后的输出 :D