Go语言相对于C++的优点

幸运草
幸运草
幸运草
896
文章
3
评论
2020年4月20日21:31:01 评论 88

Go语言是Google公司在2009年开源的一门高级编程语言,它为解决大型系统开发过程中的实际问题而设计,支持并发、规范统一、简单优雅,被很多Go语言传道者誉为“互联网时代的C语言”。而C++语言诞生于1979年,可以将C++语言视为一个语言联邦,主要包含C语言(面向过程)、面向对象、STL容器和算法、范型编程(模板)4部分,它高效强大同时又臃肿复杂,目前最流行的是C++11标准,它的很多优化为C++注入了新的活力。

谷歌出品,必属精品。Go语言流行至今,大有颠覆C++和Java在大型系统开发中的霸主地位的趋势,这篇文章简要分析Go语言相对于C++的优点,内容主要来自个人感悟,如有不对的地方还请朋友们批评指正。

1、语法规范。Go语言实现了语法规范的高度统一,例如Go语言规定大写字母开头是公开类型,而小写字母开头是私有类型,真正做到了语言规范的最高境界之“望文知义”。而在C++开发代码里没有这样的规定,因此看到一个类的成员变量名称,还需要跳转到类的定义才能确定它的访问级别。Go语言强制规定了语法规范(不符合规范的代码无法编译通过),在工程中非常实用。

2、接口设计。Go语言的核心是组合而不是继承,Go语言支持面向对象,但是不支持继承。因此在用Go语言设计程序时不需要考虑基类的设计,它的接口设计更为灵活,只需要专注每个类应该实现的功能。而C++语言支持继承,很多面试官都喜欢问为什么基类的析构函数一定要是virtual的?public继承和private继承的区别是什么?在Go语言里,这些都统统不复存在。

3、开发工具。Go语言作为Google的亲儿子,它提供了编译、测试、调试、性能分析等一系列标准工具,它的编译效率极高,原生支持单元测试,支持调试和代码检查、性能分析等等,是一个名副其实的工程化开发语言;在C++中需要借助各种各样的开源工具来组合达到这个目标,其中用于C++程序性能分析的工具gperftools就是Google开源的。

4、支持并发。Go语言被设计为支持并发,可以通过go关键字创建N个goroutine(一种用户态线程)来实现并发,同时提供多个goroutine的同步机制,例如当N个goroutine都执行完毕才继续执行。而C++需要借助第三方框架来实现并发功能,例如线程池+异步调用(一般由第三方RPC框架提供)。Go语言提供语言层面的并发支持,可以轻松的开发出并发框架。

5、内存管理。Go语言和Java、python、lua一样,都不需要程序员管理内存。而有经验的C++程序员看到别人代码里的new就害怕,因为不知道有没有相应的delete,还有就是在哪里delete的,会不会执行不到等等,总之是为内存管理这样无趣又痛苦的事情耗费精力,虽然有auto_ptr、shared_ptr这样的资源管理神器,但是语言本身是没有禁止原生的new/delete的,担心内存泄漏是一件很不爽的事情。

6、defer语句。Go语言提供defer语句来保证释放资源,例如在某个函数中打开一个文件后,通过defer filer.Close()来保证关闭文件操作一定会在函数结束时执行,而在C++中想做到这一点需要一些技巧,例如运用goto跳转,或者封装一个文件资源管理器。这点可以看出Go语言设计的多么贴心。

7、语法简洁。Go的关键字更少,同时砍掉了很多不必要的功能,例如构造函数、析构函数(Go语言为每个对象赋予初始值,负责自动内存回收)。Go语言不需要每一行代码都以分号结尾,python和lua也是这样。

8、函数支持多返回值。Go语言的函数支持返回多个值,例如返回计算结果数据和错误值,python和lua也都都支持这一特点,而在C++只支持单返回值,需要增加函数参数来达到同样的目的,所以有时候C++函数有很多参数的原因,是因为有的参数被设计为出参。

9、内置标准库。Go语言提供了http、json、xml、正则表达式等很多后端系统开发中常用的库,而C++需要使用很多第三方的库,其缺点是在技术选型上花费一些时间和精力,或者花费更多精力自己造轮子。

10、运行效率。Go语言作为一个编译型语言,它的运行效率是很高的,远远高出解释型的语言,不过当然没有高质量的C++代码程序运行效率高。问题是写出高质量C++代码需要付出相当大的努力,这对于很多有经验的C++程序员来说都是一件十分困难的事。

总结:Go语言是一门工程化、现代化的开发语言,吸取了C、C++、Java、python、lua等众多语言的优点和长处,它为程序开发者考虑了很多,同时做了很多贴心的设计,目前非常成功和流行;C++语言语言的优势仍然在于它的运行效率,但是在开发体验和开发效率上已经落后其他语言,C++11、C++14、C++17等标准的推进也是为了让C++语言能够变的更好,适应新的开发潮流,但是它毕竟背负着沉重的历史包袱,想要脱胎换骨是一件很伟大也很困难的事情。

特别声明:以上文章内容仅代表作者本人观点,不代表变化吧观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。

转载请注明:{{title}}-变化吧
  • 赞助本站
  • 微信扫一扫
  • weinxin
  • 赞助本站
  • 支付宝扫一扫
  • weinxin
幸运草
Go语言中的常量 函数代码

Go语言中的常量

1 概述 常量,一经定义不可更改的量。功能角度看,当出现不需要被更改的数据时,应该使用常量进行存储,例如圆周率。从语法的角度看,使用常量可以保证数据,在整个运行期间内,不会被更改。例如当前处理器的架构类型,可以保证不被更改。 语法如下 2 定义单个常量 const 常量名 <可选的类型> = 常量值 const c1 int = 1000 Go语言中,标识符(常量名)是否大小写,取决于是否需要在导出时被识别。 常量的值仅仅支持,基础类型,字符串,字符,整型,浮点,布尔。 3 类型推导 类型可以通过值推导出来,大多数情况可以省略类型,例如 const c2 = 1000 除非你想使用例如,int8, byte,float32这些非默认类型时,需要指定类型,例如 const c3 int16 = 1000 4 定义多个常量 可以一行定义多个常量,例如: const c4, c5 = 42, 1000 也可以使用 const()定义块,定义多个,每个常量单独一行,例如 const (  c6 = 42  c7 = 1000 ) 推荐使用const()块语法,一次性定义多个。 const()块定义时,如果常量未给出定义,则延续上面的定义规则,例如: const (  c7 = 42  c8 // c8 = 42  c9 // c9 = 42 ) 此时,c8, c9, 值都是42。 5 iota迭代定义常量 const配合iota关键字使用,可以定义一组由0开始+1迭代的常量 演示语法: const (  gender_secret = iota  gender_male // = iota  gender_female // = iota ) 此时,三个常量值,分别是,0, 1, 2 iota的规则是:若iota出现在const()中,那么const()定义的第一行的iota就是0,第二行就是0+1=1,不论iota是否被常量使用。演示如下: const (  c1 = 42...
Go语言的接口 函数代码

Go语言的接口

Go语言-接口 在Go语言中,一个接口类型总是代表着某一种类型(即所有实现它的类型)的行为。一个接口类型的声明通常会包含关键字type、类型名称、关键字interface以及由花括号包裹的若干方法声明。示例如下: type Animal interface { Grow() Move(string) string } 实现接口 如果一个数据类型所拥有的方法集合中包含了某一个接口类型中的所有方法声明的实现,那么就可以说这个数据类型实现了那个接口类型。 你可能已经意识到,我们无需在一个数据类型中声明它实现了哪个接口。只要满足了“方法集合为其超集”的条件,就建立了“实现”关系。这是典型的无侵入式的接口实现方法。 package main import ( "fmt" ) // 定义一个接口 type People interface { ReturnName() string } // 定义一个结构体 type Student struct { Name string } // 定义结构体的一个方法。 // 这个方法同接口People的所有方法,此时可直接认为结构体Student实现了接口People func (s Student) ReturnName() string { return s.Name } func main() { cbs := Student{Name:"咖啡色的羊驼"} var a People a = cbs name := a.ReturnName() fmt.Println(name) // 输出"咖啡色的羊驼" } 如何测试是否已实现该接口 h, ok := a.(People) 这种方式称为类型断言表达式。 a.(People)的求值结果可以有两个: 第一个结果是被转换后的那个目标类型(这里是Student)的值. 而第二个结果则是转换操作成功与否的标志。 空接口 interface{} 空接口就是不包含任何方法的接口。正因为如此,所有的数据类型都实现了空接口。就像Java中的Object类一样。 因此空接口可以存储任意类型的数据。 特别声明:以上文章内容仅代表作者本人观点,不代表变化吧观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。
Go语言支持的正则语法 函数代码

Go语言支持的正则语法

1 字符 语法 说明 . 任意字符,在单行模式(s标志)下,也可以匹配换行 字符类 否定字符类 d Perl 字符类 D 否定 Perl 字符类 ASCII 字符类 否定 ASCII 字符类 pN Unicode 字符类 (one-letter name) p{Greek} Unicode 字符类 PN 否定 Unicode 字符类 (one-letter name) P{Greek} 否定 Unicode 字符类 参考以下附录,获取具体字符类的内容: Perl 字符类 ASCII 字符类 Unicode 字符类 (one-letter name) Unicode 字符类 go.hellokang.net 可以获取相关内容 2 组合 语法 说明 xy xy(x 后跟随 y) x|y x 或 y (优先匹配 x) 3 重复次数 语法 说明 x* 零个或多个 x,贪婪 x+ 一个或多个 x,贪婪 x? 零个或一个 x,贪婪 x{n,m} n 到 m 个 x,贪婪 x{n,} n 个或多个 x,贪婪 x{n} n 个 x x*? 零个或多个 x,非贪婪 x+? 一个或多个 x,非贪婪 x?? 零个或一个...
Go语言的包管理 函数代码

Go语言的包管理

1 概述 Go 语言的源码复用建立在包(package)基础之上。包通过 package, import, GOPATH 操作完成。 2 main包 Go 语言的入口 main() 函数所在的包(package)叫 main,main 包想要引用别的代码,需要import导入! 3 包定义,package Go 语言的包与文件夹一一对应,同一个目录下的所有.go文件的第一行添加 包定义,以标记该文件归属的包,演示语法: package 包名 包需要满足: 一个目录下的同级文件归属一个包。 包名可以与其目录不同名。 包名为 main 的包为应用程序的入口包,其他包不能使用。 包可以嵌套定义,对应的就是嵌套目录,但包名应该与所在的目录一致,例如: // 文件:foo/bar/tool.go中 package bar // 可以被导出的函数 func FuncPublic() { } // 不可以被导出的函数 func funcPrivate() { } 包中,通过标识符首字母是否大写,来确定是否可以被导出。首字母大写才可以被导出,视为 public 公共的资源。 4 导入包,import 要引用其他包,可以使用 import 关键字,可以单个导入或者批量导入,语法演示: // 单个导入 import "package" // 批量导入 import (  "package1"  "package2"  ) 导入时,可以为包定义别名,语法演示: import (  p1 "package1"  p2 "package2"  ) // 使用时 p1.Method() 以上测试请使用系统包测试。若需要导入自定义包,需要设置GOPATH环境变量。 4 GOPATH环境变量 import导入时,会从GO的安装目录(也就是GOROOT环境变量设置的目录)和GOPATH环境变量设置的目录中,检索 src/package 来导入包。如果不存在,则导入失败。 GOROOT,就是GO内置的包所在的位置。 GOPATH,就是我们自己定义的包的位置。 通常我们在开发Go项目时,调试或者编译构建时,需要设置GOPATH指向我们的项目目录,目录中的src目录中的包就可以被导入了: 例如,我么的项目目录为: D:projectsgoProject,那么我么就需要将我们的源代码放在 D:projectsgoProjectsrc 下,同时设置GOPATH为 D:projectsgoProject。设置GOPATH的方案有: windows 通过 系统->系统信息->高级系统设置->环境变量 中完成设置。 windows 中通过 CMD 或者 powershell 也可以完成设置。通常是临时有效的,CMD或者powershell关闭失效!...