GO:源码的修改、调试
需求:
1.通过修改GO源码逻辑,实现想要的自定义功能。
例如:修改GO的net/http等相关包的代码,内嵌针对HTTP请求/应答的原始消息输出到日志,方便定位排查。
2.临时修改GO源码逻辑,进行复杂的调试,便于理解GO代码。
例如:学习GO的net/http包,看着一长串的调用【深度、广度】,如果能调试输出,是否更便于理解代码呢?
实现:
直接修改GO源码,编译。
例子:
我的开发环境:
[test1280@localhost ~]$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/test1280/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/test1280/gopath"
GOPROXY="https://goproxy.io"
GORACE=""
GOROOT="/home/test1280/go"
GOTMPDIR=""
GOTOOLDIR="/home/test1280/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build447053725=/tmp/go-build -gno-record-gcc-switches"
我的目录结构:
[test1280@localhost ~]$ tree -L 1
.
├── go
├── go1.12.5.linux-amd64.tar.gz
├── gopath
└── myproject
3 directories, 1 file
[test1280@localhost ~]$ tree -L 2
.
├── go
│ ├── api
│ ├── AUTHORS
│ ├── bin
│ ├── CONTRIBUTING.md
│ ├── CONTRIBUTORS
│ ├── doc
│ ├── favicon.ico
│ ├── lib
│ ├── LICENSE
│ ├── misc
│ ├── PATENTS
│ ├── pkg
│ ├── README.md
│ ├── robots.txt
│ ├── src
│ ├── test
│ └── VERSION
├── go1.12.5.linux-amd64.tar.gz
├── gopath
└── myproject
├── go.mod
├── main.go
└── myproject
11 directories, 13 files
我的测试代码:
[test1280@localhost myproject]$ cat go.mod
module myproject
go 1.12
[test1280@localhost myproject]$ cat main.go
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
resp, err := http.Get("http://127.0.0.1:8080/")
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
正常编译运行:
[test1280@localhost myproject]$ go build && ./myproject
{
"current": "Sat Aug 17 02:56:09 2019"
}
想要达到的效果:调用http.Get时,记录一条日志到标准输出。
修改GO源码:
我的GO源码位置从上面的信息中可知是在“$HOME/go/src”,修改net/http/client.go中的Get函数:
func Get(url string) (resp *Response, err error) {
fmt.Println("test1280: call http.Get()")
return DefaultClient.Get(url)
}
备注:由于client.go中已import “fmt”,因此我添加的fmt.Println【内嵌的自定义逻辑】不需要再额外引入。
重新编译GO项目:
[test1280@localhost myproject]$ go build && ./myproject
test1280: call http.Get()
{
"current": "Sat Aug 17 03:04:02 2019"
}
- 修改的是$HOME/go/src中的GO源码;
- 重新编译的是GO应用(GO工具链发现GO源码有被修改,重新编译GO源码以及GO应用);
- 输出将显示在stdout、stderr;(默认情况下,例如重定向输出例外)
如果你想要调试GO源码,可像我一样增加fmt.Print输出信息,这样你重新编译GO程序,调试将显示在终端。
如果你想要改变GO源码,例如记录HTTP请求/应答原始的报文,可将其内嵌到net/http等包中,记录到日志。