Go语法
可见性
- 包变量的可见性
规定首字母大写是包public
首字母小写是包Private
- 结构体变量变量的可见性
结构体中字段大写开头表示可公开访问,小写表示私有(仅在定义当前结构体的包中可访问)。
结构体标签
//Student 学生
type Student struct {
ID int `json:"id"` //通过指定tag实现json序列化该字段时的key
Gender string //json序列化是默认使用字段名作为key
name string //私有不能被json包访问
}
创建结构体切片的指针
- 使用
make
函数创建空的结构体切片,并获取其指针:
slice := make([]*MyStruct, 0)
slicePtr := &slice
上述代码中,make([]*MyStruct, 0)
创建了一个空的 []*MyStruct
类型的结构体切片,然后通过 &
运算符获取其指针。
- 直接声明并初始化一个结构体切片的指针:
slicePtr := []*MyStruct{
{Field1: value1},
{Field1: value2},
// ...
}
Package
基本规则
-
每个源文件都属于一个包,一个包可以对应多个源文件
-
对于相同的包,可以将其相关的源文件放在同一个目录下,这些源文件共同组成了包的结构。
例如,一个名为
example
的包结构如下:/example main.go helper.go
其中,
main.go
和helper.go
都属于example
包,并且可以在其中定义该包的函数、类型、变量等(同一个包内共用) 。需要注意的是,多个源文件之间不需要显式导入相同的包,因为它们属于同一个包。
-
子包:一个包可以包含子包,用于更好地组织和管理代码文件。在目录中创建一个子目录,并在子目录下创建新的源文件即可形成子包。
例如,一个名为
example
的包中包含了一个名为util
的子包,结构如下:/example main.go /util helper.go
其中,
helper.go
文件属于example/util
子包,可以在文件中声明package util
。
除了上述基本的包结构,还有一些需要注意的事项:
- 每个包都应该有一个独一无二、具有描述性的名称,以避免冲突。
- 可执行程序的入口包应该用
main
作为包名。 - 包名应该小写,并使用简短而具有描述性的名称。
- 在同一个目录下,只能存在一个包(不包括子包)。
channel
关闭后的通道有以下特点:
- 对一个关闭的通道再发送值就会导致 panic。
- 对一个关闭的通道进行接收会一直获取值直到通道为空。
- 对一个关闭的并且没有值的通道执行接收操作会得到对应类型的零值。
- 关闭一个已经关闭的通道会导致 panic。
那我们如何判断一个通道是否被关闭了呢?
对一个通道执行接收操作时支持使用如下多返回值模式。
value, ok := <- ch
其中:
- value:从通道中取出的值,如果通道被关闭则返回对应类型的零值。
- ok:通道ch关闭时返回 false,否则返回 true。
select关键字
在 Go 语言中,select
是一个关键字,用于处理通道操作的选择。select
语句允许从多个通道接收数据或发送数据,并通过对应的 case
来执行相应的操作。
select
语句的一般语法如下:
goCopy Codeselect {
case <-channel1:
// 执行 channel1 的接收操作
case data := <-channel2:
// 执行 channel2 的接收操作,并将接收到的数据赋值给 data 变量
case channel3 <- data:
// 执行 channel3 的发送操作,将 data 发送到 channel3
default:
// 如果没有任何一个 case 准备好,则执行 default 分支
}
select
语句中可以包含多个 case
子句,每个 case
表示一个通道操作。其中,接收操作使用 <-
运算符,发送操作使用 <-
运算符。每个 case
后面都跟随着一个冒号 :
。default
分支是可选的,当没有任何一个 case 准备好时,将执行 default 分支中的代码。
select
语句的工作原理是非阻塞的,它会检查每个 case 中的通道是否准备好(即通道是否有数据可以接收或空间可以发送数据),如果有多个 case 准备好,它会随机选择一个 case 执行。如果没有任何 case 准备好并且存在 default 分支,则会执行 default 分支。
一些常见的 select
语句用法包括:
- 接收数据:使用
<-
接收通道中的数据。如果多个通道都有数据可接收,则随机选择一个 case 执行。 - 发送数据:使用
<-
将数据发送到通道中。如果多个通道都可以发送数据,则随机选择一个 case 执行。 - 非阻塞操作:在
select
语句中使用default
分支,以便在没有任何一个 case 准备好时立即执行某个默认操作。 - 超时控制:通过在
select
语句中结合time.After
或time.Tick
等定时器相关函数,实现超时控制和定时器功能。
需要注意的是,在 select
语句中,只有当有 case 可用时才会执行相应的操作,而一旦某个 case 被选中执行,其他 case 将被忽略,即使其它 case 准备好了。这种特性使得 select
适用于处理并发操作和多个通道的情况。
上下文Context
上下文(Context)是 Go 语言中非常有特色的一个特性, 在 Go 1.7 版本中正式引入新标准库 context。
其主要的作用是在 goroutine 中进行上下文的传递,而在传递信息中又包含了 goroutine 的运行控制、上下文信息传递等功能。
本质上 Go 语言是基于 context 来实现和搭建了各类 goroutine 控制的,并且与 select-case联合,就可以实现进行上下文的截止时间、信号控制、信息传递等跨 goroutine 的操作,是 Go 语言协程的重中之重。