Go语言学习心得
17年接触 golang,虽然早就听说 golang 并发能力强、跨平台无虚拟机、自动 GC、快速编译等特点,但实际去练习和使用它却没有多长时间。虽然如此,感觉还是学到了点东西。
记得最早对 golang 印象还在上大学, 那时 golang 给我的印象是好像类似 lua,整个程序就只有一个线程,想要并发得靠协程间来回切换,因为当时还不够懂异步 IO,所以感觉这还不如用线程、线程池,而 lua 那种协程没发并行计算,是 1个线程对应 N 个协程,如果一个协程有个死循环整个线程会卡住,其他协程就不能执行了,因此产生了对 golang 的误解。
后来学习 nodejs 了解到了异步 IO,再后来又去看了协程异步 IO 库 state-threads 的机制,最后阅读了 golang 底层实现的相关资料,才解开了之前的误解并清楚的认知到这种并发方式的高效,M 个线程对应 N 个协程加上异步 IO 并依靠调度器,的确能提供很高的并发效率。不过虽然底层是异步 IO,但 golang 通过调度器让用户层还是原来阻塞式的写法,相对于如 libev,libuv 这类的回调函数式风格的异步 IO 框架, 较符合人们的编程习惯,提高了性能又不失开发效率。
接下来介绍下这门语言的一些特点:
1、内建的并发原语
Golang 在语言层面对并发编程提供支持,一种类似协程,称作 goroutine 的东东,只需在函数调用语句前添加 go 关键字,就可创建并发执行单元。开发人员无需了解任何执行细节,调度器会自动将其安排到合适的系统线程上执行。
goroutine 是一种非常轻量级的实现,可在单个进程里执行成千上万的并发任务。另有与之配套的 chan 类型,用以实现 "以通讯来共享内存" 的 CSP 模式,廉价的 goroutine 可以让我们美滋滋地处理异步任务,chan 可以用来交换数据, 这些简化了原本复杂的并发开发方式。
例子:
var channel chan int = make(chan int)
func asyncIO(){
fmt.Println("aab")
channel<-666
}
func mian(){
go asyncIO()
fmt.Println("main")
fmt.Println(<-channel)
}
输出:
main
aab
666
2、没有类和继承
Go语言没有类和继承的概念,取而代之的是 struct、interface 和方法,所以它和 Java 或 C++ 看起来并不相同。但是它通过接口(interface)的概念来实现多态性,interface 的特性是 golang 支持鸭子类型的基础,即“如果它走起来像鸭子,叫起来像鸭子(实现了接口要的方法),它就是一只鸭子(可以被赋值给接口的值)”。凭借接口机制和鸭子类型,golang 提供了一种游离于类、继承、模板之外的另一种可靠的选择。
例子:
type Duck interface {
cry()
walk()
}
type Goose struct {
}
func (g Goose) cry() {
fmt.Println("嘎嘎嘎")
}
func (g Goose) walk() {
fmt.Println("< < < <")
}
type Actors struct {
}
func (a Actors) cry() {
fmt.Println("嘎 嘎 嘎")
}
func (a Actors) walk() {
fmt.Println("< < < <")
}
func main() {
var duck Duck
duck = new(Goose)
duck.cry()
duck.walk()
duck = new(Actors)
duck.cry()
duck.walk()
}
输出:
嘎嘎嘎
< << <
嘎 嘎 嘎
<< < <
3、不用trycatch来处理异常
Java、javascript 这类是通过 try 块来包裹住会抛出异常的代码,catch 块来处理捕获的错误,而 go 语言就不一样了,是通过 panic 函数来抛出,而捕获则需要 defer + recover, 不过这个 defer 不是 block 级别的,而是函数级别的,需要在函数返回前才得到执行。怎么说呢,这种机制不同于以上两种语言,各有各的特点,不过 golang 的就和 nodejs 以前的异步操作的回调函数一样,错误处理比较繁琐,需要对很多 err 进行判断。
例子:
func error1(){
defer func(){
if err:=recover; err!=nil{
fmt.Println(err)
}
}()
panic("aab")
fmt.Println("hihihi")
}
func main(){
error1()
fmt.Println("main")
}
输出:
aab
main
以上就是 golang 感觉比较有特点的地方。总的来说呢,golang 是比较容易上手,学习曲线也比较低,最好是有 c 或 c++ 基础,因为 golang 里面有指针之类的东西,有前两个的基础理解较为方便。还有对于运维来说,Go 编译生成的是一个静态可执行文件,除了 glibc 外没有其他外部依赖。这让部署变得很方便,不需要操心应用所需的各种包、库的依赖关系,减轻了维护的负担。
当然 golang 也有一些不足之处,不过自己只拿来写过的练手 web 服务不便谈论,golang 其他优秀的、好玩的特性,因为篇幅限制,就不一一阐述了,欢迎大家转发、点赞、评论,谢谢。
【海说软件接受各种技术咨询及开发业务】
END