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

本文涉及的产品
云服务器 ECS,每月免费额度200元 3个月
云服务器ECS,u1 2核4GB 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
set GOPROXY=https://mirrors.aliyun.com/golang/,direct
进入源代码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文件压缩包下载

相关实践学习
一小时快速掌握 SQL 语法
本实验带您学习SQL的基础语法,快速入门SQL。
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情:&nbsp;https://www.aliyun.com/product/ecs
目录
相关文章
|
17天前
|
Go
go语言中的数据类型
go语言中的数据类型
13 0
|
4天前
|
数据采集 存储 Go
使用Go语言和chromedp库下载Instagram图片:简易指南
Go语言爬虫示例使用chromedp库下载Instagram图片,关键步骤包括设置代理IP、创建带代理的浏览器上下文及执行任务,如导航至用户页面、截图并存储图片。代码中新增`analyzeAndStoreImage`函数对图片进行分析和分类后存储。注意Instagram的反爬策略可能需要代码适时调整。
使用Go语言和chromedp库下载Instagram图片:简易指南
|
23天前
|
存储 安全 Go
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
|
1天前
|
安全 Go 开发者
Golang深入浅出之-Go语言并发编程面试:Goroutine简介与创建
【4月更文挑战第22天】Go语言的Goroutine是其并发模型的核心,是一种轻量级线程,能低成本创建和销毁,支持并发和并行执行。创建Goroutine使用`go`关键字,如`go sayHello(&quot;Alice&quot;)`。常见问题包括忘记使用`go`关键字、不正确处理通道同步和关闭、以及Goroutine泄漏。解决方法包括确保使用`go`启动函数、在发送完数据后关闭通道、设置Goroutine退出条件。理解并掌握这些能帮助开发者编写高效、安全的并发程序。
10 1
|
1天前
|
人工智能 Go 调度
掌握Go并发:Go语言并发编程深度解析
掌握Go并发:Go语言并发编程深度解析
|
1天前
|
SQL 关系型数据库 MySQL
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
|
2天前
|
Go 开发者
Golang深入浅出之-Go语言流程控制:if、switch、for循环详解
【4月更文挑战第21天】本文介绍了Go语言中的流程控制语句,包括`if`、`switch`和`for`循环。`if`语句支持简洁的语法和初始化语句,但需注意比较运算符的使用。`switch`语句提供多分支匹配,可省略`break`,同时支持不带表达式的形式。`for`循环有多种形式,如基本循环和`for-range`遍历,遍历时修改原集合可能导致未定义行为。理解并避免易错点能提高代码质量和稳定性。通过实践代码示例,可以更好地掌握Go语言的流程控制。
11 3
Golang深入浅出之-Go语言流程控制:if、switch、for循环详解
|
2天前
|
Go
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
【4月更文挑战第21天】Go语言函数是代码组织的基本单元,用于封装可重用逻辑。本文介绍了函数定义(包括基本形式、命名、参数列表和多返回值)、调用以及匿名函数与闭包。在函数定义时,注意参数命名和注释,避免参数顺序混淆。在调用时,要检查并处理多返回值中的错误。理解闭包原理,小心处理外部变量引用,以提升代码质量和可维护性。通过实践和示例,能更好地掌握Go语言函数。
16 1
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
|
3天前
|
程序员 Go API
【Go语言快速上手(二)】 分支与循环&函数讲解
【Go语言快速上手(二)】 分支与循环&函数讲解
|
3天前
|
Go
Golang深入浅出之-Go语言基础语法:变量声明与赋值
【4月更文挑战第20天】本文介绍了Go语言中变量声明与赋值的基础知识,包括使用`var`关键字和简短声明`:=`的方式,以及多变量声明与赋值。强调了变量作用域、遮蔽、初始化与零值的重要性,并提醒读者注意类型推断时的一致性。了解这些概念有助于避免常见错误,提高编程技能和面试表现。
18 0