「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」
为什么我开始学习Go语言
天生支持并发
很重要的一点是Go语言天生支持并发,或许其他语言写一个并发并不难,例如Java的Thread。
但是深入学习之后会发现里面的细节很多,而且并发编程的八股文一年一个新花样。而却,大多数现代编程语言(如Java,Python等)都来自90年代的单线程环境。虽然一些编程语言的框架在不断地提高多核资源使用效率,例如 Java 的 Netty 等,但仍然需要开发人员花费大量的时间和精力搞懂这些框架的运行原理后才能熟练掌握。而Go语言作为21世纪诞生的语言,从创建之初就是在多核版本下。
Go语言的并发是基于 goroutine 的,goroutine 类似于线程,但并非线程。可以将 goroutine 理解为一种虚拟线程。Go 语言运行时会参与调度 goroutine,并将 goroutine 合理地分配到每个 CPU 中,最大限度地使用CPU性能。开启一个goroutine的消耗非常小(大约2KB的内存),而一个java线程至少需要 1M ,你可以轻松创建数百万个goroutine。
goroutine的特点:
goroutine具有可增长的分段堆栈。这意味着它们只在需要时才会使用更多内存。goroutine的启动时间比线程快。goroutine原生支持利用channel安全地进行通信。goroutine共享数据结构时无需使用互斥锁。
GoLand 安装
Golang 环境安装
安装包下载路径 国内地址
go语言官网
选择对应版本的安装包安装即可
检查是否安装成功
# 使用go version命令即可
wangdeMacBook-Pro:~ wang$ go version
go version go1.15.2 darwin/amd64
查看go 环境 因为go默认的依赖环境是国外地址,所以有些依赖包下载会很慢
go env命令查看go环境
我这里已经改过GOPROXY了 go代理
修改GOPROXY
$ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct
安装GoLand
自行微信搜一搜,比百度还要好用哦
Go语言基本语法
从Hello World 开始
新建go项目
配置GOPROXY 因为之后学习的很多依赖包都是在github上,下载速度很慢
创建完成之后如下
新建go文件 选择 Simple Application 会自动生成一个入口函数
点击main 前面的三角号。运行一下吧
Hello World
Process finished with exit code 0
我们的 Hello World 就ok了
Go语言中的命令行操作
go 语言作为编译型语言,需要先进行编译才可以运行。在命令行中试一下该如何进行go程序的编译和运行
在命令行中cd 到当前程序所在目录
go build 用于测试编译包,主要检查是否会有编译错误,如果是一个可执行文件的源码(即是 main 包),就会在当前目录直接生成一个可执行文件( .exe 文件)。
编译之后在同级目录会生成可执行文件,可直接运行
也可以go run 运行编译并直接运行程序,它会产生一个临时文件(但实际不存在,也不会生成 .exe 文件),直接在命令行输出程序执行结果,方便用户调试。运行速度也相应较慢
wangdeMacBook-Pro:01_helloword wang$ go build main.go
wangdeMacBook-Pro:01_helloword wang$ ./main
Hello World!
wangdeMacBook-Pro:01_helloword wang$ go run main.go
Hello World!
配置GoLand
勾选Reformat code 在保存时会自动格式化代码
go语言中的常量和变量
变量和常量是编程中必不可少的部分,也是很好理解的一部分。
标识符
在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名、常量名、函数名等等。 Go语言中标识符由字母数字和_(下划线)组成,并且只能以字母和_开头。 举几个例子:abc, _, _123, a123。(大部分语言的标识符都是这样规定的)
关键字 关键字是指编程语言中预先定义好的具有特殊含义的标识符。 关键字和保留字都不建议用作变量名。 Go语言的关键字有下面这些,不用背下来,之后的学习慢慢就会记住了
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
未使用的保留字(类似于关键字)
Constants: true false iota nil
Types: int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
float32 float64 complex128 complex64
bool byte rune string error
Functions: make len cap new append copy close delete
complex real imag
panic recover
变量
参考代码
标准声明
Go语言的变量声明格式为:
var 变量名 变量类型
变量声明以关键字var开头,变量类型放在变量的后面,行尾无需分号。 举个例子:
var name string
var age int
批量声明
一次声明多个 变量
var (
a string
b int
c bool
d float32
)
变量的初始化 Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值,例如: 整型和浮点型变量的默认值为
0。 字符串变量的默认值为空字符串。 布尔型变量默认为false。 切片、函数、指针变量的默认为nil。对于string 类型的初始化为 空字符串 所以需要用%q进行格式化
var 变量名 类型 = 表达式
var hobby string = "唱歌"
也可以一次初始化多个变量
var height, university = 175, "清华大学隔壁八百公里外"
类型自动推导,当没有执行类型的时候,go语言会自动根据值来推断当前变量类型
var hobby = "唱歌"
短变量声明(推荐) 在函数内部,可以使用更简略的
:=方式声明并初始化变量。 注意 :函数内部声明的变量必须使用,否则会编译错误
a := 100
fmt.Println(a)
匿名变量 上面我们说了函数声明则必须使用,那么假如我们一个函数返回了两个值,该怎么办呢
func main() {
x, _ := doubleReturn()
fmt.Println(x)
}
func doubleReturn() (x, y int) {
return 1, 2
}
这时就用到了匿名变量(anonymous variable) _ ,它更像是一个占位符。
匿名变量不占用命名空间,不会分配内存,所以匿名变量之间不存在重复声明。
注意事项:
- 函数外的每个语句都必须以关键字开始(var、const、func等)
:=不能使用在函数外。_多用于占位,表示忽略值。
常量
常量是恒定不变的值,多用于定义程序运行期间不会改变的那些值。 常量的声明和变量声明非常类似,只是把var换成了const,常量在定义的时候必须赋值。例如 PI = 3.1415926, KB = 1024等
标准声明
const PI = 3.1415926
const E = 2.71828
批量声明
const (
pi = 3.1415926
e = 2.71828
)
在批量声明时,如果没有初始化值,则和上面的值一样,此时的 a,b 都为 2.71828
const (
pi = 3.1415926
e = 2.71828
a
b
)
常量计数器 iota
iota在const关键字出现时将被重置为0。const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。 使用iota能简化定义,在定义枚举时很有用。
const (
n1 = iota //0
n2 //1
n3 //2
n4 //3
)
使用_ 跳过某些值
const (
m1 = iota //0
m2 //1
_
m4 //3
)
插队
const (
k1 = iota //0
k2 = 100 //100
k3 = iota //2
k4 //3
)
const k5 = iota //0
多个iota定义在一行
const (
l1, l2 = iota + 1, iota + 2 //1,2
l3, l4 //2,3
l5, l6 //3,4
)
最常用的位运算
const (
b = 1 << (10 * iota)
kb
mb
gb
tb
pb
)
总结
这些就是这篇文章的所有,相关的代码会在github上