ECS上golang源码编译,修改源码版本号编译,修改增加语言关键字xxxfunc

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: ECS上golang源码编译,修改源码版本号编译,修改增加语言关键字xxxfunc

获取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

看到定义的关键字解析为函数声明,并输出结果

本文中修改的go文件压缩包下载

相关实践学习
2分钟自动化部署人生模拟器
本场景将带你借助云效流水线Flow实现人生模拟器小游戏的自动化部署
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情:&nbsp;https://www.aliyun.com/product/ecs
目录
相关文章
|
12天前
|
Ubuntu Linux Go
golang编译成Linux可运行文件
本文介绍了如何在 Linux 上编译和运行 Golang 程序,涵盖了本地编译和交叉编译的步骤。通过这些步骤,您可以轻松地将 Golang 程序编译成适合 Linux 平台的可执行文件,并在目标服务器上运行。掌握这些技巧,可以提高开发和部署 Golang 应用的效率。
85 14
|
Linux Go Windows
Golang-编译和Go语言文件基本机构
Go语言编译和Go语言文件基本机构
107 0
|
缓存 Linux Go
Golang交叉编译(跨平台编译)的使用
存在交叉编译的情况时,cgo 工具是不可用的。在标准 go 命令的上下文环境中,交叉编译意味着程序构建环境的目标计算架构的标识与程序运行环境的目标计算架构的标识不同,或者程序构建环境的目标操作系统的标识与程序运行环境的目标操作系统的标识不同
405 0
Golang交叉编译(跨平台编译)的使用
|
Java 中间件 Unix
Golang 环境配置与应用编译
这篇文章主要是说一下 Go 的工作目录与编译的规则,初步体验一下 Go 的大道至简的魅力。
300 0
Golang 环境配置与应用编译
|
Go C++ PHP
centos6使用 swig3.0.6 编译c,golang 1.4.2调用
1,关于swig SWIG是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。SWIG能应用于各种不同类型的语言包括常用脚本编译语言例如Perl, PHP, Python, Tcl, Ruby and PHP。 最新的版本已经开始支持golang了。 2,环境搭建 参考文档: http://www.swig.org/Doc3.0/G
1526 0
|
4月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
152 4
Golang语言之管道channel快速入门篇
|
4月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
76 4
Golang语言文件操作快速入门篇
|
4月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
125 3
Golang语言之gRPC程序设计示例
|
4月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
105 4
下一篇
开通oss服务