Notes
Go
基础

基础

环境搭建

下载安装包

下载地址 (opens in a new tab)

下载完成后,可以使用 go version 查看版本信息。

$ go version
go version go1.15.6 darwin/amd64

环境变量

Go 语言中环境变量主要有两个:

  • GOROOT:Go 语言的安装目录。GOROOT/src 目录下的函数都可以被导入和使用。例如 fmt.Println
  • GOPATH:除了 Go 语言的安装目录外的源码目录,同样可以调用目录下的函数。

可以使用 go env 查看环境变量。

$ go env GOROOT
/usr/local/go
$ go env GOPATH
/Users/username/go

可以使用 export 命令设置环境变量。

$ export GOROOT=/usr/local/go
$ export GOPATH=/Users/username/go

IDE

通常使用 GoLand 进行开发。下载地址:GoLand (opens in a new tab)

Go 的跨平台

Java 一直遵循一次编译,到处运行的原则,虽然 Go 不是一次编译,到处运行的语言,但是能做到一次编写,到处运行。这是因为 Go 不像 Java 拥有自己的虚拟机,Go 语言的编译器会将 Go 代码编译成机器码,然后直接运行在操作系统上。虽然牺牲了一定的便利性,但是保障了性能。

Go 语言会区分运行程序的操作系统,主要通过操作系统CPU 架构来区分。

$ go env GOOS
windows
$ go env GOARCH
amd64

常见的 Goos 和 Goarch 如下:

GOOSGOARCH说明
darwinamd64Mac OS
linuxamd64Linux
windowsamd64Windows

可以使用 go tool dist list 查看所有支持的操作系统和 CPU 架构。

$ go tool dist list

我们无需进行任何显式的操作,Go 语言会自动识别当前的操作系统和 CPU 架构,然后编译成对应的可执行文件。

不过当我们尝试在 MacOS 上编译 Windows 的可执行文件时,需要进行一些额外的操作。

$ export GOOS=windows GOARCH=amd64
$ go build hello.go

如果要恢复原来的运行状态,需要对这两个变量进行清空。

$ export GOOS= GOARCH=

编译执行过程

我们通过 go help build 查看编译命令的帮助信息。

$ go help build
- a
    force rebuilding of packages that are already up-to-date.
- n
    print the commands but do not run them.
...

有三个值得我们关注的参数:

  • -n:打印编译的详细过程,但不执行。相当于预览。
  • -x:打印编译的详细过程,并执行。
  • --work:打印编译的详细过程,并且保留生成的中间文件和目录,方便我们进行调试。
$ go build -x hello.go
WORK=/var/folders/28/1z5z1j7d7zq7z1z7z1z7z1z7z1z7z1z/T/go-build1234567890
mkdir -p $WORK/b001/
cat >$WORK/b001/_gomod_.go << 'EOF' # internal
packagefile command-line-arguments=/Users/username/Libraries/Caches/go-build/12/34567890abcdefg
packagefile fmt=/usr/local/go/src/fmt.a
packagefile runtime=/usr/local/go/src/runtime.a
...
...
...
packagefile runtime=/usr/local/go/src/path.a
modinfo "0w\xaf\x1f\x.."
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/b001/exe/hello -trimpath $WORK -p main -complete -buildid 1234567890abcdefg -D _/Users/username/Libraries/Caches/go-build -I $WORK/b001 -pack ./hello.go
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/a.out -L $WORK/b001 -extld=clang -buildmode=exe -buildid=1234567890abcdefg $WORK/b001/exe/hello
mv $WORK/b001/exe/a.out hello

快速开始

Hello World

$ mkdir hello
$ cd hello
$ go mod init hello
go: creating new go.mod: module hello

通过 go mod init 命令初始化一个新的模块,会在当前目录下生成一个 go.mod 文件,内容如下:

module hello
 
go 1.15

然后创建一个 hello.go 文件,内容如下:

package main
 
import "fmt"
 
func main() {
    fmt.Println("Hello, World!")
}

运行 go run hello.go,可以看到输出结果:

$ go run hello.go
Hello, World!

Main 函数

Go 程序的入口是 main 函数。

Go 程序执行时,将先从 fmt 包中导入 Println 函数以及其他的函数,并在 main 函数中调用。

编译

$ go build
$ ./hello
Hello, World!

这里 go build 命令会生成一个可执行文件,然后执行该文件。

在 Windows 系统下,会生成一个 hello.exe 文件,然后执行该文件。

注释和转义符

注释

Go 语言中的注释有两种,分别是单行注释和多行注释。

单行注释以 // 开头,多行注释以 /* 开头,以 */ 结尾。

// 这是单行注释
 
/*
这是多行注释
*/

不过不推荐使用多行注释,Go 在源代码中均使用单行注释。

转义符

Go 语言中的转义符有以下几种:

转义符含义
\r回车符(返回行首)
\n换行符(直接跳到下一行的同列位置)
\t制表符
\\反斜杠
\'单引号
\"双引号

转义符的使用十分麻烦,推荐使用后面的原义字符

原义字符

类似于 JS 中的模板字符串,Go 语言中也有原义字符。

package main
 
import "fmt"
 
func main() {
    a := `"hello
    world"`
    fmt.Println(a)
}

输出结果:

"hello
    world"

Go 的分号

Go 语言中的语句结尾不需要分号,如果写了分号,编译器会自动忽略。

fmt 格式化字符

格式化字符含义
%v值的默认格式
%+v类似 %v,但输出结构体时会添加字段名
%#v值的 Go 语法表示
%T值的类型的 Go 语法表示
%%百分号
%b二进制表示
%c相应 Unicode 码点所表示的字符
%d十进制表示
%o八进制表示
%q单引号围绕的字符字面值,由 Go 语法安全地转义
%x十六进制表示,字母形式为小写 a-f
%X十六进制表示,字母形式为大写 A-F
%UUnicode 格式:U+1234,等同于 "U+%04X"
%e科学计数法表示
%E科学计数法表示
%f浮点数表示
%F等价于 %f
%g根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的 0)输出
%G根据情况选择 %E 或 %F 以产生更紧凑的(无末尾的 0)输出
%s字符串表示

运算符

算术运算符

运算符含义
+相加
-相减
*相乘
/相除
%求余

关系运算符

运算符含义
==相等
!=不等
>大于
<小于
>=大于等于
<=小于等于

逻辑运算符

运算符含义
&&逻辑与
`
!逻辑非

位运算符

运算符含义
&按位与
``
^按位异或
<<左移
>>右移

赋值运算符

运算符含义
=简单赋值
+=相加后赋值
-=相减后赋值
*=相乘后赋值
/=相除后赋值
%=求余后赋值
<<=左移后赋值
>>=右移后赋值
&=按位与后赋值
|=按位或后赋值
^=按位异或后赋值

其他运算符

运算符含义
&取地址
*取指针的值
++自增
--自减
.结构体成员

命令行参数的接收

Go 中可以通过 os 包来接收命令行参数。

package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    for i, arg := range os.Args {
        fmt.Printf("arg[%d]: %s\n", i, arg)
    }
}

执行 go run main.go hello world,可以看到输出结果:

arg[0]: /var/folders/28/1z5z1j7d7zq7z1z7z1z7z1z7z1z7z1z/T/go-build1234567890/b001/exe/main
arg[1]: hello
arg[2]: world

这是顺序获得命令行参数的方法,实际上还能通过参数名来获取参数。

package main
 
import (
    "flag"
    "fmt"
)
 
func main() {
    var name = flag.String("name", "everyone", "The greeting object.") // 参数名,默认值,参数说明
    flag.Parse()  // 解析参数
    fmt.Println("Hello, ", *name) // *name 表示获取 name 的值, 如果直接使用 name 会输出指针地址
}

执行 go run main.go -name=world,可以看到输出结果:

Hello, world