go 能解决的问题, java 也能,甚至解决得更好?

//不一定。java太吃服务器资源,go解决了太吃资源的问题。


对于开发量在 100人月上下的项目, 同样的业务管理, go 实现要比 java , 在部署/运维上, 成本要降很多.


如果是 100人月以上的项目, 开发人员在30人以上.基本还是选择容易招人的开发语言( 与开发语言对应的成熟 架框/库). java 挺好招人.

go 就不要选择了( 深圳宝安某几个公司, 招 go 开发人员, 招聘信息处处发, 都发了快一年了, 还在四处挂着招人)

//现在容易招人了


go不止学习成本低这么简单,并发成本更低


一切皆异步



将静态语言的安全性和高效性与动态语言的易开发性进行有机结合


Go 语言中仍有指针的存在,但并不允许进行指针运算。


Go 语言的另一个目标是对于网络通信、并发和并行编程的极佳支持,从而更好地利用大量的分布式和多核的计算机。


构建速度(编译和链接到机器代码的速度)很快


Go 语言还能够在运行时进行反射相关的操作。


Go 语言还支持调用由 C 语言编写的海量库文件。


Go 语言支持交叉编译


** goroutine和线程


协程和线程的区别:

协程:用户态"线程",不是真正的线程。一个线程里可以创建多个协程。

线程创建需要操作系统api,协程不需要,协程在编程语言层面即可完成操作。

//可以理解为有线程的方便,但是比线程轻便易用

//goroutine是协程的一种形式


go关键字创建协程


创建和销毁的代价更小:由于线程创建时需要向操作系统申请资源,并且在销毁时将资源归还,因此它的创建和销毁的开销比较大。相比之下,goroutine的创建和销毁是由go语言在运行时自己管理的,因此开销更低。


内存消耗更少:Goroutine所需要的内存通常只有2kb,而线程则需要1Mb(500倍)。


调度独立于线程


切换开销更小:

goroutine的调度是协同式的,它不会直接地与操作系统内核打交道。

在协同式调度中,没有时间片的概念。

Golang调度器中有三个概念:

Processor(P)OSThread(M)Goroutines(G)


Golang的调度器可以利用多processor资源

Go scheduler将可运行的goroutines分配到多个运行在一个或多个processor上的OS threads上。


操作系统的一个线程下可以并发执行上千个goroutine,每个goroutine所占用的资源和切换开销都很小,因此,goroutine是golang适合高并发场景的重要原因。


** context

有协程,就需要context管理和协调多个协程。

不能直接杀死协程


通过context可以关闭

功能有点像java,c++的threadLocal

为什么不设计threadLocal一样的东东?

//go为了比java,c++更好的并发性,要在协程粒度上去并发,就不能用threadLocal了。

//于是设计了context上下文。只是这个context在各函数的参数里传来传去,有点丑陋。。。



在 Go 的 server 里,通常每来一个请求都会启动若干个 goroutine 同时工作:有些去数据库拿数据,有些调用下游接口获取相关数据等等。

Go 语言中的 server 实际上是一个“协程模型”,也就是说一个协程处理一个请求。

context 用来解决 goroutine 之间退出通知、元数据传递的功能。


TODO和background的区别

background 是一个空的 context, 它不能被取消,没有值,也没有超时时间。

用作根context


context的使用注意:

>不要将 Context 塞到结构体里。直接将 Context 类型作为函数的第一参数,而且一般都命名为 ctx。

>不要向函数传入一个 nil 的 context,如果你实在不知道传什么,标准库给你准备好了一个 context:todo。

这里不能默认用根context即background context吗?

//语义上,background代表context树的根节点。而todo代表占位或尚不明确的上下文。

>不要把本应该作为函数参数的类型塞到 context 中,context 存储的应该是一些共同的数据。例如:登陆的 session、cookie 等。

>同一个 context 可能会被传递到多个 goroutine,别担心,context 是并发安全的。


*** go的局限性

- 多个业务流程前后共用一个context,某流程失败取消了context,可能导致危险的业务大面积失败。


- golang在发展中, 有的库甚至第三方库可能有比较麻烦的bug,比如官方包database/sql在某竞态条件下事务既没有commit,也没有rollback。


参考:

Go Context的踩坑经历 - 包增辉的文章 - 知乎