Go 语言的基础组成有以下几个部分:
- 包声明
- 引入包
- 函数
- 变量
- 语句 & 表达式
- 注释
并发和Goroutine
并发和并行的区别 并发可能更多的是精确到语言的逻辑,也就是直接的多线程,或者多进程。
而并行则是一种表述程序运行的方式,就如同异步和同步的描述。
并发程序不一定是并行的,这个看操作系统的调度。
线程与协程的区别 线程:是比进程更小粒度的运行单位,存在于内核态,需要操作系统来调度,内存消耗是MB级别。
协程:是比线程更小的粒度,通过m:n的比例在一个线程中再细分出来的单位,存在于用户态,用户可以自由调度,内存消耗是KB级别。
协程对比线程的优势:
存在于用户态,可操作性强,调度可由自己控制。 更轻量,所需资源更少。
Goroutine
go语言的go关键字跑的就是协程,我们称为goroutine。
并发的通信
并发程序之间的通信,一般都是通过共享内存的形式实现通信,临界区一般需要加锁保护。 而go语言采取的是通过通信来实现共享内存,这个过程是反过来的,但用起来更为直观。
并发安全
互斥锁
go语言并没有对加锁机制的弃用,标准库里面仍然有sync.Mutex。
以下为简单加锁实现并发安全: `package main
import ( "fmt" "sync" "time" ) var( x int mut sync.Mutex ) func AddWithLock() { mut.Lock() for i:=0;i<2000;i++ { x++ } mut.Unlock() }
func AddWithoutLock() { for i:=0;i<2000;i++ { x++ } }
func main() { //开五个协程的锁版本,再打印最终结果 for i := 0; i < 5; i++ { go AddWithoutLock() } //等待上面的协程执行结束 time.Sleep(time.Second) fmt.Println(x)
//有锁版本
x = 0
for i:=0;i<5;i++{
go AddWithLock()
}
time.Sleep(time.Second)
fmt.Println(x)
}
`依赖管理
Go依赖管理的演进 GOPATH Go Vendor Go Module