This is a creation in Article, where the information may have evolved or changed.
Go can be said to be one of the hottest emerging languages in recent years, when people see distributed and Big Data think of Go,
This series of articles will study the Golang source code to analyze the internal implementation principle,
Unlike CORECLR, the source code of Golang has been studied by many people, and I will focus on the parts that they have not mentioned.
Another point and coreclr different is that the source code of Golang is very easy to understand , the comments are very rich ,
It's obvious that Google's engineers are writing code that other people will look at this code.
Although the code is easy to understand, it is necessary to actually run and debug them to get a better understanding.
This series of analysis of the Golang source code is Google's official implementation of the 1.9.2, does not apply to other versions and other implementations such as GCCGO,
The operating environment is Ubuntu 16.04 LTS 64bit.
Compiling Golang source code
The Go source code is written in go, and compiling requires a running go.
First we download the source code and binary files from our official website.
Go1.9.2.src.tar.gz
Go1.9.2.linux-amd64.tar.gz
Note the two compressed packages extracted from the folder name are go, we extracted to the following directory:
源代码: ~/git_go/go_src二进制: ~/git_go/go_bin
You need to set environment variables before compiling go.
GOROOT_BOOTSTRAP
is the directory where the Go binary folder is located,
GO_GCFLAGS
Is the parameter used when compiling the go.
export GOROOT_BOOTSTRAP=~/git_go/go_binexport GO_GCFLAGS="-N -l"
The -N
parameters here represent forbidden optimizations, the -l
parameters are forbidden inline, and go is embedded in the runtime's binary when compiling the target program.
Prohibiting optimizations and inline makes it easier to debug functions in the Runtime (runtime).
When you are ready, you can go to the Go Source code folder to perform the all.bash
compilation:
The results of the compilation are as ~/git_go/go_src/bin
follows:
Debug Golang Source code
I used the lldb in the previous CORECLR series, and I continued to use this debugger in this series.
The LLDB 4.0 is used in this series.
Take the following source code (HELLO.GO) as an example:
package main ( "FMT" "time" ) func Printnumber (from, to int , C chan int ) {for x: = from; x <= to; X + + {FMT. Printf ( "%d \n " , x) time. Sleep (1 * time. Millisecond)} C <-0 }func main () {c: = make (chan int , 3 ) go< /span> Printnumber (1 , 3 , c) go Printnumber ( 4 , 6 , C) _, _ = <-C, <-C}
Compile the source code using the following command, the parameter here is the -l
same as above, if necessary can also add -N
parameters:
~/git_go/go_src/bin/go build -gcflags "-l" hello.go
Run with Lldb after compiling:
lldb ./hello
The naming convention for the function symbol name in Go is, for example, the symbolic name of the main function is the name of the 包名称.函数名称
main.main
symbol in the runtime newobject
runtime.newobject
.
First give the main function the next breakpoint and then run:
You can see that the main function has been successfully entered and there is a source code hint.
Next the breakpoint is given by file name and number of lines:
Then look at the assembly code for the function:
You can view this document for a LLDB command.
In the environment I'm using, lldb can take a normal down breakpoint, step in and step through the go code or assemble instructions,
However, the value of the print variable output may be wrong , even if optimization is not turned on.
Although the function of printing variables is not easy to use, we can still directly let go output the values we want,
For example, modify runtime/malloc.go
the output size of the Arena|spans|bitmap area in the current environment:
After the modification src
, enter and execute ./make.bash
, then recompile the target program, run:
You can see that the current environment arena is 512G, spans is 512M, bitmap is 16G.
This method is rather stupid, but it can output the value we want in any case.
In addition, the Go Runtime (runtime) source code is included in the target file,
For example runtime.newobject
, you can debug the Go's own source code for the next breakpoint.
Reference links
https://golang.org
Https://golang.org/doc/install/source
Https://golang.org/doc/gdb
Http://lldb.llvm.org/tutorial.html
Http://legendtkl.com/archives
Next I will analyze Golang's task scheduling mechanism and the specific implementation of the Tri-color GC, so please look forward to it.