这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
首先,很荣幸能够参加本次青训营,相信这一定是一段美好且收获丰富的旅程啦!
王克纯老师在课程中主要讲解了
- Go语言的优势
- Go语言的基础语法
本文就学习了王克纯老师的第一堂课,记录下个人的探索和思考。
一、内容概述
本文就不对课程内容进行总结,而是在学习王克纯老师教授内容后,根据网络上的资料、自己的理解(欢迎大家交流、纠正)介绍了: Go高效并发的关键
二、知识点介绍
1. 基本概念
首先,介绍一下几个基础概念,网络中太多这种八股式的介绍,我就不写过多内容,我就用我觉得最通俗易懂的解释来介绍概念(例子c++):
① 进程/线程:./main 将一个main这样的可执行程序运行起来就是一个进程;main.cpp中可以通过pthread调用另起线程。一个进程中的多个线程之间可以并发执行。
② 并发/并行:多线程在单核cpu上运行,主要通过时间片实现并发;多线程程序在多核cpu上运行就是并行。
③ 协程:协程是用户态的线程,跟内核线程是多对一的关系。
④ 管道:Unix中管道实际上就是一个传输数据的内核缓冲区/文件,其是大小受限的无格式字节流。
2. 高效关键(个人理解)
2.1 goroutine
goroutine其实就是更小的线程,多个goroutine实际上在底层就对应一个线程,它是实现Go语言并发设计的核心。
使用go关键字就可以创建goroutine,调用的函数执行时会被作为一个独立的并发线程。
go DoSomething();
go func(){
}(val1, val2)
go {
}
goroutine使得cpu并行运行,那么还有一点疑惑?怎么拿到并行的结果呢? 答案是 通过channel
2.2 channel
channel是Go语言中提供的goroutine间的通信方式,可以在多个goroutine之间传递消息。
go语言提倡使用通信的方式代替共享内存(区别于Unix中共享内存的方式,进程间采用虚拟内存映射到相同的物理内存中,然后就可以实现通信)
channel是进程内类型相关的通信方式,实际上就是安全的管道,因此定义一个channel需要指明类型,同时通过channel传递对象的过程和调用函数时的参数必须一致。
channel_int := make(chan int)
channel_string := make(chan string)
channel_interface := make(chan interface{})
eg1:
channel_int <- 10
num := <- channel_int
}
数据接收的方式有四种:阻塞接收、非阻塞接收、忽略接收、循环接收 ① 阻塞接收
data := <- ch
② 非阻塞接收
data, ok := <- ch
③ 接收任意数据,并忽略: 执行该语句会阻塞,直到接收到数据。因此可以通过这个方式实现并发
func main() {
ch := make(chan int)
//开启goroutine匿名函数
go func() {
fmt.Println("start goroutine")
ch <- 0
fmt.Println("end goroutine")
}
fmt.Println("wait goroutine")
<- ch //等待匿名的goroutine
fmt.Println("all done")
④ 循环接收
for data := range ch {
}
三、个人总结
在学习了王克纯老师的第一堂课后,掌握了go基本语法,并且对于goroutine、channel做了更加深入、细致的学习。
Go语言保证了既能到达静态编译语言的安全和性能,又达到了动态语言开发速度和易维护性。让人联想到C、Python,Go语言结合了C静态语言程序的运行速度 和 Python动态语言的快速开发。
因此,个人觉得:Go语言的高效高并发十分适合于网络IO密集型的场景,诸如服务器开发、网络编程、数据库和云平台领域。