Go语言的几个注意点

简介:

撸了一段时间的Go,觉得Go确实是个不错的语言,适合写高并发的程序,又自带各种强大的库。不过我最喜欢的还是C++,哈哈。

这里总结一下几个写Go的注意点。

Go语言的协程中,写死循环的注意点:

现象:

在写Go的多协程程序时,出现过几次无法理解的情况。

  • 有一次,我想写一个能跑满cpu的程序,最容易想到的就是,开几个Go的协程,每个协程里写死循环。没想到,运行的时候发现,协程就只开出了一个。
  • 另一次,我写了个程序,也是开了多个协程。因为如果不阻塞住主函数,主函数一结束,程序就会结束。所以我就在主函数结束前加了个死循环。然后就发现整个协程都被卡住了。

分析:

其实,这个东西是协程的特点。以前没用过协程,加上Go又说可以当线程用。所以想当然的写了死循环。

准确的说,是在Go语言里,写了死循环,并且死循环内并没有什么系统调用,只有简单的计算这类的。你就会发现,Go的协程调度就废掉了。

协程并非像线程那样,是由CPU中断来触发切换的。它不是应用程序能控制的(操作系统内核的某些关键操作会被保护,不被中断)。即使你在线程里写了死循环,只要周期一到,CPU产生终端,死循环会被打断,重新调度。但是,协程就不是这样了,协程的调度其实是在协程调用了某个系统调用时,自动跳到另一个协程执行。也就是这个“中断”是程序主动产生的,而不是被”中断”。

所以,协程中,如果你写了死循环,那你的死循环就会一直跑着,而不会让别的协程运行。主函数中也是一样,而且主函数中执行这个会让整个协程卡住,因为调度的代码没法被执行。

在Go语言中,如果你想写死循环,循环里面没有系统调用,又想让Go的协程能起作用,只需要在死循环里面加一条语句即可。估计系统调用时也是这个语句起的作用。

1 runtime.Gosched()
2 //主动让出时间片

Go的并发设置:

现象:

Go语言最大的优势就在于写高并并发的程序,能很方便的利用goroutine来充分利用系统资源,但估计你用协程写出的第一个高并发程序都没有充分的利用起CPU。最多就跑个100%,这让我几十核的CPU情何以堪啊。

分析:

因为Go默认情况下只用单线程。这就是说,你即使开了几百个goroutine,系统中同一时间在跑的只有一个线程,也就是一个协程。那是因为没有设置并发度。(╯’ – ‘)╯︵ ┻━┻

1 runtime.GOMAXPROCS()    //这个函数设置的是Go语言跑几个线程。
2 runtime.NumCPU()              //这个函数返回当前有的CPU数。

CPU并不知道协程,CPU只认识线程,CPU的核心数就是CPU能同时(同一个时间点)运行的线程的数量。协程则会挂在每个线程上,goroutine也会适当的调整协程,让它均匀的挂在每个线程上。

一般情况,线程的数量建议是CPU核数的2倍。所以我一般会这么设置:

1 runtime.GOMAXPROCS(runtime.NumCPU()*2)

Go语言可导出标识:

可导出就是说可以把import的包里的函数和变量暴露出来,可以被调用和访问。

这个有点类似于C++中,private和public这类访问控制。只是Go的控制是以包来划分,C++这个以类来划分。如果这个包的函数/变量是私有的,那么即使import了包,也无法调用里面的函数或访问里面的变量。

这会在编译的时候爆出错误。

1 //调用未导出的函数
2 xxxxx undefined (cannot refer to unexported field or method xxxxxx)
3  
4 //隐式赋值时的报错,因为那个被赋值的类变量是不被导出的。
5 implicit assignment of unexported field 'xxxxxx' in xxxxx literal

Go语言的导出规范:

  • 公有函数/变量的名字以大写字母开头
  • 私有函数/变量的名字以小写字母开头

声明的变量必须使用:

在Go语言中你必须使用所有被声明的变量。或者是import时导出的包。函数可以声明了但是不用。如果你写了个Go程序,发现编译时一堆报错,很可能里面大部分错误是因为你声明了变量但是没用。

真的是个反人类的设定。没办法,这个只能忍着。

总结:

总的来说,Go确实是个不错的语言。除了有一些反人类的设定。

要是C++的标准库能和Go一样,果断就抛弃Go了 ( ̄▽ ̄)~*。听说Google内部都是用C++的,就是因为有强大的类库。

转载请注明:旅途@KryptosX » Go语言的几个注意点

目录
相关文章
|
1天前
|
程序员 Go PHP
为什么大部分的 PHP 程序员转不了 Go 语言?
【9月更文挑战第8天】大部分 PHP 程序员难以转向 Go 语言,主要因为:一、编程习惯与思维方式差异,如语法风格和编程范式;二、学习成本高,需掌握新知识体系且面临项目压力;三、职业发展考量,现有技能价值及市场需求不确定性。学习新语言虽有挑战,但对拓宽职业道路至关重要。
23 10
|
2天前
|
算法 程序员 Go
PHP 程序员学会了 Go 语言就能唬住面试官吗?
【9月更文挑战第8天】学会Go语言可提升PHP程序员的面试印象,但不足以 solely “唬住” 面试官。学习新语言能展现学习能力、拓宽技术视野,并增加就业机会。然而,实际项目经验、深入理解语言特性和综合能力更为关键。全面展示这些方面才能真正提升面试成功率。
20 10
|
1天前
|
编译器 Go
go语言学习记录(关于一些奇怪的疑问)有别于其他编程语言
本文探讨了Go语言中的常量概念,特别是特殊常量iota的使用方法及其自动递增特性。同时,文中还提到了在声明常量时,后续常量可沿用前一个值的特点,以及在遍历map时可能遇到的非顺序打印问题。
|
6天前
|
安全 大数据 Go
深入探索Go语言并发编程:Goroutines与Channels的实战应用
在当今高性能、高并发的应用需求下,Go语言以其独特的并发模型——Goroutines和Channels,成为了众多开发者眼中的璀璨明星。本文不仅阐述了Goroutines作为轻量级线程的优势,还深入剖析了Channels作为Goroutines间通信的桥梁,如何优雅地解决并发编程中的复杂问题。通过实战案例,我们将展示如何利用这些特性构建高效、可扩展的并发系统,同时探讨并发编程中常见的陷阱与最佳实践,为读者打开Go语言并发编程的广阔视野。
|
3天前
|
存储 Shell Go
Go语言结构体和元组全面解析
Go语言结构体和元组全面解析
|
8天前
|
Go
golang语言之go常用命令
这篇文章列出了常用的Go语言命令,如`go run`、`go install`、`go build`、`go help`、`go get`、`go mod`、`go test`、`go tool`、`go vet`、`go fmt`、`go doc`、`go version`和`go env`,以及它们的基本用法和功能。
20 6
|
8天前
|
存储 Go
Golang语言基于go module方式管理包(package)
这篇文章详细介绍了Golang语言中基于go module方式管理包(package)的方法,包括Go Modules的发展历史、go module的介绍、常用命令和操作步骤,并通过代码示例展示了如何初始化项目、引入第三方包、组织代码结构以及运行测试。
16 3
|
10天前
|
缓存 安全 Java
如何利用Go语言提升微服务架构的性能
在当今的软件开发中,微服务架构逐渐成为主流选择,它通过将应用程序拆分为多个小服务来提升灵活性和可维护性。然而,如何确保这些微服务高效且稳定地运行是一个关键问题。Go语言,以其高效的并发处理能力和简洁的语法,成为解决这一问题的理想工具。本文将探讨如何通过Go语言优化微服务架构的性能,包括高效的并发编程、内存管理技巧以及如何利用Go生态系统中的工具来提升服务的响应速度和资源利用率。
|
10天前
|
Rust Linux Go
Rust/Go语言学习
Rust/Go语言学习
|
11天前
|
Java 数据库连接 数据库
携手前行:在Java世界中深入挖掘Hibernate与JPA的协同效应
【8月更文挑战第31天】Java持久化API(JPA)是一种Java规范,为数据库数据持久化提供对象关系映射(ORM)方法。JPA定义了实体类与数据库表的映射及数据查询和事务控制方式,确保不同实现间的兼容性。Hibernate是JPA规范的一种实现,提供了二级缓存、延迟加载等丰富特性,提升应用性能和可维护性。通过结合JPA和Hibernate,开发者能编写符合规范且具有高度可移植性的代码,并利用Hibernate的额外功能优化数据持久化操作。
27 0