获取golang源码
下载go源码 https://golang.google.cn/dl/go1.18.3.src.tar.gz
[root@iZ2zee2m456rb6bde98jpkZ ~]# wget -c https://golang.google.cn/dl/go1.18.3.src.tar.gz
--2022-06-29 14:34:55-- https://golang.google.cn/dl/go1.18.3.src.tar.gz
Resolving golang.google.cn (golang.google.cn)... 220.181.174.226
Connecting to golang.google.cn (golang.google.cn)|220.181.174.226|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://dl.google.com/go/go1.18.3.src.tar.gz [following]
--2022-06-29 14:34:56-- https://dl.google.com/go/go1.18.3.src.tar.gz
Resolving dl.google.com (dl.google.com)... 220.181.174.97
Connecting to dl.google.com (dl.google.com)|220.181.174.97|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 22838104 (22M) [application/x-gzip]
Saving to: ‘go1.18.3.src.tar.gz’
go1.18.3.src.tar.gz 100%[====================================================>] 21.78M 23.9MB/s in 0.9s
2022-06-29 14:34:57 (23.9 MB/s) - ‘go1.18.3.src.tar.gz’ saved [22838104/22838104]
解压到目录/data/
[root@iZ2zee2m456rb6bde98jpkZ ~]# tar zxf go1.18.3.src.tar.gz -C /data/
[root@iZ2zee2m456rb6bde98jpkZ ~]# cd /data
[root@iZ2zee2m456rb6bde98jpkZ data]# cd /data/go
[root@iZ2zee2m456rb6bde98jpkZ go]#
编译测试
编译golang源码需要系统中已安装一个版本的golang,这里已有的go版本
[root@iZ2zee2m456rb6bde98jpkZ go]# go version
go version go1.18.3 linux/amd64
进入源码目录查看
[root@iZ2zee2m456rb6bde98jpkZ go]# cd src/
[root@iZ2zee2m456rb6bde98jpkZ src]# ls
all.bash builtin compress encoding go.sum log net reflect strconv time
all.bat bytes container errors hash make.bash os regexp strings unicode
all.rc clean.bash context expvar html make.bat path run.bash sync unsafe
archive clean.bat crypto flag image Make.dist plugin run.bat syscall vendor
bootstrap.bash clean.rc database fmt index make.rc race.bash run.rc testdata
bufio cmd debug go internal math race.bat runtime testing
buildall.bash cmp.bash embed go.mod io mime README.vendor sort text
直接运行bash all.bash可以编译,编译后有测试运行
[root@iZ2zee2m456rb6bde98jpkZ src]# bash all.bash
Building Go cmd/dist using /usr/local/go. (go1.18.3 linux/amd64)
Building Go toolchain1 using /usr/local/go.
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 linux/amd64.
##### Testing packages.
ok archive/tar 0.070s
ok archive/zip 0.129s
ok bufio 0.130s
ok bytes 0.222s
......
ok cmd/pack 7.460s
ok cmd/pprof 5.190s
ok cmd/trace 0.575s
ok cmd/vet 6.587s
##### os/user with tag osusergo
ok os/user 0.004s
......
##### ../test
##### API check
Go version is "go1.18.3", ignoring -next /data/go/api/next.txt
ALL TESTS PASSED
---
Installed Go for linux/amd64 in /data/go
Installed commands in /data/go/bin
*** You need to add /data/go/bin to your PATH.
查看源码结构
安装tree软件查看源码结构
[root@iZ2zee2m456rb6bde98jpkZ go]# dnf install -y tree
Last metadata expiration check: 3:11:08 ago on Wed 29 Jun 2022 11:30:16 AM CST.
Dependencies resolved.
=============================================================================================================================
Package Architecture Version Repository Size
=============================================================================================================================
Installing:
tree x86_64 1.7.0-15.2.al8 alinux3-os 60 k
Transaction Summary
=============================================================================================================================
Install 1 Package
Total download size: 60 k
Installed size: 129 k
Downloading Packages:
tree-1.7.0-15.2.al8.x86_64.rpm 365 kB/s | 60 kB 00:00
-----------------------------------------------------------------------------------------------------------------------------
Total 363 kB/s | 60 kB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : tree-1.7.0-15.2.al8.x86_64 1/1
Running scriptlet: tree-1.7.0-15.2.al8.x86_64 1/1
Verifying : tree-1.7.0-15.2.al8.x86_64 1/1
Installed:
tree-1.7.0-15.2.al8.x86_64
Complete!
因为已经编译的目录中有一些日志文件,这里再解压一份源码至另一目录查看tar zxf /root/go1.18.3.src.tar.gz -C /data/sub1/,然后用tree命令查看第一级目录
[root@iZ2zee2m456rb6bde98jpkZ go]# tree -L 1 -F
.
├── api/
├── AUTHORS
├── codereview.cfg
├── CONTRIBUTING.md
├── CONTRIBUTORS
├── doc/
├── lib/
├── LICENSE
├── misc/
├── PATENTS
├── README.md
├── SECURITY.md
├── src/
├── test/
└── VERSION
6 directories, 9 files
根目录下文件为版本说明等文件
api目录下文件都为txt文件,是不同版本api说明文档
[root@iZ2zee2m456rb6bde98jpkZ go]# tree -L 1 -F api/
api/
├── except.txt
├── go1.10.txt
......
├── go1.txt
├── next.txt
└── README
0 directories, 22 files
doc目录下html文件,技术上一些说明
[root@iZ2zee2m456rb6bde98jpkZ go]# tree -L 1 -F doc/
doc/
├── asm.html
├── go1.17_spec.html
├── go1.18.html
├── go_mem.html
└── go_spec.html
0 directories, 5 files
lib目录为空目录,编译后存放的是时区信息
[root@iZ2zee2m456rb6bde98jpkZ go]# tree -L 1 -F lib/
lib/
└── time/
1 directory, 0 files
misc目录是不同模块支持,比如android, ios,还有web网页上wasm执行的支持
[root@iZ2zee2m456rb6bde98jpkZ go]# tree -L 1 -F misc/
misc/
├── android/
├── arm/
├── cgo/
├── chrome/
├── editors
├── go.mod
├── ios/
├── linkcheck/
├── reboot/
├── swig/
├── trace/
└── wasm/
10 directories, 2 files
test目录是运行测试的代码,src目录是主要的程序目录,这里继续查看src目录
[root@iZ2zee2m456rb6bde98jpkZ go]# tree -L 1 -F src/
src/
├── all.bash*
├── all.bat
├── all.rc*
├── archive/
├── bootstrap.bash*
├── bufio/
├── buildall.bash*
├── builtin/
├── bytes/
├── clean.bash*
├── clean.bat
├── clean.rc*
├── cmd/
├── cmp.bash
├── compress/
├── container/
├── context/
├── crypto/
├── database/
├── debug/
├── embed/
├── encoding/
├── errors/
├── expvar/
├── flag/
├── fmt/
├── go/
├── go.mod
├── go.sum
├── hash/
├── html/
├── image/
├── index/
├── internal/
├── io/
├── log/
├── make.bash*
├── make.bat
├── Make.dist
├── make.rc*
├── math/
├── mime/
├── net/
├── os/
├── path/
├── plugin/
├── race.bash*
├── race.bat
├── README.vendor
├── reflect/
├── regexp/
├── run.bash*
├── run.bat
├── run.rc*
├── runtime/
├── sort/
├── strconv/
├── strings/
├── sync/
├── syscall/
├── testdata/
├── testing/
├── text/
├── time/
├── unicode/
├── unsafe/
└── vendor/
46 directories, 21 files
其中目录说明
目录 | 说明
------- | -------
archive | 归档
bufio | 缓存io
builtin | 内置调用
bytes | 字节处理
cmd | 命令工具
compress | 压缩
container | 数据容器
context | 上下文
crypto | 加密
database | 数据库sql
debug | 调试
embed | 访问运行中的go程序的文件
encoding | 编码
errors | 错误
expvar | 公共变量
flag | 命令行参数
fmt | 格式化输出
go | go文件解析
hash | hash函数
html | html处理
image | 图像处理
index | 索引
internal | 内部功能模块
io | 输入输出
log | 日志
math | 数学计算
mime | mime类型
net | 网络
os | 系统
path | 路径解析
plugin | 插件
reflect | 反射
regexp | 正则
runtime | 运行时
sort | 排序
strconv | 字符串转换
strings | 字符串
sync | 同步
syscall | 系统调用
testdata | 测试数据
testing | 测试
text | 文本
time | 时间
unicode | unicode编码
unsafe | 不安全内存访问
vendor | 扩展模块
windows环境编译
介绍下windows下源码编译,系统中先安装golang语言包,安装目录为C:\Go
然后解压源代码
打开命令提示符,设置环境变量
set GOROOT_BOOTSTRAP=C:\Go
set CGO_ENABLED=0
进入源代码src目录,运行all.bat执行编译
如果提示错误
golang.org/x/mod@v0.6.0-dev.0.20220419223038-86c51ed26bb4: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
golang.org/x/tools@v0.1.11: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
To ignore the vendor directory, use -mod=readonly or -mod=mod.
To sync the vendor directory, run:
go mod vendor
运行go mod tidy下载依赖包,然后运行all.bat
注释all.bat中下一行,不运行测试。如果运行测试过程,那时间会较长
call run.bat --no-rebuild --no-local
如何修改版本号
修改根目录下VERSION文件内容,比如修改为20220629,运行all.bat编译,再运行bin/go version
$ bin/go version
go version go20220629 windows/amd64
修改源代码增加关键字xxxfunc
比如给golang增加一个关键字xxxfunc,功能同func,用于声明函数
这里修改的文件,实际上是在词法解析和语法分析中搜索func关键字的部分,然后再增加xxxfunc关键字的功能。
以下是文件的改动
src/go/parser/parser.go
--- src_org/go/parser/parser.go 2022-06-02 00:44:44.000000000 +0800
+++ src/go/parser/parser.go 2022-06-29 17:39:14.500166600 +0800
@@ -746,7 +746,7 @@
f.name = p.parseIdent()
}
switch p.tok {
- case token.IDENT, token.MUL, token.ARROW, token.FUNC, token.CHAN, token.MAP, token.STRUCT, token.INTERFACE, token.LPAREN:
+ case token.IDENT, token.MUL, token.ARROW, token.FUNC, token.XXXFUNC, token.CHAN, token.MAP, token.STRUCT, token.INTERFACE, token.LPAREN:
// name type
f.typ = p.parseType()
@@ -779,7 +779,7 @@
}
}
- case token.MUL, token.ARROW, token.FUNC, token.LBRACK, token.CHAN, token.MAP, token.STRUCT, token.INTERFACE, token.LPAREN:
+ case token.MUL, token.ARROW, token.FUNC, token.XXXFUNC, token.LBRACK, token.CHAN, token.MAP, token.STRUCT, token.INTERFACE, token.LPAREN:
// type
f.typ = p.parseType()
@@ -1000,6 +1000,21 @@
return &ast.FuncType{Func: pos, Params: params, Results: results}
}
+func (p *parser) parseXxxFuncType() *ast.FuncType {
+ if p.trace {
+ defer un(trace(p, "FuncType"))
+ }
+
+ pos := p.expect(token.XXXFUNC)
+ tparams, params := p.parseParameters(true)
+ if tparams != nil {
+ p.error(tparams.Pos(), "function type must have no type parameters")
+ }
+ results := p.parseResult()
+
+ return &ast.FuncType{Func: pos, Params: params, Results: results}
+}
+
func (p *parser) parseMethodSpec() *ast.Field {
if p.trace {
defer un(trace(p, "MethodSpec"))
@@ -1269,6 +1284,9 @@
case token.FUNC:
typ := p.parseFuncType()
return typ
+ case token.XXXFUNC:
+ typ := p.parseXxxFuncType()
+ return typ
case token.INTERFACE:
return p.parseInterfaceType()
case token.MAP:
@@ -1347,6 +1365,25 @@
return &ast.FuncLit{Type: typ, Body: body}
}
+func (p *parser) parseXxxFuncTypeOrLit() ast.Expr {
+ if p.trace {
+ defer un(trace(p, "FuncTypeOrLit"))
+ }
+
+ typ := p.parseXxxFuncType()
+ if p.tok != token.LBRACE {
+ // function type only
+ return typ
+ }
+
+ p.exprLev++
+ body := p.parseBody()
+ p.exprLev--
+
+ return &ast.FuncLit{Type: typ, Body: body}
+}
+
+
// parseOperand may return an expression or a raw type (incl. array
// types of the form [...]T. Callers must verify the result.
//
@@ -1376,6 +1413,8 @@
case token.FUNC:
return p.parseFuncTypeOrLit()
+ case token.XXXFUNC:
+ return p.parseXxxFuncTypeOrLit()
}
if typ := p.tryIdentOrType(); typ != nil { // do not consume trailing type parameters
src/go/token/token.go
--- src_org/go/token/token.go 2022-06-02 00:44:44.000000000 +0800
+++ src/go/token/token.go 2022-06-29 17:36:47.508924600 +0800
@@ -108,6 +108,7 @@
FOR
FUNC
+ XXXFUNC
GO
GOTO
IF
@@ -214,6 +215,7 @@
FOR: "for",
FUNC: "func",
+ XXXFUNC: "xxxfunc",
GO: "go",
GOTO: "goto",
IF: "if",
src/cmd/compile/internal/syntax/parser.go
--- src_org/cmd/compile/internal/syntax/parser.go 2022-06-02 00:44:40.000000000 +0800
+++ src/cmd/compile/internal/syntax/parser.go 2022-06-29 19:07:36.659900300 +0800
@@ -422,7 +422,7 @@
p.next()
f.DeclList = p.appendGroup(f.DeclList, p.varDecl)
- case _Func:
+ case _Func, _Xxxfunc:
p.next()
if d := p.funcDeclOrNil(); d != nil {
f.DeclList = append(f.DeclList, d)
@@ -435,7 +435,7 @@
} else {
p.syntaxError("non-declaration statement outside function body")
}
- p.advance(_Const, _Type, _Var, _Func)
+ p.advance(_Const, _Type, _Var, _Func, _Xxxfunc)
continue
}
@@ -445,7 +445,7 @@
if p.tok != _EOF && !p.got(_Semi) {
p.syntaxError("after top level declaration")
- p.advance(_Const, _Type, _Var, _Func)
+ p.advance(_Const, _Type, _Var, _Func, _Xxxfunc)
}
}
// p.tok == _EOF
@@ -991,7 +991,7 @@
}
return x
- case _Func:
+ case _Func, _Xxxfunc:
pos := p.pos()
p.next()
_, ftyp := p.funcType("function literal")
@@ -1331,7 +1331,7 @@
t.Elem = p.chanElem()
return t
- case _Func:
+ case _Func, _Xxxfunc:
// fntype
p.next()
_, t := p.funcType("function type")
@@ -2616,7 +2616,7 @@
return p.simpleStmt(nil, 0) // unary operators
}
- case _Literal, _Func, _Lparen, // operands
+ case _Literal, _Func, _Xxxfunc, _Lparen, // operands
_Lbrack, _Struct, _Map, _Chan, _Interface, // composite types
_Arrow: // receive operator
return p.simpleStmt(nil, 0)
src/cmd/compile/internal/syntax/scanner.go
--- src_org/cmd/compile/internal/syntax/scanner.go 2022-06-02 00:44:40.000000000 +0800
+++ src/cmd/compile/internal/syntax/scanner.go 2022-06-29 19:01:11.397127500 +0800
@@ -425,7 +425,7 @@
func init() {
// populate keywordMap
- for tok := _Break; tok <= _Var; tok++ {
+ for tok := _Break; tok <= _Xxxfunc; tok++ {
h := hash([]byte(tok.String()))
if keywordMap[h] != 0 {
panic("imperfect hash")
src/cmd/compile/internal/syntax/token_string.go
--- src_org/cmd/compile/internal/syntax/token_string.go 2022-06-02 00:44:40.000000000 +0800
+++ src/cmd/compile/internal/syntax/token_string.go 2022-06-29 18:47:32.776526600 +0800
@@ -54,12 +54,13 @@
_ = x[_Switch-44]
_ = x[_Type-45]
_ = x[_Var-46]
- _ = x[tokenCount-47]
+ _ = x[_Xxxfunc-47]
+ _ = x[tokenCount-48]
}
-const _token_name = "EOFnameliteralopop=opop=:=<-*([{)]},;:....breakcasechanconstcontinuedefaultdeferelsefallthroughforfuncgogotoifimportinterfacemappackagerangereturnselectstructswitchtypevar"
+const _token_name = "EOFnameliteralopop=opop=:=<-*([{)]},;:....breakcasechanconstcontinuedefaultdeferelsefallthroughforfuncgogotoifimportinterfacemappackagerangereturnselectstructswitchtypevarxxxfunc"
-var _token_index = [...]uint8{0, 3, 7, 14, 16, 19, 23, 24, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 42, 47, 51, 55, 60, 68, 75, 80, 84, 95, 98, 102, 104, 108, 110, 116, 125, 128, 135, 140, 146, 152, 158, 164, 168, 171, 171}
+var _token_index = [...]uint8{0, 3, 7, 14, 16, 19, 23, 24, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 42, 47, 51, 55, 60, 68, 75, 80, 84, 95, 98, 102, 104, 108, 110, 116, 125, 128, 135, 140, 146, 152, 158, 164, 168, 171, 178, 178}
func (i token) String() string {
i -= 1
src/cmd/compile/internal/syntax/tokens.go
--- src_org/cmd/compile/internal/syntax/tokens.go 2022-06-02 00:44:40.000000000 +0800
+++ src/cmd/compile/internal/syntax/tokens.go 2022-06-29 18:47:11.069644800 +0800
@@ -65,6 +65,7 @@
_Switch // switch
_Type // type
_Var // var
+ _Xxxfunc // xxxfunc
// empty line comment to exclude it from .String
tokenCount //
注释all.bat中run部分,运行重新编译生成新的go程序
编写代码文件xxxfunc.go,使用关键字xxxfunc声明函数
package main
import "fmt"
func main() {
fmt.Println("test")
main2()
}
xxxfunc main2() {
fmt.Println("test xxxfunc")
}
然后用生成的go程序运行代码
$ bin/go run ../xxxfunc.go
test
test xxxfunc
看到定义的关键字解析为函数声明,并输出结果