(文章持续更新中...有志同道合的人可以一起探讨下。整个系列(1~8)准备重写,不过都是很基础的入门笔记,想学到很深入的东西则不建议阅读...)
接口是双方约定的一种合作协议。每个接口类型由数个方法组成
type 接口类型名 interface{
方法名1( 参数列表1 ) 返回值列表1
方法名2( 参数列表2 ) 返回值列表2
…
}
type Writer interface {
Write(p []byte) (n int, err error)
}
复制代码
- 接口的方法与实现接口的类型方法格式一致.实现接口类型中的方法的名称、参数列表、返回参数列表中的任意一项与接口要实现的方法不一致,那么接口的这个方法就不会被实现。
- 接口中所有方法均被实现.当一个接口中有多个方法时,只有这些方法都被实现了,接口才能被正确编译并使用
Go 语言的源码复用建立在包(package)基础之上.Go 语言的入口 main() 函数所在的包(package)叫 main,main 包想要引用别的代码,必须同样以包的方式进行引用,Go 语言的包与文件夹一一对应,所有与包相关的操作,必须依赖于工作目录(GOPATH)
GOPATH 绝对路径提供项目的工作目录
goroutine 的概念类似于线程,但 goroutine 由 Go 程序运行时的调度和管理。Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU
Go 程序中使用 go 关键字为一个函数创建一个 goroutine。一个函数可以被创建多个 goroutine,一个 goroutine 必定对应一个函数
// 为普通函数创建goroutine 的格式
go 函数名( 参数列表 )
复制代码
如果需要在 goroutine 中返回数, 用通道(channel)把数据从 goroutine 中作为返回值传出
package main
import (
"fmt"
"time"
)
func running() {
var times int
for {
times++
fmt.Println("tick", times)
time.Sleep(time.Second)
}
}
func main() {
// 并发执行程序
go running()
// 接受命令行输入, 不做任何事情
var input string
fmt.Scanln(&input)
}
复制代码
一般情况下,可以使用 runtime.NumCPU() 查询 CPU 数量,并使用 runtime.GOMAXPROCS() 函数进行设置
runtime.GOMAXPROCS(runtime.NumCPU())
复制代码
并发和并行的概念
并发:任务在不同的时间点在处理器进行处理。在同一时间点,任务并不会同时运行 并行:每一个任务分配给每一个处理器独立完成。在同一时间点,任务一定是同时运行
Go语言通道
单纯地将函数并发执行是没有意义的。函数与函数间需要交换数据才能体现并发执行函数的意义
任何时候,同时只能有一个 goroutine 访问通道(channel Go语言中一种特殊类型)进行发送和获取数据。(类似队列,先进先出)
// 申明通道类型
var 通道变量 chan 通道类型(通道内的数据类型)
复制代码
chan 类型的空值是 nil,声明后需要配合 make 后才能使用
通道是引用类型,需要使用 make 进行创建
通道实例 := make(chan 数据类型)
ch1 := make(chan int) // 创建一个整型类型的通道
ch2 := make(chan interface{}) // 创建一个空接口类型的通道, 可以存放任意格式
type Equip struct{ /* 一些字段 */ }
ch2 := make(chan *Equip) // 创建Equip指针类型的通道, 可以存放*Equip
复制代码
通道创建后,就可以使用通道进行发送和接收操作
通道的发送使用特殊的操作符<-
// 数据通过通道发送数据格式
通道变量 <- 值(值的类型必须与ch通道的元素类型一致)
// 创建一个空接口通道
ch := make(chan interface{})
// 将0放入通道中
ch <- 0
// 将hello字符串放入通道中
ch <- "hello"
复制代码
发送将持续阻塞直到数据被接收
把数据往通道中发送时,如果接收方一直都没有接收,那么发送操作将持续阻塞。Go 程序运行时能智能地发现一些永远无法发送成功的语句并做出提示,代码如下:
package main
func main() {
// 创建一个整型通道
ch := make(chan int)
// 尝试将0通过通道发送
ch <- 0
}
复制代码
通道接收同样使用<-操作符
通道的收发操作在不同的两个 goroutine 间进行
接收将持续阻塞直到发送方发送数据
通道一次只能接收一个数据元素
阻塞模式接收数据时,将接收变量作为<-操作符的左值,执行该语句时将会阻塞,直到接收到数据并赋值给 data 变量
// 阻塞式接收值
data := <-ch
// 非阻塞式
data, ok := <-ch
data 表示接收到的数据
ok 表示是否接收到数据
非阻塞的通道接收方法可能造成高的 CPU 占用,因此使用非常少
// 忽略从通道返回的数据
<-ch
复制代码
Go 的通道可以在声明时约束其操作方向,如只发送或是只接收。这种被约束方向的通道被称做单向通道
只能发送的通道类型为chan<-,只能接收的通道类型为<-chan
var 通道实例(声明的通道变量) chan<- 元素类型 // 只能发送
var 通道实例(声明的通道变量) <-chan 元素类型 // 只能接收
复制代码
使用 close() 来关闭一个通道.给被关闭通道发送数据将会触发panic
close(ch)
复制代码
互斥锁是一种常用的控制共享资源访问的方法,它能够保证同时只有一个 goroutine 可以访问共享资源
Lock()
UnLock()