重拾 Golang

什么是 Golang?

 Go™ is a programming language built to resemble a simplified version of the C programming language.

特性

类别

  • 静态语言
  • 编译型语言

优点

  • 语言层面支持并发
  • 无依赖,直译机器码
  • 内置 runtime,支持 GC
  • 可跨平台编译
  • 支持内嵌 C
  • 丰富的标准库
  • 学习曲线低

缺点

  • 接口是枚举类型
  • import 包不支持版本
  • goroutine 一旦启动,切换将不受程序控制

环境配置

安装

 根据操作系统(这里以 MacOS 为例),在 Download 页面下载对应的安装包,进行安装

1
2
3
# 安装完成后,iTerm 中看到可以执行 go 命令了
$ which go
/usr/local/go/bin/go

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 环境变量
$ vim ~/.bashrc
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin

# 工作目录
# bin: 存放可执行文件
# pkg: 存放编译好的库文件
# src: 存放 go 的源文件
$ mkdir -p /code/gopath
$ vim ~/.bashrc
export GOPATH=/code/gopath
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

$ source ~/.bashrc

Hello world

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
# 创建项目目录
$ mkdir -p $GOPATH/src/test/hello
$ cd $GOPATH/src/test/hello

# 编写 go 源文件
$ vim hello.go
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}

# 执行
$ go run hello.go
Hello, world!
$ ll
total 4.0K
-rw-r--r-- 1 benedictjin wheel 75 1 15 11:20 hello.go

# 编译
$ go build
$ ll
total 2.0M
-rwxr-xr-x 1 benedictjin staff 2.0M 1 15 11:20 hello*
-rw-r--r-- 1 benedictjin wheel 75 1 15 11:20 hello.go

# 运行可执行文件
$ ./hello
Hello, world!

# 清理编译的中间文件
$ go clean
$ ll
total 4.0K
-rw-r--r-- 1 benedictjin wheel 75 1 15 11:20 hello.go

下载依赖

1
2
3
4
5
6
7
$ GOROOT=/usr/local/go
$ GOPATH=/code/gopath

# 单个依赖
$ /usr/local/go/bin/go get -t -v github.com/golang/snappy/...
# 所有依赖
$ /usr/local/go/bin/go get -t -v ./...

基本语法

常量

说明

1
const <常量名> <常量类型> = <常量值>

举例

1
2
3
4
5
6
7
const NODES int = 3

const (
NODES int = 4
SHARDS int = 64
REPLICATIONS int = 3
)

三元表达式

说明

 Golang 并不支持三元表达式,只能用 if-else 来表达对应的含义

举例

1
2
3
4
5
if expr {
n = trueYuzhouwan
} else {
n = falseYuzhouwan
}

数组

说明

1
var <变量名> [SIZE] <元素类型>

举例

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
// 声明数组变量
var yuzhouwan [10] float32
// 初始化数组
var yuzhouwan = [3]float32{0.1, 0.2, 0.30000000000000004}
// 不指定数组长度,Golang 会根据数组内的元素,来设置数组的大小
var yuzhouwan = [...]float32{0.1, 0.2, 0.30000000000000004}

// 遍历数组
var arr [3]int
var i, j int

for i = 0; i < 3; i++ {
arr[i] = i
}

for j = 0; j < 3; j++ {
fmt.Printf("%d = %d\n", j, arr[j])
}

// 打印所有元素
fmt.Printf("%v\n", arr)

// 增加新元素
var yuzhouwan [] int
for n := 0; n < 3; n++ {
yuzhouwan = append(yuzhouwan, n)
}
fmt.Printf("%v", yuzhouwan)

List

举例

1
2
3
4
5
6
7
l := list.New()
for i := 0; i < 3; i++ {
l.PushBack(i)
}
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}

Map

举例

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
// 初始化
site := map[string]int{
"yuzhouwan": 0,
"blog": 1,
}

// 增加新元素
site := make(map[string]int)
site["yuzhouwan"] = 0
site["blog"] = 1

// 判断指定 key 是否存在于 map 中
if value, exists := site["yuzhouwan"]; exists {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}

// 遍历
m := map[string]int{"yuzhouwan": 1, "blog": 2,}
for k, v := range m {
fmt.Printf("%s=%d\n", k, v)
}

// 按照 Key 排序后遍历
m := make(map[int]string)
m[1] = "a"
m[2] = "c"
m[0] = "b"
var keys []int
for k := range m {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
fmt.Printf("%v : %v\n", k, m[k])
}

接口

说明

1
2
3
type <接口名> interface {
<方法名称>() <方法返回值>
}

举例

1
2
3
4
type Value interface {
String() string
Set(string) error
}

自定义数据类型

说明

1
type <自定义类型> <原始类型>

举例

1
type ErrorHandling int

给自定义数据类型扩展方法

说明

 可以使得自定义数据类型作为某一个 interface 的实现类,只需要扩展 interface 中申明的方法即可

举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
type Value interface {
String() string
Set(string) error
}

type StringsFlag []string

func (v *StringsFlag) Set(s string) error {
var err error
*v, err = str.SplitQuotedFields(s)
if *v == nil {
*v = []string{}
}
return err
}

func (v *StringsFlag) String() string {
return "<StringsFlag>"
}

初始化空的结构体

说明

 struct{} 表示一个空的结构体,不包含任何的属性和方法,相当于 Java 中的 Object。而 struct{}{} 表示对空的结构体进行初始化,相当于 Java 中的 new Object()

举例

1
struct{}{}

defer 异步

说明

 被 defer 关键字修饰的函数调用可以异步地执行。多次 defer 异步调用之间会以逆序的顺序执行,类似于压栈出栈的过程。并且,defer 修饰的函数会在外层函数返回之前进行调用(准确来说,是在外层函数设置返回值之后, 在即将返回之前)。因此,defer 常用于资源的释放

举例

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

import "fmt"

func main() {
for i := 1; i <= 3; i++ {
//noinspection GoDeferInLoop
defer fmt.Println(i)
fmt.Println(fmt.Sprintf("for %d looping...", i))
}
fmt.Println("done")
}
1
2
3
4
5
6
7
for 1 looping...
for 2 looping...
for 3 looping...
done
3
2
1

踩到的坑

version go1.11.9 does not match go tool version go1.11.5

解决

1
2
$ brew uninstall --ignore-dependencies go
Uninstalling /usr/local/Cellar/go/1.11.5... (9,298 files, 404.3MB)

资料

Blog

Github

Common

Prometheus

TiDB

欢迎加入我们的技术群,一起交流学习

人工智能 (高级)& (进阶)| BigData | 算法

Benedict Jin wechat
Subscribe to my blog by scanning my public wechat account.