最近三年,在工作中使用go开发了不少服务。深感go的便捷,以及它的runtime的复杂。我觉得需要定期的进行总结,因此决定写这篇文章,也许更准确的,应该叫笔记。
创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:成都网站设计、成都网站制作、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的鄄城网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
最近终于解决了一个和cgo有关的问题。这个问题从发现到解决前后经历了接近4个月,当然,和人手不足也有关系。而对于我个人而言,这个问题其实历时2年!这得从头说起。
在上一家公司的一个项目里,有一个服务做音视频数据的提取,这个服务运行在嵌入式设备TX2上。音视频提取这一关键功能主要利用nvidia基于gstreamer开发的插件,这个插件可以发挥nvidia gpu的硬件解码功能。当时这个服务使用go和c混编的方式,问题的症状是服务运行一段时间后,不输出音视频数据。遗憾的是,由于疫情,项目停止,因此没有机会继续研究这个问题。
时间来到去年底。当前这个项目进行压力测试,发现关键的语音处理服务运行一段时间后,会出现不拉流的情况,因此也没有后续的结果输出。症状和上一个项目非常像。虽然使用的第三方SDK不一样,但同样用了go和c混编的方式。一开始,焦点就放在go的运行时上,觉得可能是go和c相互调用的方式不对。经过合理猜测,并用测试进行验证后,发现问题还是在第三方拉流的SDK上,它们的回调函数必须要快,否则有可能会阻塞它们的回调线程。当然,在go调用c的时候,如果耗时比较长,会对go的运行时造成一些副作用;在c回调go的时候,go的运行时也有可能阻塞c的回调线程。但go的运行时已经比较成熟,因此我觉得它对这个问题的贡献不大。以上采用了假设-验证的方法,主要的原因还是第三方的拉流SDK不开源。在定位问题的过程中,使用了gdb的gcore来生成堆栈;也搭建了灰度环境来进行压力测试,以及完善监控,这些都是解决方法的一部分。
正是这一问题,促使我更多的了解go的运行时。而我看得越多,越觉得go的运行时是一个庞大的怪物。因此,抱着能了解一点是一点的心态,不断的完善这篇笔记。
作为一个测试,作为一个测试开发, 全栈化+管理 是我们未来的发展方向。已经掌握了Java、Python、HTML的你,是不是也想了解下最近异常火爆的Go语言呢?来吧,让我们一起了解下。
Go 是一个开源的编程语言 ,它能让构造简单、可靠且高效的软件变得容易。
Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。这三个人都是计算机界的大神,有的参与了C语言的编写,有的还是数学大神,有的还获得了计算机最高荣誉-图灵奖。
接下来说说 Go语言的特色 :
简洁、快速、安全
并行、有趣、开源
内存管理、数组安全、编译迅速
Go语言的用途 :
Go 语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。
对于高性能分布式系统领域而言,Go 语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于 游戏 服务端的开发而言是再好不过了。
Go语言的环境安装:
建议直接打开 官方地址因为墙的原因打不开
因为我用的是windows系统,这里主要讲下Windows系统上使用Go语言来编程。
Windows 下可以使用 .msi 后缀(在下载列表中可以找到该文件,如go1.17.2.windows-amd64.msi)的安装包来安装。
默认情况下 .msi 文件会安装在 c:Go 目录下。你可以将 c:Gobin 目录添加到 Path 环境变量中。添加后你需要重启命令窗口才能生效。个人建议还是安装到 Program Files文件夹中。
使用什么开发工具来对Go语言进行编写:
个人建议用VS code, 也可以用Sublime Text来编辑。如果你之前看了我讲的HTML语言的学习,肯定已经下载了VS code. 那么这时你需要在VS code中下载Go语言的扩展插件。
这里有一个巨大的坑,就是在下载Go的插件和依赖包时,会提示一些包没有。主要是因为下载的依赖包部分被墙了,只能想别的办法去下载。
建议参考网页:
解决vscode中golang插件安装失败方法
在学习go的过程中,使用的是vscode,但是一直提示安装相关插件失败,然后上网查方法,基本上是叫你建立golang.org目录什么的,结果全是错的,而且都是抄袭,很烦。无意之中看到一位博主分享的方法,他也是饱受上述的垃圾博文困扰,然后找到了解决方法,这里向他致敬,秉着让更多人看到正确解决方法的心,我写下正确的解决方法,希望对你有所帮助,也可以点开原博主链接参考:
Go有一个全球模块代理,设置代理再去安装golang的插件,就可以安装成功了。步骤有,首先Windows用户打开Powershell,一个蓝色的界面,注意不是cmd!不知道的直接打开window下面的搜索,然后输入powershell,搜索出来就可以了。
$env:GO111MODULE=“on”
$env:GOPROXY=“”
go env -w GOPROXY=
go env -w GOPRIVATE=*.corp.example.com
然后我们打开VsCode界面,下面会提示安装插件,我们选择Install ALL,就会安装成功
当你在运行Go语言程序时,提示所有的插件包都已经安装成功了时,就可以正常使用了,要不然一堆报错会让你非常心烦。
好了,今天先到这里,晚安、下班~
创建 PayPal 的目的是使金融服务民主化,并使个人和企业能够加入并在全球经济中蓬勃发展。这项工作的核心是 PayPal 的支付平台,该平台使用专有技术和第三方技术的组合来高效、安全地促进全球数百万商家和消费者之间的交易。随着支付平台变得越来越大、越来越复杂,PayPal 寻求对其系统进行现代化改造并缩短新应用程序的上市时间。
Go 在生成干净、高效的代码方面的有着极高的价值。这些代码可以随着软件部署的扩展而轻松扩展,这使得该语言非常适合支持 PayPal 的目标。
支付处理平台的核心是 PayPal 用 C++ 开发的专有 NoSQL 数据库。然而,代码的复杂性大大降低了开发人员发展平台的能力。Go 的简单代码布局、goroutine(轻量级执行线程)和通道(用作连接并发 goroutine 的管道)使 Go 成为 NoSQL 开发团队简化和现代化平台的自然选择。
作为概念验证,一个开发团队花了六个月的时间学习 Go 并在 Go 中从头开始重新实现 NoSQL 系统,在此期间,他们还提供了有关如何在 PayPal 更广泛地实施 Go 的见解。截至今天,已迁移 30% 的集群以使用新的 NoSQL 数据库。
随着 PayPal 的平台变得越来越复杂,Go 提供了一种轻松简化大规模创建和运行软件的复杂性的方法。该语言为 PayPal 提供了出色的库和快速工具,以及并发、垃圾收集和类型安全。
借助 Go,PayPal 使其开发人员能够将更多时间从 C++ 和 Java 开发的噪音中解放出来,从而能够花更多时间查看代码和进行战略性思考。
在这个新改写的 NoSQL 系统取得成功后,PayPal 内更多的平台和内容团队开始采用 Go。Natarajan 目前的团队负责 PayPal 的构建、测试和发布管道——所有这些都是在 Go 中构建的。该公司拥有一个大型构建和测试农场,它使用 Go 基础设施进行完全管理,以支持整个公司的开发人员的构建即服务(和测试即服务)。
凭借 PayPal 所需的分布式计算能力,Go 是刷新系统的正确语言。PayPal 需要并发和并行的编程,为高性能和高度可移植性而编译,并为开发人员带来模块化、可组合的开源架构的好处——Go 已经提供了所有这些以及更多帮助 PayPal 对其系统进行现代化改造。
安全性和可支持性是 PayPal 的关键问题,该公司的运营管道越来越多地由 Go 主导,因为该语言的简洁性和模块化帮助他们实现了这些目标。PayPal 对 Go 的部署为开发人员提供了一个创意平台,使他们能够为 PayPal 的全球市场大规模生产简单、高效和可靠的软件。
随着 PayPal 继续使用 Go 对其软件定义网络 (SDN) 基础设施进行现代化改造,除了更易于维护的代码外,他们还看到了性能优势。例如,Go 现在为路由器、负载平衡和越来越多的生产系统提供动力。
作为一家全球性企业,PayPal 需要其开发团队有效管理两种规模:生产规模,尤其是与许多其他服务器(如云服务)交互的并发系统;和开发规模,尤其是由许多程序员协同开发的大型代码库(如开源开发)
PayPal 利用 Go 来解决这些规模问题。该公司的开发人员受益于 Go 将解释型动态类型语言的编程易用性与静态类型编译语言的效率和安全性相结合的能力。随着 PayPal 对其系统进行现代化改造,对网络和多核计算的支持至关重要。Go 不仅提供了这种支持,而且提供的速度很快——在单台计算机上编译一个大型可执行文件最多需要几秒钟。
PayPal 目前有 100 多名 Go 开发人员,未来选择采用 Go 的开发人员将更容易获得该语言的批准,这要归功于公司已经在生产中的许多成功实现。
最重要的是,PayPal 开发人员使用 Go 提高了他们的生产力。Go 的并发机制使得编写充分利用 PayPal 的多核和联网机器的程序变得很容易。使用 Go 的开发人员还受益于它可以快速编译为机器代码的事实,并且他们的应用程序获得了垃圾收集的便利和运行时反射的强大功能。
今天 PayPal 的第一类语言是 Java 和 Node,Go 主要用作基础设施语言。虽然 Go 可能永远不会在某些应用程序中取代 Node.js,但 Natarajan 正在推动让 Go 成为 PayPal 的第一类语言。
通过他的努力,PayPal 还在评估迁移到 Google Kubernetes Engine (GKE) 以加快其新产品的上市时间。GKE 是一个用于部署容器化应用程序的托管、生产就绪环境,并带来了 Google 在开发人员生产力、自动化操作和开源灵活性方面的最新创新。
对于 PayPal 而言,部署到 GKE 将使 PayPal 更容易部署、更新和管理其应用程序和服务,从而实现快速开发和迭代。此外,PayPal 会发现更容易运行机器学习、通用 GPU、高性能计算和其他受益于 GKE 支持的专用硬件加速器的工作负载。
对 PayPal 来说最重要的是,Go 开发和 GKE 的结合使公司能够轻松扩展以满足需求,因为 Kubernetes 自动扩展将使 PayPal 能够处理用户对服务不断增长的需求——在最重要的时候保持它们可用,然后在安静的时间来省钱。
相比很多其它流行语言,Go的语法相对简洁。 此篇文章将介绍编程中常用的代码元素,并展示一份简单的Go程序代码,以便让刚开始学Go编程的程序员对Go代码结构有一个大概的印象。
编程和程序代码元素
简单来讲,编程可以看作是以各种方式控制和组合计算机运行中的各种操作,以达到各种各样的目的。 一个操作可能从一个硬件设备读取、或者向一个硬件设备写入一些数据,从而完成一个特定的任务。 对于现代计算机来说,最基本的操作是底层计算机指令,比如CPU和GPU指令。 常见的硬件设备包括内存、磁盘、网卡、显卡,显示器、键盘和鼠标等。
直接操控底层计算机指令进行编程是非常繁琐和容易出错的。 高级编程语言通过对底层指令进行一些封装和对数据进行一些抽象,从而使得编程变得直观和易于理解。
在流行高级编程语言中,一个操作通常是通过函数(function)调用或者使用操作符(operator)运算来完成的。 大多数高级编程语言都支持一些条件和循环控制语句。 这些条件和循环控制语句可以看作是特殊的操作。 它们的语法接近于人类语言,因此一个人写的代码很容易被其他人理解。
在大多数高级编程语言中,数据通常被抽象为各种类型(type)和值(value)。 一个类型可以看作是值的模板。一个值可以看作是某个类型的实例。 大多数编程语言支持自定义类型和若干预声明类型(即内置类型)。 一门语言的类型系统可以说是这门语言的灵魂。
编程中常常会使用大量的值。 一些在编码阶段可确定的值可以用它们的字面形式(literal,即字面量)来表示。 为了编程灵活和不易出错,其它的值一般使用变量(variable)和(具名)常量(named constant)来表示。
在《Go语言101》中,具名的函数、具名的值(包括变量和具名常量)、以及定义类型和类型别名将被统称为代码要素。 代码要素名必须为标识符(identifier)。
高级编程语言代码将被编译器或者解释器转换为底层机器码进行执行。 为了帮助编译器和解释器解析高级语言代码,一些单词将被用做关键字(keyword)。 这些单词不能被当做标识符使用。
很多现代高级语言使用包(package)来组织代码。 一个包必须引入(import)另一个包才能使用另一个包中的公有(导出的)代码要素。 包名和包的引入名也都必须是标识符。
尽管高级编程语言代码比底层机器指令友好和易懂,我们还是需要一些注释来帮助自己和其他程序员理解我们所写的代码。 在下一节的程序示例中,我们可以看到很多注释。
一个简单的Go示例程序
为了对各种代码元素有一个更清楚的认识,让我们来看一个简短的Go示例程序。 和很多其流行语言一样,Go使用//来起始一个行注释,使用一个/*和*/对来包裹一个块注释。
下面是这个Go示例程序。请注意阅读其中的注释。程序之后有更多解释。
package main // 指定当前源文件所在的包名
import "math/rand" // 引入一个标准库包
const MaxRand = 16 // 声明一个具名整型常量
// 一个函数声明
/*
StatRandomNumbers生成一些不大于MaxRand的非负
随机整数,并统计和返回小于和大于MaxRand/2的随机数
个数。输入参数numRands指定了要生成的随机数的总数。
*/
func StatRandomNumbers(numRands int) (int, int) {
// 声明了两个变量(类型都为int,初始值都为0)
var a, b int
// 一个for循环代码块
for i := 0; i numRands; i++ {
// 一个if-else条件控制代码块
if rand.Intn(MaxRand) MaxRand/2 {
a = a + 1
} else {
b++ // 等价于:b = b + 1
}
}
return a, b // 此函数返回两个结果
}
// main函数,或主函数,是一个程序的入口函数。
func main() {
var num = 100
// 调用上面声明的StatRandomNumbers函数,
// 并将结果赋给使用短声明语句声明的两个变量。
x, y := StatRandomNumbers(num)
// 调用两个内置函数(print和println)。
print("Result: ", x, " + ", y, " = ", num, "? ")
println(x+y == num)
}
将上面的程序代码存盘到一个名为basic-code-element-demo.go 的文件中并使用下列命令运行此程序:
$ go run basic-code-element-demo.go
Result: 46 + 54 = 100? true
在上面的示例程序中,单词package、import、const、func、var、for、if、else和return均为关键字。 其它大多数单词均为标识符。 请阅读关键字和标识符以获得更多关于关键字和标识符的信息。
四个int(一个在第15行,另三个在第13行) 表示内置基本类型int。int类型是Go中的基本整数类型之一。 第5行中的16、第17行中的0、 第20行中的1以及第30行的100均为整型字面量。 第35行的"Result: "是一个字符串字面量。 请阅读基本类型和它们的字面量表示以获取更多关于基本类型和它们的字面量的信息。 Go中的非基本类型(均为组合类型)将在以后的其它文章中介绍和解释。
第20行是一个赋值语句。 第5行声明了一个具名常量,叫做MaxRand。 第15行和第30行使用标准变量声明语句声明了三个变量。 第17行的变量i以及第33行的变量x和y是使用变量短声明语句声明的。 变量a和b在声明的时候被指定为int类型。 编译器会自动推导出变量i、num、x和y的类型均为int类型,因为它们的初始值都是整型字面量表示的。 请阅读常量和变量以获取什么是类型不确定值、类型推导、赋值、以及如何声明变量和具名常量。
上面的示例程序中使用了很多操作符,比如第17和19行的小于比较符,第36行的等于比较符==,还有第20和36行的加法运算符+。 第35行中的+不是一个运算符,它是一个字符串字面量中的一个字符。 一个使用操作符的操作中涉及到的值称为操作值(有时也可称为运算数)。 请阅读常用操作符以获取更多关于操作符的信息。 更多操作符将在后续其它文章中介绍。
第35和36行调用了两个内置函数print和println。 从第13行到第26行声明的函数StatRandomNumbers在第33行被调用。 第19行也调用了一个函数 Intn。 这个函数声明在math/rand标准库包中。 请阅读函数声明及函数调用以获取更多关于函数声明及函数调用的信息。
(注意,一般print和println这两个内置函数并不推荐使用。 在正式的项目中,我们应该尽量使用fmt标准库包中声明的相应函数。 《Go语言101》只在开始的几篇文章中使用了这两个函数。)
第1行指定了当前源文件所处的包的名称。 一个Go程序的主函数(main函数)必须被声明在一个名称为main的包中。 第3行引入了math/rand标准库包,并以rand做为引入名。 在这个包中声明的Intn函数将在第19行被调用。 请阅读代码包和包引入,以获取更多关于代码包和包引入的信息。
表达式、语句和简单语句一文中介绍了什么是表达式和语句。特别地,此文列出了所有的简单语句类型。 在Go代码中,各种流程控制代码块中的某些部分必须为简单语句,某些部分必须为表达式。
StatRandomNumbers函数的声明体中使用了两个流程控制代码块。 其中一个是for循环代码块,它内嵌了另外一个代码块。 另外一个代码块是一个if-else条件控制代码块。 请阅读基本流程控制语法以获取更多关于流程控制代码块的信息。 更多的特殊的流程控制代码块将在以后的其它文章中介绍。
空行常常用来增加代码的可读性。 上面的程序中也包涵了很多注释,但它们大多是为了Go初学者快速理解的目的而加入的。 我们应该尽量使代码自解释,只在确实需要解释的地方进行注释。
关于代码断行
像很多其它流行编程语言一样,Go也使用一对大括号{ and }来形成一个显式代码块。但是在Go代码中,编码样式风格有一些限制。 比如,很多左大括号{不能被放到下一行。 如果,上面的StatRandomNumbers被修改成如下所示,则上面的示例程序将编译不通过。
func StatRandomNumbers(numRands int) (int, int)
{ // 编译错误:语法错误
var a, b int
for i := 0; i numRands; i++
{ // 编译错误:语法错误
if rand.Intn(MaxRand) MaxRand/2
{ // 编译错误:语法错误
a = a + 1
} else {
b++
}
}
return a, b
}
一些程序员不是很喜欢这些限制。但是这些限制有两个好处:
它们使得Go程序编译得非常快。
它们使得不同的Go程序员编写的代码风格类似,从而一个Go程序员写的代码很容易被另一个程序员看懂。
我们可以阅读代码断行规则一文以获取更多关于代码换行规则的细节。在目前,我们最好避免将左大括号放在下一行。 或者说,每行的非空起始字符不能是左大括号(但是,请记住,这不是一个普适的规则
1、学习曲线
它包含了类C语法、GC内置和工程工具。这一点非常重要,因为Go语言容易学习,所以一个普通的大学生花一个星期就能写出来可以上手的、高性能的应用。在国内大家都追求快,这也是为什么国内Go流行的原因之一。
2、效率
Go拥有接近C的运行效率和接近PHP的开发效率,这就很有利的支撑了上面大家追求快速的需求。
3、出身名门、血统纯正
之所以说Go语言出身名门,是因为我们知道Go语言出自Google公司,这个公司在业界的知名度和实力自然不用多说。Google公司聚集了一批牛人,在各种编程语言称雄争霸的局面下推出新的编程语言,自然有它的战略考虑。而且从Go语言的发展态势来看,Google对它这个新的宠儿还是很看重的,Go自然有一个良好的发展前途。我们看看Go语言的主要创造者,血统纯正这点就可见端倪了。
4、组合的思想、无侵入式的接口
Go语言可以说是开发效率和运行效率二者的完美融合,天生的并发编程支持。Go语言支持当前所有的编程范式,包括过程式编程、面向对象编程以及函数式编程。
5、强大的标准库
这包括互联网应用、系统编程和网络编程。Go里面的标准库基本上已经是非常稳定,特别是我这里提到的三个,网络层、系统层的库非常实用。
6、部署方便
我相信这一点是很多人选择Go的最大理由,因为部署太方便,所以现在也有很多人用Go开发运维程序。
7、简单的并发
它包含降低心智的并发和简易的数据同步,我觉得这是Go最大的特色。之所以写正确的并发、容错和可扩展的程序如此之难,是因为我们用了错误的工具和错误的抽象,Go可以说这一块做的相当简单。
8、稳定性
Go拥有强大的编译检查、严格的编码规范和完整的软件生命周期工具,具有很强的稳定性,稳定压倒一切。那么为什么Go相比于其他程序会更稳定呢?这是因为Go提供了软件生命周期的各个环节的工具,如go
tool、gofmt、go test。
很多朋友可能知道Go语言的优势在哪,却不知道Go语言适合用于哪些地方。
1、 Go语言作为服务器编程语言,很适合处理日志、数据打包、虚拟机处理、文件系统、分布式系统、数据库代理等;网络编程方面。Go语言广泛应用于Web应用、API应用、下载应用等;除此之外,Go语言还可用于内存数据库和云平台领域,目前国外很多云平台都是采用Go开发。
2、 其实Go语言主要用作服务器端开发。其定位是用来开发"大型软件"的,适合于很多程序员一起开发大型软件,并且开发周期长,支持云计算的网络服务。Go语言能够让程序员快速开发,并且在软件不断的增长过程中,它能让程序员更容易地进行维护和修改。它融合了传统编译型语言的高效性和脚本语言的易用性和富于表达性。
3、 Go语言成功案例。Nsq:Nsq是由Go语言开发的高性能、高可用消息队列系统,性能非常高,每天能处理数十亿条的消息;
4、 Docker:基于lxc的一个虚拟打包工具,能够实现PAAS平台的组建。
5、 Packer:用来生成不同平台的镜像文件,例如VM、vbox、AWS等,作者是vagrant的作者
6、 Skynet:分布式调度框架。
7、 Doozer:分布式同步工具,类似ZooKeeper。
8、 Heka:mazila开源的日志处理系统。
9、 Cbfs:couchbase开源的分布式文件系统。
10、 Tsuru:开源的PAAS平台,和SAE实现的功能一模一样。
11、 Groupcache:memcahe作者写的用于Google下载系统的缓存系统。
12、 God:类似redis的缓存系统,但是支持分布式和扩展性。
13、 Gor:网络流量抓包和重放工具。
以上的就是关于go语言能做什么的内容介绍了。