当前位置: 首页 > news >正文

Go语言的几个注意点

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

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

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

现象:

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

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

分析:

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

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

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

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

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

1runtime.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倍。所以我一般会这么设置:

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

Go语言可导出标识:

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

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

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

1//调用未导出的函数
2xxxxx 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语言的几个注意点

相关文章:

  • this 绑定题目简析
  • express如何解决request entity too large问题
  • idea 添加yuicompressor压缩js/css
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 全局Threshold和动态阈值分割Dyn_Threshold的应用场景
  • Streaming源码解读 mapWithState-2
  • 你真的知道 == 和 equals 的区别吗?
  • 关于错误提示:此实现不是 Windows 平台 FIPS 验证的加密算法的一部分的解决方案...
  • 【c++进阶:c++ algorithm的常用函数】
  • (转) RFS+AutoItLibrary测试web对话框
  • 刚刚接触python的感想
  • linux下使用hiredis异步API实现sub/pub消息订阅和发布的功能
  • 第70届(2019)IMO中国国家队选拔考试试题
  • xml编码格式在tomcat下运行出错,eclipse里面直接运行没有问题
  • 微服务架构 SpringCloud(二)Eureka(服务注册和服务发现基础篇)
  • JavaScript-如何实现克隆(clone)函数
  • 【Leetcode】104. 二叉树的最大深度
  • canvas 高仿 Apple Watch 表盘
  • CSS 专业技巧
  • input的行数自动增减
  • Java知识点总结(JavaIO-打印流)
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • Laravel 菜鸟晋级之路
  • node.js
  • nodejs实现webservice问题总结
  • Python3爬取英雄联盟英雄皮肤大图
  • session共享问题解决方案
  • Spring框架之我见(三)——IOC、AOP
  • sublime配置文件
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 搞机器学习要哪些技能
  • 关于Flux,Vuex,Redux的思考
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 简单实现一个textarea自适应高度
  • 力扣(LeetCode)357
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 前端工程化(Gulp、Webpack)-webpack
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 试着探索高并发下的系统架构面貌
  • 小程序button引导用户授权
  • 主流的CSS水平和垂直居中技术大全
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​linux启动进程的方式
  • #QT(串口助手-界面)
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • $.ajax()参数及用法
  • (2020)Java后端开发----(面试题和笔试题)
  • (C语言)二分查找 超详细
  • (floyd+补集) poj 3275
  • (pojstep1.1.2)2654(直叙式模拟)
  • (二)JAVA使用POI操作excel
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (三)uboot源码分析
  • (小白学Java)Java简介和基本配置