Go快速入门

文档

语言特点

  • 自动立即回收
  • 更丰富的内置类型
  • 函数多返回值
  • 错误处理
  • 匿名函数和闭包
  • 类型和接口
  • 并发编程
  • 反射
  • 语言交互性

基础语法

数据类型

语言声明与作用域

语言作用域

  • 声明在函数内部,是函数的本地值,类似** private**
  • 声明在函数外部,是对当前包可见(包内所有 .go 文件都可见)的全局值,类似 protect
  • 声明在函数外部且首字母大写是所有包可见的全局值,类似 public

语言定义

var(声明变量)

语法

1
2
3
4
5
6
7
# 单个
var 变量名
# 批量
变量类型 var (
a int
b int
)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 正常定义方式
var a int = 0
fmt.Println("常定义方式 :", a)

// 根据值得知类型
var b = 0
fmt.Println("根据值得知类型 :", b)

// := 隐式定义方式
c := 0 fmt.Println(" := 定义方式 :", c)

// 批量定义
var ( v_a int = 201 v_b int = 202 v_c int )
vc = 203
fmt.Printf("批量声明变量 v_a:%a | v_b:%b | v_c:%c \n", v_a, v_b, v_c)

const(声明常量)

语法

语法

1
2
3
4
5
6
7
8
const identifier [type] = value
const (
n1 = iota //0
n2 //1
n3 //2
n4 //3
)
const c_name1, c_name2 = value1, value2

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
const GNAME = "GNAME"
const (
a = 1
b = 2
)
const (
a1 = 10
b1
c1
)
fmt.Println("GNAME", GNAME)
fmt.Println("a, b: ", a, b)
fmt.Println("a1, b1, c1: ", a1, b1, c1)

iota(特殊常量)

iota 可以认为是一个可以被编译器修改的常量,是 go 语言的常量计数器,只能在常量的表达式中使用。iota 在 const 关键字出现时将被重置为 0。const 中每新增一行常量声明将使 iota 计数一次( iota 可理解为 const 语句块中的行索引)。 使用 iota 能简化定义,在定义枚举时很有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const (
a1 = iota
b1
c1
)
const (
a1 = iota
b1 = iota
c1 = iota
)
fmt.Println("a1, b1, c1: ", a1, b1, c1)
// 输出都是 : a1, b1, c1: 0 1 2

const (
a = iota //0
b //1
c //2
d = "ha" //独立值,iota += 1
e //"ha" iota += 1
f = 100 //iota +=1
g //100 iota +=1
h = iota //7,恢复计数
i //8
)
fmt.Println(a, b, c, d, e, f, g, h, i)
// 输出是 :0 1 2 ha ha 100 100 7 8

const (
a,
d = iota + 1, iota + 10
b,
e
c,
f
)
fmt.Println(a, b, c, d, e, f)
// 输出是 :1 2 3 10 11 12

type(声明类型)

语法

1
2
3
4
5
type 类型名 struct {
字段名 字段类型
字段名 字段类型

}

其中:

1. 类型名:标识自定义结构体的名称,在同一个包内不能重复。

2. 字段名:表示结构体字段名。结构体中的字段名必须唯一。

3. 字段类型:表示结构体字段的具体类型。

对于学习过其他语言的同志来说可以理解为是对象属性,只是不存在方法

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
type class struct {
name string
stage int
}

func main() {
fmt.Println(class{"class", 1})
var c class
c.name = "demo class"
c.stage = 1
fmt.Println("名称: ", g.name)
fmt.Println("阶段: ", g.stage)
}

func(声明函数)

特点

  • 无需声明原型
  • 支持不定变参
  • 支持多返回值
  • 支持命名返回参数
  • 支持匿名函数和闭包
  • 函数也是一种类型,一个函数可以赋值给变量
  • 不支持 嵌套 (nested) 一个包不能有两个名字一样的函数
  • 不支持 重载 (overload)
  • 不支持 默认参数 (default parameter)

语法

1
func function_name( [parameter list] ) [return_types] { 函数体 }

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func main() {
a, b := test(1, 2, "sum")
fmt.Println("a,b : ", a, b)
dome()
}

func test(x, y int, s string) (int, string) {
// 类型相同的相邻参数,参数类型可合并。 多返回值必须用括号。
n := x + y
return n, s
}

func dome() {
fmt.Println("dome")
}

init 和 main 函数

main 函数

Go 语言程序的默认入口函数(主函数):func main() ,函数体用{}一对括号包裹。

main 函数只能用于 main 包中,且只能定义一个。如同 PHP 框架中的 index.php 。

init 函数

go 语言中 init 函数用于包(package)的初始化,该函数是 go 语言的一个重要特性。可以理解为如同其他语言中的面向对象。func init() { }。

特点

  • init 函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等
  • 每个包可以拥有多个 init 函数
  • 包的每个源文件也可以拥有多个 init 函数
  • 同一个包中多个 init 函数的执行顺序 go 语言没有明确的定义(说明)
  • 不同包的 init 函数按照包导入的依赖关系决定该初始化函数的执行顺序
  • init 函数不能被其他函数调用,而是在 main 函数执行之前,自动被调用

示例

1
2
3
4
5
6
var name string func init() {
name = "demo"
}
func main() {
fmt.Println(name)
}

执行流程

  • 对同一个 go 文件的 init()调用顺序是从上到下的。
  • 对同一个 package 中不同文件是按文件名字符串比较“从小到大”顺序调用各文件中的 init()函数。
  • 对于不同的 package,如果不相互依赖的话,按照 main 包中”先 import 的后调用”的顺序调用其包中的 init(),如果 package 存在依赖,则先调用最早被依赖的 package 中的 init(),最后调用 main 函数。
  • 如果 init 函数中使用了 println()或者 print()会导致不会顺序执行过程 ,这两个函数官方只推荐在测试环境中使用,对于正式环境不要使用。

import 和 package 的使用

  • golang 使用 package 来管理定义模块,使用 import 关键字来导入使用。
  • 如果导入的是 go 自带的包,则会去安装目录 $GOROOT/src,按照包路径加载。
  • 如果是我们 go get 安装的或自定义的包,则会去 $GOPATH/src 加载。

package

  • 模块目录文件夹名作为包名,前面的路径只是用来导入而和包名无关
  • package 的存放位置是以$GOPATH/src 作为根目录,然后灵活的按照目录去组织,且包名需与最后一级目录名一致。

示例

import

常用

1
2
3
4
import (
"database/sql"
"github.com/go-sql-driver/mysql"
)

别名

1
2
3
4
import (
"database/sql"
mysql "github.com/go-sql-driver/mysql"
)

下划线

忽略导入的包,只执行包内的 init 方法

当导入一个包时,该包下的所有文件的 init() 函数都会被执行,然而,有些时候我们并不需要把整个包都导入进来使用,仅仅是希望它执行 init() 函数而已。

1
import _ 包路径 // 只是引用该包,仅仅是为了调用init()函数,所以无法通过包名来调用包中的其他函数。

示例

1
2
import "database/sql"
import _ "github.com/go-sql-driver/mysql"

忽略返回值

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"

func main() {
a, _ := compare(1)
fmt.Println(a)
}

func compare(a int) (int, error) {
return a, nil
}

解释 1

  • 下划线意思是忽略这个变量.
  • 比如 compare,返回值为 int, error
  • 普通写法是 a,err := compare(1)
  • 如果此时不需要知道返回的错误值
  • 就可以用 a,_ := compare(1)
  • 如此则忽略了 error 变量

解释 2

  • 占位符,意思是那个位置本应赋给某个值,但是咱们不需要这个值
  • 所以就把该值赋给下划线,意思是丢掉不要
  • 这样编译器可以更好的优化,任何类型的单个值都可以丢给下划线
  • 这种情况是占位用的,方法返回两个结果,而你只想要一个结果
  • 那另一个就用”_“占位,而如果用变量的话,不使用,编译器是会报错的

接口断言

1
2
3
4
5
6
7
type Person interface {
Say()
}

type Student struct {
}
var _ Person = Student{}

判断 Student是否实现了 Person, 用作类型断言,如果 Student 没有实现 Person ,则会报编译错误。

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Go is a tool for managing Go source code.

Usage:

go <command> [arguments]

The commands are:

bug start a bug report
build compile packages and dependencies
clean remove object files and cached files
doc show documentation for package or symbol
env print Go environment information
fix update packages to use new APIs
fmt gofmt (reformat) package sources
generate generate Go files by processing source
get add dependencies to current module and install them
install compile and install packages and dependencies
list list packages or modules
mod module maintenance
run compile and run Go program
test test packages
tool run specified go tool
version print Go version
vet report likely mistakes in packages

Use "go help <command>" for more information about a command.

Additional help topics:

buildconstraint build constraints
buildmode build modes
c calling between Go and C
cache build and test caching
environment environment variables
filetype file types
go.mod the go.mod file
gopath GOPATH environment variable
gopath-get legacy GOPATH go get
goproxy module proxy protocol
importpath import path syntax
modules modules, module versions, and more
module-get module-aware go get
module-auth module authentication using go.sum
packages package lists and patterns
private configuration for downloading non-public code
testflag testing flags
testfunc testing functions
vcs controlling version control with GOVCS

Use "go help <topic>" for more information about that topic.
  • go env 用于打印 Go 语言的环境信息。
  • go run 命令可以编译并运行命令源码文件。
  • go get 可以根据需求从互联网上下载或更新指定的代码包及其依赖包,并对它们进行编译和安装。
  • go build 命令用于编译我们指定的源码文件或代码包以及它们的依赖包。
  • go install 用于编译并安装指定的代码包及它们的依赖包。
  • go clean 命令会删除掉执行其它命令时产生的一些文件和目录。
  • go doc 命令可以打印附于 Go 语言程序实体上的文档。我们可以通过把程序实体的标识符作为该命令的参数来达到查看其文档的目的。
  • go test 命令用于对 Go 语言编写的程序进行测试。
  • go list 命令的作用是列出指定的代码包的信息。
  • go fix 会把指定代码包的所有 Go 语言源码文件中的旧版本代码修正为新版本的代码。
  • go vet 是一个用于检查 Go 语言源码中静态错误的简单工具。