[Go] Go语言教程
Go-lang概述
-
Go是一个开源的、一种静态强类型的、【编译型】编程语言,它能让构造简单、可靠且高效的软件变得容易。 -
Go是从2007年末由Robert Griesemer,Rob Pike,Ken Thompson主持开发,后来还加入了Ian Lance Taylor,Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。
现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。
- Go 语言特色
- 简洁、快速、安全
- 并行、有趣、开源
- 内存管理、数组安全、编译迅速
Go = 编译型语言




适用场景
- Go 语言用途
- Go 语言被设计成一门应用于搭载
Web服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。- 对于高性能分布式系统领域而言,
Go语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于游戏服务端的开发而言是再好不过了。
- 为什么Go语言适合现代的后端编程环境?
- 服务类应用以API居多,IO密集型,且网络IO最多;
- 运行成本低,无VM。网络连接数不多的情况下内存占用低;
- 强类型语言,易上手,易维护;
- 适用于IT基础设施(如:Kubernates)
为什么适合基础设施?
k8s、etcd、istio、docker已经证明了Go的能力
环境安装
- 支持的操作系统
Go 语言支持以下系统:
- Linux
- Linux
- FreeBSD
- Mac OS X
(也称为
Darwin)
- Windows
- 安装包
安装包下载地址为:https://go.dev/dl/。
如果打不开可以使用这个镜像地址: https://golang.google.cn/dl/。
- 各个系统对应的包名:
| 操作系统 | 包名 |
| Windows | go1.4.windows-amd64.msi |
| Linux | go1.4.linux-amd64.tar.gz |
| Mac | go1.4.darwin-amd64-osx10.8.pkg |
| FreeBSD | go1.4.freebsd-amd64.tar.gz |

基于 Alpline Linux 的包管理器安装
- 安装 go
# apk update
# apk add go
- 配置 PATH
- 查看 安装路径
# which go
/usr/bin/go
# ls -la /usr/bin/go
lrwxrwxrwx 1 root root 18 Feb 7 18:03 /usr/bin/go -> /usr/lib/go/bin/go
或 查看完整的安装路径: (通常,Go 的可执行文件位于 /usr/bin/go)
# readlink -f $(which go)
/usr/lib/go/bin/go
- 添加安装路径到环境变量PATH
将 Go 的路径添加到你的 PATH 环境变量中。你可以通过修改你的 shell 配置文件(如 .bashrc 或 .zshrc)来实现这一点。例如,如果你使用的是 bash,你可以在你的家目录下的 .bashrc 文件中添加以下行
vim ~/.bashrc
export PATH=$PATH:/usr/lib/go/bin/go
source ~/.bashrc
- 验证安装
# go version
go version go1.22.10 linux/amd64
基于 UNIX/Linux/Mac OS X, 和 FreeBSD 的安装
以下介绍了在UNIX/Linux/Mac OS X, 和 FreeBSD系统下使用源码安装方法:
亦可参见 : https://www.runoob.com/go/go-environment.html
如下以 CENTOS7.9 为例:
- 1、下载二进制包:go1.23.0.linux-amd64.tar.gz。
https://go.dev/dl/
https://golang.google.cn/dl/
https://go.dev/dl/go1.23.0.linux-amd64.tar.gz
https://go.dev/dl/go1.23.4.linux-amd64.tar.gz
cd /usr/local
wget https://go.dev/dl/go1.23.0.linux-amd64.tar.gz
- 2、将下载的二进制包解压至
/usr/local目录。
tar -C /usr/local -xzf go1.23.0.linux-amd64.tar.gz
- 3、将 /usr/local/go/bin 目录添加至 PATH 环境变量:
export PATH=$PATH:/usr/local/go/bin
以上只能暂时添加 PATH,关闭终端后下次再登录就没有了。
我们可以编辑 ~/.bash_profile 或者 /etc/profile,并将以下命令添加该文件的末尾,这样就永久生效了:
export PATH=$PATH:/usr/local/go/bin
添加后需要执行:
source ~/.bash_profile
或
source /etc/profile
注意:
MAC系统下你可以使用.pkg结尾的安装包直接双击来完成安装,安装目录在/usr/local/go/下。
4、配置GOPROXY环境变量(可选步骤)
GO安装成功后,应用项目的二进制程序保存在$GOPATH/bin目录。如果是国内用户,安装失败,建议配置GOPROXY
vim /etc/profile 或 vim ~/.bash_profile
export GOPROXY=https://goproxy.cn
source /etc/profile 或 source ~/.bash_profile
echo $GOPROXY
5、验证
go env 或 go version
# 例如:
# go env GOOS
linux
# go env GOARCH
amd64
# go env GOPATH
/opt/go-projects/opengemini
# go env GOPROXY
https://goproxy.cn
6、配置项目的GOPATH的环境变量 (可选步骤)
mkdir -p /opt/go-projects/xxx
vim /etc/profile
export GOPATH=/opt/go-projects/xxx
source /etc/profile
echo $GOPATH
不主动配置
GOPATH时,则默认路径为
#go env GOPATH
/root/go
主动配置
GOPATH的意义:
go install命令本身不会自动配置 GOPATH 环境变量; 换言之,配置GOPATH是在使用go install或其他 Go 命令之前进行的。go install命令会将编译后的可执行文件放置在GOPATH/bin目录下。如果你没有设置 GOPATH,或者 GOPATH 没有正确指向一个有效的目录,go install 命令可能会失败,或者编译后的文件可能不会被放置在预期的位置。- 如果你使用的是 Go 1.11 或更高版本,并且启用了Go 1.11 的模块支持特性,那么 GOPATH 可能不会像以前那样频繁使用。
- 要启用模块支持,你可以在项目目录下运行
go mod init <module-name>命令来初始化一个新的模块。之后,你可以使用go build或go install命令来构建你的项目,而不需要依赖GOPATH。
基于 Windows 系统的安装
- 选择对应版本,选择windows-amd64.zip下载后解压到本地目录
https://golang.google.cn/dl/go1.23.3.windows-amd64.zip [√]
https://golang.google.cn/dl/go1.23.3.linux-amd64.tar.gz
https://golang.google.cn/dl/go1.23.3.src.tar.gz

- 创建一个新文件夹,在里面新建
bin、pkg、src3个文件夹 : 此步骤可忽略
可以是任意位置,用来存放go项目。
假定其目录为:
D:\Workspace\CodeRepositories\GoHelloWorld
D:\Workspace\CodeRepositories\GoHelloWorld
/bin
/pkg
/src
- 配置系统变量
GOROOT在系统变量下选择新建,添加一个
GOROOT的变量,变量值为当前go的安装目录
GOROOT
D:\Program\Go-Lang\go1.23.3.windows-amd64\go
GOPATH: 当前工作目录,可以随时按需修改
GOPATH
D:\Workspace\CodeRepositories\GoHelloWorld
Path: 环境变量添加2个值
%GOROOT%\bin
%GOPATH%\bin
- 验证
go env

如果出现这样就配置成功了
- 打开CMD终端,输入以下配置 (可选步骤)
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
- 查看版本
> go version
go version go1.23.3 windows/amd64
【补充说明】
如果是msi包的windows安装方式,则:
Windows 下可以使用 .msi 后缀(在下载列表中可以找到该文件,如go1.4.2.windows-amd64.msi)的安装包来安装。
默认情况下 .msi 文件会安装在 c:\Go 目录下。你可以将 c:\Go\bin 目录添加到 Path 环境变量中。添加后你需要重启命令窗口才能生效。
基于 Docker 构建Go的基础镜像及环境
使用docker构建基础环境
FROM centos
RUN yum install golang -y \
&& yum install dlv -y \
&& yum install binutils -y \
&& yum install vim -y \
&& yum install gdb -y
# docker build -t test .
# docker run -it --rm test bash
查验版本
[root@vmw-b local]# go version
go version go1.23.0 linux/amd64
配置 GO 的源
解决Go安装时由于默认使用国外源导致的下载速度慢问题
参考文献 : go 配置国内源 - CSDN
- Windows
SETX GO111MODULE on
go env -w GOPROXY=https://goproxy.cn,direct
SETX GOPROXY https://goproxy.cn,direct
- Linux
echo "export GO111MODULE=on" >> ~/.profile
echo "export GOPROXY=https://goproxy.cn" >> ~/.profile
source ~/.profile
- 效果对比
- 配置前 : 找不到 go.mod、安装超时
# go get -v github.com/deckarep/golang-set
go: go.mod file not found in current directory or any parent directory.
'go get' is no longer supported outside a module.
To build and install a command, use 'go install' with a version,
like 'go install example.com/cmd@latest'
For more information, see https://golang.org/doc/go-get-install-deprecation
or run 'go help get' or 'go help install'.
~ # go install google.golang.org/grpc@latest
go: google.golang.org/grpc@latest: module google.golang.org/grpc: Get "https://proxy.golang.org/google.golang.org/grpc/@v/list": dial tcp 142.251.215.241:443: i/o timeout
- 配置后
- 初始化 go 应用工程,将生成 go.mod 文件
# go mod init my-grpc-service
go: creating new go.mod: module my-grpc-service
go: to add module requirements and sums:
go mod tidy
# cat go.mod
module my-grpc-service
go 1.22.10
此举能避免此类
go.mod文件找不到的错误:
# go get -v github.com/deckarep/golang-set
go: go.mod file not found in current directory or any parent directory. (在当前目录或任何父目录中找不到 go.mod 文件。)
'go get' is no longer supported outside a module. (在模块外不再支持‘go get’)
To build and install a command, use 'go install' with a version, (要构建和安装一个命令,使用‘go install’和一个版本)
like 'go install example.com/cmd@latest' (比如“安装example.com/cmd@latest”)
For more information, see https://golang.org/doc/go-get-install-deprecation (欲了解更多信息,请访问 https://golang.org/doc/go-get-install-deprecation)
or run 'go help get' or 'go help install'. (或者运行‘go help get’或‘go help install’。)
# go get -v github.com/deckarep/golang-set
go: warning: ignoring go.mod in $GOPATH /root/grpc-service/
go: downloading github.com/deckarep/golang-set v1.8.0
go: added github.com/deckarep/golang-set v1.8.0
# go install google.golang.org/grpc@latest
go: downloading google.golang.org/grpc v1.70.0
go: downloading golang.org/x/net v0.32.0
go: downloading google.golang.org/protobuf v1.35.2
go: downloading golang.org/x/sys v0.28.0
go: downloading google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a
go: downloading golang.org/x/text v0.21.0
package google.golang.org/grpc is not a main package
Hello World 程序
- 安装GO环境
- 新建一个
hello.go源文件
package main
import (
"fmt"
"os"
)
func main() {
goPathEnv := os.Getenv("GOPATH");
if goPathEnv == "" { // 检查环境变量XX是否存在
goPathEnv = "/root/xxxx";
}
fmt.Println("hello world! GOPATH:", goPathEnv)
}
- 使用
go run hello.go命令运行
D:\Workspace\CodeRepositories\GoHelloWorld\src>go run hello.go
hello world! GOPATH:/opt/go-projects/opengemini
GO编译开发指令
go run 和 go build 以及 go install 是 Go 语言中用于构建和运行 Go 程序的不同命令,它们之间的关系和区别如下:
go run
- 用途:
go run命令用于直接编译并运行 Go 程序,它不会生成永久的可执行文件。 - 编译:当你运行
go run时,Go 编译器会编译指定的源文件和它们的依赖。 - 执行:编译完成后,生成的程序会立即执行,并且执行完毕后不会留下任何可执行文件。
- 适用场景:适用于快速测试小段代码或脚本,不需要保留生成的可执行文件。
go build
- 用途:
go build命令用于编译 Go 程序,但不会自动运行生成的可执行文件。 - 编译:
go build会编译指定的包和它们的依赖,并生成一个或多个可执行文件。 - 生成文件:编译完成后,会在当前目录生成可执行文件。
- 适用场景:适用于需要生成可执行文件以供后续分发或运行的情况。
go install
- 用途:
go install命令用于编译并安装 Go 程序,通常用于安装命令行工具或库。 - 编译:
go install会编译指定的包和它们的依赖。 - 安装:编译完成后,
go install会将生成的可执行文件放置到$GOPATH/bin(或$GOBIN,如果设置了的话)目录下。 - 适用场景:适用于安装需要全局使用的命令行工具或库,这些工具或库可以在任何地方通过它们的导入路径被引用。
指令简介
go install命令用于编译和安装go程序,它允许将项目本地构建(build)、并安装(install)到$GOPATH/bin目录中。
可用于安装依赖项和排除测试,其选项包括:
-v(详细模式,显示构建信息)-p {n}(并行构建n个包)-x(显示正在运行的命令)-target {OS/ARCH}(设置目标操作系统和架构)
- 最佳实践:
go install前,建议先配置好应用程序项目的GOPATH环境变量。这样,go install时,会依据$GOPATH/bin目录进行安装。
使用案例
- 样例指令:安装程序和依赖项
# 要构建和安装 hello.go 程序
go install hello.go
# 从远程源码仓库拉取代码构建
go install github.com/openGemini/gemix@v1.0.1
# 或者,如果您想指定安装目录,可使用`-d`选项
go install -d github.com/myusername/myproject
- 样例指令: 本地编译安装
//1.编译的中间文件(目标库文件):放到pkg下,xxx.a文件
//2.把编译的二进制可执行程序:放到go的bin目录下 (也可提前设置好`GOBIN`路径)
go install chapter11/goinstall
//当前目录是项目main.go所在目录,包名为chapter11,要安装的目录为goinstall
//只有这样才能在pkg下面生成.a文件,否则生成不了
├── bin
│ └── goinstall
├── pkg
│ └── linux_amd64
│ └── chapter11
│ └── goinstall
│ └── mypkg.a
└── src
└── chapter11
├── gobuild
│ ├── lib.go
│ └── main.go
└── goinstall
├── main.go
└── mypkg
└── mypkg.go
- 案例:编译本地工程(以 安装 OpenGemini-Gemix(v1.0.1) on CENTOS7 为例)
# 安装 git
yum -y install git
# 下载 gemix 指定版本的源码
cd /root
git clone -b v1.0.1 https://github.com/openGemini/gemix.git
# 注: -b {branch | tag | commit }
# 编辑代码:
vim /root/gemix/pkg/cluster/operation/download.go
...
# 配置 GOPATH 环境变量
export GOPATH=/opt/go-projects/opengemini
echo $GOPATH
# 切换到 go 应用工程 main.go 所在目录,
cd /root/gemix/
# 编译本地 go 应用工程 ,编译结果放 $GOPATH/bin
go install
# 注:编译后的可执行二进制程序: $GOPATH/bin/gemix
# 将可执行二进制程序设置为可直接使用的命令(而无需再提供完整的路径): gemix
ln -s $GOPATH/bin/gemix /usr/local/bin/gemix
- 样例指令:排除测试
如果您不想安装程序的测试,请使用
-test选项
go install -test github.com/myusername/myproject
帮助手册
[root@vmw-b ~]# go help install
usage: go install [build flags] [packages]
Install compiles and installs the packages named by the import paths.
Install会编译并安装由导入路径命名的包。
Executables are installed in the directory named by the GOBIN environment
variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH
environment variable is not set. Executables in $GOROOT
are installed in $GOROOT/bin or $GOTOOLDIR instead of $GOBIN.
可执行文件安装在GOBIN环境变量指定的目录中;
若未设置环境变量`GOPATH`,则默认为 `$GOPATH/bin` 或 $HOME/go/bin。
$GOROOT 中的可执行文件安装在`$GOROT/bin`或`$GOTOOLDIR`中,而不是`$GOBIN`中。
If the arguments have version suffixes (like @latest or @v1.0.0), "go install"
builds packages in module-aware mode, ignoring the go.mod file in the current
directory or any parent directory, if there is one. This is useful for
installing executables without affecting the dependencies of the main module.
To eliminate ambiguity about which module versions are used in the build, the
arguments must satisfy the following constraints:
- Arguments must be package paths or package patterns (with "..." wildcards).
They must not be standard packages (like fmt), meta-patterns (std, cmd,
all), or relative or absolute file paths.
- All arguments must have the same version suffix. Different queries are not
allowed, even if they refer to the same version.
- All arguments must refer to packages in the same module at the same version.
- Package path arguments must refer to main packages. Pattern arguments
will only match main packages.
- No module is considered the "main" module. If the module containing
packages named on the command line has a go.mod file, it must not contain
directives (replace and exclude) that would cause it to be interpreted
differently than if it were the main module. The module must not require
a higher version of itself.
- Vendor directories are not used in any module. (Vendor directories are not
included in the module zip files downloaded by 'go install'.)
If the arguments don't have version suffixes, "go install" may run in
module-aware mode or GOPATH mode, depending on the GO111MODULE environment
variable and the presence of a go.mod file. See 'go help modules' for details.
If module-aware mode is enabled, "go install" runs in the context of the main
module.
When module-aware mode is disabled, non-main packages are installed in the
directory $GOPATH/pkg/$GOOS_$GOARCH. When module-aware mode is enabled,
non-main packages are built and cached but not installed.
Before Go 1.20, the standard library was installed to
$GOROOT/pkg/$GOOS_$GOARCH.
Starting in Go 1.20, the standard library is built and cached but not installed.
Setting GODEBUG=installgoroot=all restores the use of
$GOROOT/pkg/$GOOS_$GOARCH.
For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.
See also: go build, go get, go clean.
go run / go build / go install 的关系
- 编译过程:
go run、go build和go install都涉及编译过程,但它们在编译后的行为不同。 - 生成的文件:
go run不生成永久文件,go build在当前目录生成可执行文件,而go install将可执行文件安装到指定的目录。 - 执行:
go run编译后立即执行程序,而go build和go install需要用户手动执行生成的可执行文件。
总结来说,go run 适合快速运行代码片段,go build 适合构建程序但不运行,go install 适合安装程序到全局路径。根据你的具体需求,你可以选择适当的命令来构建和运行 Go 程序。
go lang中 go get 与 go install 的区别
- 在 Go 语言中,go get 和 go install 是两个常用的命令,它们在功能和用途上有明显的区别,主要用于模块的获取和安装,以下为你详细介绍:
go get
- 功能:
- go get 主要用于下载指定的 Go 模块(包括依赖模块)到本地的 GOPATH 或 go.mod 文件指定的模块缓存中。
- 它会自动解析依赖关系,递归地下载模块及其依赖的所有子模块。
- 如果本地已经存在该模块,go get 会检查是否有更新版本,如果有更新版本且符合版本约束,则会下载更新版本。
- 使用场景:
- 当你开始一个新的项目,需要引入外部的 Go 模块时,通常会使用 go get 来获取这些模块。
- 例如,如果你想使用 github.com/gin-gonic/gin 这个 Web 框架,可以通过命令 go get github.com/gin-gonic/gin 来下载该模块及其依赖。
- 它主要用于开发阶段,帮助开发者获取和管理项目依赖。
- 输出结果:
- 如果是
Go Modules模式下,go get会将模块下载到GOPATH/pkg/mod目录下(默认情况下),并且会更新go.mod文件,记录模块的版本信息。- 如果是
GOPATH模式下,go get会将代码下载到GOPATH/src目录下。
go install
- 功能:
go install主要用于编译并安装指定的 Go 包及其依赖的包,并将编译生成的可执行文件安装到 GOBIN 环境变量指定的目录(默认是 $GOPATH/bin 或 $GOBIN)。- 它不会下载模块代码,而是直接从本地的模块缓存中获取已下载的模块进行编译和安装。
- 如果本地没有该模块,
go install会报错提示无法找到模块。
- 使用场景:
- 当你已经通过 go get 获取了所需的模块,并且想要将某个模块编译成可执行文件以便直接运行时,可以使用 go install。
- 例如,你已经通过 go get 下载了 github.com/yourusername/yourproject,然后使用
go install github.com/yourusername/yourproject将其编译成可执行文件,安装到$GOBIN目录下,之后你就可以直接在终端运行该可执行文件。- 它主要用于将模块编译成可执行文件,方便在生产环境中使用。
- 输出结果:
- go install 会生成一个可执行文件,并将其安装到 GOBIN 指定的目录下。例如,如果你的 GOBIN 是 /usr/local/go/bin,那么编译生成的可执行文件会被安装到该目录下。
- 总结
- go get:
主要用于下载模块及其依赖,更新 go.mod 文件,适用于开发阶段的依赖管理。
重点是获取代码和依赖关系。
- go install:
主要用于编译并安装模块为可执行文件,方便运行,适用于将模块编译成可执行程序的场景。
重点是将代码编译成可执行文件并安装到指定目录。
在实际开发中,通常先使用go get获取所需的模块,然后根据需要使用go install将模块编译成可执行文件。
go module
-
go module是go官方自带的go依赖管理库,在1.13版本正式推荐使用 -
go module可以将某个应用项目(文件夹)下的所有依赖整理成一个go.mod文件,里面写入了依赖的版本等
- 使用
go module之后我们可不用将代码放置在src下- 使用
go module管理依赖后会在项目根目录下生成2个文件go.mod(会记录当前项目的所依赖)和go.sum(记录每个依赖库的版本和哈希值)
GO111MODULE
GO111MODULE是go modules功能的开关GO111MODULE=off,无模块支持,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。GO111MODULE=on,模块支持,go命令行会使用modules,而一点也不会去GOPATH目录下查找。GO111MODULE=auto,默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:
- (1)当前目录在
GOPATH/src之外且该目录包含go.mod文件,开启模块支持。- (2)当前文件在包含
go.mod文件的目录下面。
- Go mod使用方法
//初始化模块
go mod init <项目模块名称>
//依赖关系处理,根据go.mod文件
go mod tidy
//将依赖包复制到项目的vendor目录
go mod vendor
//显示依赖关系
Go list -m all
//显示详细依赖关系
Go list -m -json all
//下载依赖
go mod download [path@version]
- 参考文献
原理与架构
Go语言的编译过程
- Go程序的编译过程:文本 -> 编译 -> 二进制可执行文件

-
编译:文本代码 -> 目标文件(.o, .a)
-
链接:将目标文件合并为可执行文件
-
使用
go build -x xxx.go可以观察这个过程

main.go : GO工程编译后的【可执行】二进制程序的入口点
先问一个问题: 一个go工程中,不定义 main.go 能编译吗?
- 在Go语言中,一个工程(或称为一个包)可以不包含
main.go文件,但这并不意味着它可以被编译成一个可执行文件。
以下是一些关于没有
main.go的Go工程的情况:
- 库包:
如果没有main.go文件,该Go工程通常是一个库包,它包含的代码可以被其他Go程序所引用和使用。
若库包不包含main函数,因此不能直接编译成可执行文件。
- 编译:
你可以编译没有main.go的Go工程,但编译的结果不是可执行文件,而是.a归档文件,这是一种包含编译后的对象代码的库文件。
这个库文件可以被其他Go程序通过import语句引用。
- 测试:
即使没有main.go,你仍然可以运行测试。
如果你有测试文件(以_test.go结尾),你可以使用go test命令来执行这些测试。
-
命令行工具:
如果你想创建一个命令行工具,那么必须有一个main.go文件,因为这是程序的入口点。 -
模块:
从Go 1.11版本开始,引入了模块系统,这使得管理和引用库包变得更加方便。
即使没有main.go,你也可以通过模块来管理和分发库代码。
总结来说,没有
main.go的Go工程不能被编译成可执行文件,但它可以被编译成库文件,供其他Go程序使用。
如果你想创建一个独立的程序,你需要在工程中包含一个main.go文件。
不同操作系统的可执行文件规范
- 可执行文件在不同的操作系统规范不一样
| Linux | Windows | MacOS |
|---|---|---|
| ELF | PE | Mach-O |
- 以
Linux的可执⾏⽂件ELF(Executable and Linkable Format) 为例,ELF由⼏部分构成:
- ELF header
- Section header
- Sections
- 操作系统执行可执行文件的步骤(Linux为例):

- 如何寻找Go进程的入口
通过
entry point找到Go进程的执⾏⼊⼝,使⽤readelf。进一步找到Go进程要从哪里启动了

Go进程的启动与初始化
计算机如何执⾏我们的程序

CPU⽆法理解⽂本,只能执⾏⼀条⼀条的⼆进制机器码指令,每次执⾏完⼀条指令,pc寄存器就指向下⼀条继续执⾏。
在 64 位平台上 pc 寄存器 = rip。
计算机会自上而下,依次执行汇编指令:

Runtime是什么 ? Go语言的Runtime
Go 语⾔是⼀⻔有
runtime的语⾔,那么runtime是什么?

可以认为runtime是为了实现额外的功能,⽽在程序运⾏时⾃动加载/运⾏的⼀些模块。
Go语言中,运行时、操作系统和程序员定义的应用程序代码之间的关系如下图:

- 在Go语言中,runtime主要包括:
- Scheduler:调度器管理所有的 G,M,P,在后台执⾏调度循环
- Netpoll:⽹络轮询负责管理⽹络 FD 相关的读写、就绪事件
- Memory Management:当代码需要内存时,负责内存分配⼯作
- Garbage Collector:当内存不再需要时,负责回收内存
这些模块中,最核⼼的就是 Scheduler,它负责串联所有的runtime 流程。
通过 entry point 找到 Go 进程的执⾏⼊⼝:

runtime.rt0_go的相关处理过程:
- 开始执行用户main函数(从这里开始进入调度循环)
- 初始化内置数据结构
- 获取CPU核心数
- 全局
m0、g0初始化argc、argv处理
m0为Go程序启动后创建的第一个线程
GO基础语法
go 语言结构
-
在我们开始学习 Go 编程语言的基础构建模块前,让我们先来了解 Go 语言最简单程序的结构。
-
Go 语言的基础组成有以下几个部分:
- 包声明
- 引入包
- 函数
- 变量
- 语句 & 表达式
- 注释
CASE: 从分析 Hello World 程序的语言结构入手
接下来让我们来看下简单的代码,该代码输出了"Hello World!":
package main
import "fmt"
func main() {
/* 这是我的第一个简单的程序 */
fmt.Println("Hello, World!")
}
让我们来看下以上程序的各个部分:
- 第一行代码
package main定义了包名。你必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main。
package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为main的包。
-
下一行
import "fmt"告诉 Go 编译器这个程序需要使用fmt包(的函数,或其他元素),fmt包实现了格式化IO(输入/输出)的函数。 -
下一行
func main()是程序开始执行的函数。
main函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有init()函数则会先执行该函数)。
-
下一行
/*...*/是注释,在程序执行时将被忽略。单行注释是最常见的注释形式,你可以在任何地方使用以//开头的单行注释。多行注释也叫块注释,均已以/*开头,并以*/结尾,且不可以嵌套使用,多行注释一般用于包的文档描述或注释成块的代码片段。 -
下一行
fmt.Println(...)可以将字符串输出到控制台,并在最后自动增加换行字符\n。
使用
fmt.Print("hello, world\n")可以得到相同的结果。
Println这两个函数也支持使用变量,如:fmt.Println(arr)。如果没有特别指定,它们会以默认的打印格式将变量arr输出到控制台。
- 当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:
Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的protected)。
执行 Go 程序
让我们来看下如何编写 Go 代码并执行它。步骤如下:
-
打开编辑器如Sublime2,将以上代码添加到编辑器中。
-
将以上代码保存为
hello.go -
打开命令行,并进入程序文件保存的目录中。
-
输入命令
go run hello.go并按回车执行代码。 -
如果操作正确你将在屏幕上看到 "Hello World!" 字样的输出。
$ go run hello.go
Hello, World!
- 我们还可以使用
go build命令来生成二进制文件:
$ go build hello.go
$ ls
hello hello.go
$ ./hello
Hello, World!
注意事项
{不能单独放在一行。
所以,以下代码在运行时会产生错误:
package main
import "fmt"
func main()
{ // 错误,{ 不能在单独的行上
fmt.Println("Hello, World!")
}
Go 语言基础语法
- 上一节我们已经了解了 Go 语言的基本组成结构,本节我们将学习 Go 语言的基础语法。
Go 标记
- Go 程序可以由多个标记组成,可以是关键字,标识符,常量,字符串,符号。
如以下 GO 语句由 6 个标记组成:
fmt.Println("Hello, World!")
6 个标记是(每行一个):
1. fmt
2. .
3. Println
4. (
5. "Hello, World!"
6. )
行分隔符
-
在
Go程序中,一行代表一个语句结束。每个语句不需要像 C 家族中的其它语言一样以分号;结尾,因为这些工作都将由Go编译器自动完成。 -
如果你打算将多个语句写在同一行,它们则必须使用
;人为区分,但在实际开发中我们并不鼓励这种做法。
以下为两个语句:
fmt.Println("Hello, World!")
fmt.Println("菜鸟教程:runoob.com")
注释
-
注释不会被编译,每一个包应该有相关注释。
-
单行注释是最常见的注释形式,你可以在任何地方使用以
//开头的单行注释。 -
多行注释也叫块注释,均已以
/*开头,并以*/结尾。如:
/*
Author by xx教程
我是多行注释
*/
标识符
- 标识符用来命名变量、类型等程序实体。
- 一个标识符实际上就是一个或是多个字母(AZ和az)数字(0~9)、下划线_组成的序列,但第一个字符必须是字母或下划线而不能是数字。
以下是有效的标识符:
mahesh kumar abc move_name a_123
myname50 _temp j a23b9 retVal
以下是无效的标识符:
1ab(以数字开头)
case(Go 语言的关键字)
a+b(运算符是不允许的)
字符串连接
- Go 语言的字符串连接可以通过
+实现:
package main
import "fmt"
func main() {
fmt.Println("Google" + " Hello")
}
out :
Google Hello
关键字
下面列举了 Go 代码中会使用到的 25 个关键字或保留字:
| break | default | func | interface | select |
|---|---|---|---|---|
| case | defer | go | map | struct |
| chan | else | goto | package | switch |
| const | fallthrough | if | range | type |
| continue | for | import | return | var |
除了以上介绍的这些关键字,Go 语言还有 36 个预定义标识符:
| append | bool | byte | cap | close | complex | complex64 | complex128 | uint16 |
|---|---|---|---|---|---|---|---|---|
| copy | false | float32 | float64 | imag | int | int8 | int16 | uint32 |
| int32 | int64 | iota | len | make | new | nil | panic | uint64 |
| println | real | recover | string | true | uint | uint8 | uintptr |
程序一般由关键字、常量、变量、运算符、类型和函数组成。
程序中可能会使用到这些分隔符:括号 (),中括号 [] 和大括号 {}。
程序中可能会使用到这些标点符号:.、,、;、: 和 …。
Go 语言的空格
-
在 Go 语言中,空格通常用于分隔标识符、关键字、运算符和表达式,以提高代码的可读性。
-
Go 语言中变量的声明必须使用空格隔开,如:
var x int
const Pi float64 = 3.14159265358979323846
- 在运算符和操作数之间要使用空格能让程序更易阅读:
无空格:
fruit=apples+oranges;
在变量与运算符间加入空格,程序看起来更加美观,如:
fruit = apples + oranges;
在关键字和表达式之间要使用空格。
例如:
if x > 0 {
// do something
}
在函数调用时,函数名和左边等号之间要使用空格,参数之间也要使用空格。
例如:
result := add(2, 3)
格式化字符串
- Go 语言中使用
fmt.Sprintf或fmt.Printf格式化字符串并赋值给新串:
Sprintf根据格式化参数生成格式化的字符串并返回该字符串。Printf根据格式化参数生成格式化的字符串并写入标准输出。
- 示例:
SPrintf
package main
import (
"fmt"
)
func main() {
// %d 表示整型数字,%s 表示字符串
var stockcode=123
var enddate="2020-12-31"
var url="Code=%d&endDate=%s"
var target_url=fmt.Sprintf(url,stockcode,enddate)
fmt.Println(target_url)
}
out:
Code=123&endDate=2020-12-31
- 示例:
Printf
package main
import (
"fmt"
)
func main() {
// %d 表示整型数字,%s 表示字符串
var stockcode=123
var enddate="2020-12-31"
var url="Code=%d&endDate=%s"
fmt.Printf(url,stockcode,enddate)
}
out
Code=123&endDate=2020-12-31
- 更多内容参见:
FAQ
常配的变量: GOROOT/GOPATH/GOBIN/PATH/...
- GO安装目录
$GOROOT=/usr/local/go
- GO应用程序的工作目录
$GOPATH=/usr/local/var/www/go/$GOPATH=/opt/go-projects/opengemini
$GOPATH工作目录结构,约定有3个子目录(需要自行创建):
src—— 存放源代码文件pkg—— 存放编译后的文件bin—— 存放编译后的可执行文件

- GO应用程序的可执行文件目录
$GOBIN=$GOPATH/bin
PATH环境变量
$PATH=$PATH:$GOBIN:$GOROOT/bin| 将GO可执行文件加入PATH环境变量中
GOROOT与GOPATH路径的区别?
-
GOROOT和GOPATH是Go语言开发环境中的两个重要路径,它们在功能和使用场景上有明显的区别。 -
不同于其他语言,go中没有【项目】的说法,只有【包】
其中有两个重要的路径:
GOROOT和GOPATH
- Go开发相关的环境变量:
GOROOT:Go的安装目录,其bin目录下有go,gofmt等工具。(类似于java的JDK)Mac/Unix/Linux 默认 :
/usr/local/go
Windows 默认 :C:\Go
GOPATH:GOPATH是开发者的工作空间,保存go项目代码和第三方依赖包用于:
- 保存编译后的二进制文件。
go get和go install命令会下载go代码到GOPATH。import包时的搜索路径
GOPATH可以设置多个,其中,第一个将会是默认的包目录,使用 go get 下载的包都会在第一个path中的src目录下
使用 go install时,在哪个GOPATH中找到了这个包,就会在哪个GOPATH下的bin目录生成可执行文件
- 使用GOPATH时,GO会在以下目录中搜索包:
GOROOT/src:该目录保存了Go标准库代码。
GOPATH/src:该目录保存了应用自身的代码和第三方依赖的代码。
- 案例释义
假设程序中引入了如下的包:
import "Go-Player/src/chapter17/models"
第一步:
Go会先去GOROOT的src目录中查找,很显然它不是标准库的包,没找到。
第二步:继续在GOPATH的src目录去找,准确说是GOPATH/src/Go-Player/src/chapter17/models这个目录。如果该目录不存在,会报错找不到package。在使用GOPATH管理项目时,需要按照GO寻找package的规范来合理地保存和组织Go代码。
- GOROOT
GOROOT是Go语言的安装目录,包含了Go的编译器和标准库。
GOROOT在绝大多数情况下都不需要修改,因为它主要存储Go语言的安装文件,如编译器和标准库。
GOROOT目录下通常包含bin、doc和src子目录,其中bin目录包含go和gofmt等工具,类似于Java的JDK目录。
- GOPATH
GOPATH是开发时的工作目录,用于存放项目代码、编译后的二进制文件和第三方依赖包。
GOPATH可以设置多个,但第一个GOPATH会被默认使用
go get命令下载的包会存放在第一个GOPATH的src目录下,而go install命令会在找到包的GOPATH下的bin目录生成可执行文件。
- 设置和使用
在开发过程中,设置好
GOROOT和GOPATH对执行编译命令至关重要。
GOROOT通常不需要修改,而GOPATH则需要根据项目需求进行设置。
Go语言在寻找包时会首先在GOROOT的src目录中搜索,如果找不到才会在GOPATH的src目录中搜索。
GO111MODULE 配置?
-
当你开启了
GO111MODULE,仍然使用GOPATH模式的方法,在引入自定义模块时会报错。 -
GO111MODULE有3个值:off,on和auto(默认值)。
GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。GO111MODULE=on,go命令行会使用modules,而一点也不会去GOPATH目录下查找。GO111MODULE=auto,默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:
- 当前目录在
GOPATH/src之外, 且该目录包含go.mod文件- 当前文件在包含
go.mod文件的目录下面。
-
当
modules功能启用时,依赖包的存放位置变更为$GOPATH/pkg,允许同一个package多个版本并存,且多个项目可以共享缓存的module。 -
(1)使用了了相对路径:import "./models"
报错:build command-line-arguments: cannot find module for path /D/dev这里后面一堆本地路径
这是因为在go module下 你源码中 impot …/ 这样的引入形式不支持了, 应该改成 impot 模块名/ 。 这样就ok了
- (2)使用结合了GOPATH的形式:import "Go-Player/src/ademo/models"
于是我们把上面的
import改成了结合GOPATH的如上形式
报错:package Go-Player/src/ademo/models is not in GOROOT D:/development/go/src/GPlayer/src/ademo/models
- (3)彻底解决方法:用
go env -u恢复初始设置
不再使用go mod:
- go env -w GO111MODULE=off 或者 go env -w GO111MODULE=auto
- go env -u GO111MODULE
区别在于,如果GO111MODULE=on或者auto,在go get下载包时候,会下载到GOPATH/pkg/mod,引入时也是同样的从这个目录开始。如果这行了上述命令,那么在go get下载包时候,会下载到GOPATH/src 目录下
从最佳实践角度,go lang 中 推荐 GO111MODULE 的配置值是多少?原因呢?
- 在
Go语言中,GO111MODULE环境变量用于控制是否启用Go Modules功能。最佳实践推荐将GO111MODULE设置为on,原因如下:
- 明确启用模块支持
设置GO111MODULE=on可以明确启用Go Modules功能,无论当前工作目录是否在$GOPATH/src内。这避免了自动模式(auto)可能带来的混淆,确保项目始终使用模块化的方式管理依赖。- 未来版本的默认行为
从 Go 1.14 开始,GO111MODULE=on 已经成为推荐设置,并且在更高版本中将成为默认值。使用 on 可以确保代码和项目管理方式与未来版本保持一致,减少迁移成本。- 更好的依赖管理
Go Modules 提供了更强大的依赖管理功能,包括版本控制、离线构建、模块隔离和可重现构建等。启用模块支持可以充分利用这些特性,提高项目的可维护性和稳定性。- 简化项目结构
使用 Go Modules 后,项目不再依赖于 GOPATH 模式,而是通过 go.mod 文件管理依赖。这使得项目的结构更加清晰,也便于团队协作。
因此,为了确保项目依赖管理的一致性和未来兼容性,推荐将 GO111MODULE 设置为 on。
Go Modules模式 vs.GOPATH模式
如果是 Go Modules 模式下,go get 会将模块下载到 GOPATH/pkg/mod 目录下(默认情况下),并且会更新 go.mod 文件,记录模块的版本信息。
如果是 GOPATH 模式下,go get 会将代码下载到 GOPATH/src 目录下。
Hello world(GOPATH版) 【被废弃的方式】
此处仅介绍
Hello world(GOPATH版),虽然此种方法不推荐使用,但是初学者在使用的时候仍会遇到很多问题。后续将介绍如何使用Go Module版
- (1)设置并查看GOPATH和GOROOT环境变量
安装go SKD目录:D:\development\go
go项目存放目录:D:\development\jetbrains\goland\workspace,且此目录下含有bin、src、pkg 3个文件夹,src文件夹用来存放项目代码
当引入module时,首先在GOROOT的src目录下查找,然后再GPOPATH的src目录下查找

- (2)GOLand环境配置
在D:\development\jetbrains\goland\workspace\src目录下新建项目GO-Player
- bin:存放编译后的exe文件
- pkg:存放自定义包的目录
- src:存放项目源文件的目录

按如下指令进行配置

可在Settings中选择SDK和添加GOPATH

- (3)测试
models : Student.go

- main : hello.go
//hello.go
package main
import (
//"./models" //相对路径
"Go-Player/src/ademo/models" //根据GOPATH找
//根据GOPATH:D:\development\jetbrains\goland\workspace,在其src目录下查找
//即GOPATH/src/Go-Player/src/ademo/models
"fmt"
)
func main() {
stu := models.Student{
Name: "张三",
}
fmt.Println(stu)
}
此处仅介绍网上大部分GOPATH版本。
Go语言Hello World都只简单地介绍了GOPATH版本。
但是从Go的1.11版本之后,已不再推荐使用GOPATH来构建应用了。
也就是说GOPATH被认为是废弃的,错误的做法。
Intellij IDEA 配置Go语言开发环境?
- 推荐文献
X 参考文献
Go v1.20 +
Python v3.7+

本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

浙公网安备 33010602011771号