终于有应用场景需要用到Go了,这次算是正式开始学了。其实在我眼里,Go的应用场景主要有以下几点
- 超高并发/超高性能,能轻松创建上百万线程而不会让服务器宕机
- 多核CPU充分利用
- 系统底层应用开发
其实自己的项目或者现在公司的项目,都配不上”超高”两字,所以也就没考虑过用Go
语言,而是用能快速开发的Python
和PHP
。
安装Go
需要注意的是,在使用go之前,必须设置GOPATH这个环境变量,并且该环境变量不允许和GOROOT
一样,该目录是用来存放第三方包的源码的地方。
1 |
编译与构建
如果是一个单独的文件运行程序,那么该文件的package必须是package main
,否则会出现go run: cannot run non-main package
错误
基本语法
变量
- 基本的变量类型有
bool/string/int/int8/int16/int32/int64/uint/uint8/uint16/uint32/uint64/unitptr/float32/float64/complex64/complex128
(其中uint8
=byte
,int32
=rune
) - 如果是在块中定义的变量(例如if for等),作用于仅仅在块中
1 | var a, b bool // var声明变量,必须在后面指定类型。而且会给一个默认值 |
数字/整型/布尔值
- 布尔值的默认值为false
- 由于
int
类型的范围,与平台有关,所以在长度不确定的时候,最好使用int64
1 | string:=strconv.Itoa(int) // 整型转换为字符串 |
数组slice
1 | var g [10]int // 声明g为一个包含10个int的数组 |
字符串/json
1 | str = `定义超长的字符串` |
结构体/类/接口
go语言本身没有类的概念,但是可以用结构体来实现一个类。
判断结构体是否为空,可以直接判断里面的某个字段是否为空,或者,新建一个空结构体,例如
(Option{}) == option
结构体中属性开头字母如果大写,表示可以在其他包中访问,否则只能在本包中访问。这个地方需要特别注意的是,像使用
json.Marshal
类似的操作,也是访问不到小写开头属性的,因为json
算是另外一个包了接口
interface
类似于基类或者接口类,定义一些公有的方法然后继承者去实现空接口类型
interface{}
可以存储任意数据类型的实例,如果用于函数参数表示该函数接收任意的数据类型由于有些函数确定了入参类型,但是接口又代表的是所有类型,所以如果要把一个接口传入一个明确类型的函数中,就需要特别指明其类型。例如
function(var.(string)
。不过这不能作用于接口数组,否则会出现invalid type assertion non-interface type []... on left
这样的错误,如果要传入一个数组,需要我们构建一下参考:1
2
3
4
5
6s := make([]interface{}, len(t))
for i, v := range t {
s[i] = v
}
function(s) // function([] interface{})
1 | // 创建匿名结构体 |
映射map/字典
1 | // 变量映射,额,跟字典超级像呀 |
控制语句
1 | // if语句 |
函数
1 | // defer语句会将语句推迟到外层函数返回之后执行,相当于finally,类似析构函数,例如 |
错误处理
通常函数都会返回一个error值
1 | re, err := Abs() |
go协程-go程
Go的协程居然就叫go。select
语句让go可以等待多个通信操作。
1 | go f(x,y,z) // 这样会启动一个新的协程去处理f函数 |
信道
信道是带有类型的管道,你可以通过它用信道操作符 <- 来发送或者接收值。看起来非常有用。信道的发送和接收操作在另一端准备好之前都会阻塞,相当于发送信道方在其他协程从信道读取数据之前会被阻塞,而接收信道方在其他协程发送之前会被阻塞。可用于在其他协程结束之前,阻塞Go主协程。
1 | ch := make(chan int) // 定义一个信道,其中的值类型为int |
文件操作
1 | b, err := ioutil.ReadFile("test.json") // 直接读取文件内容 |
包管理
引用包里面的变量,必须是已经导出的,只有大写开头的才是导出的,例如math.Pi
1 | // 定义当前包名 |
标准库
网络请求
1 | import "net/http" |
时间处理
1 | import time |
扩展库推荐
基本上可以理解为gopkg.in
才是Go官方推荐的库网站,地址与github中的地址其实是相对应的,不过这个好处是可以在后面加一个版本号做到版本控制
TroubleShooting
should have comment or be unexported,这只是VSCode的语法Warning,它希望暴露的结构体等有一个明确的注释,这时候只需要在需要注释的结构体上面加上这样的注释即可:
1
2// test is ...
type test struct {}
扩展阅读
官方FAQ: 我见过写得最详细的编程语言官方FAQ
Why you can have millions of Goroutines but only thousands of Java Threads