来源:芒果教你学编程
概述
Go语言是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言,它用批判吸收的眼光,融合C语言、Java等众家之长,将简洁、高效演绎得淋漓尽致。
Go语言起源于2007年,当时Google的技术大神们备受C++越来越臃肿的困扰,决心开发一种新的语言来取代C++。他们认为:与其在臃肿的语言上不断增加新的特性,不如简化编程语言。于是,Golang这门新语言应运而生。
在十年多的时间里,Go语言发展势头强劲,凭借其简洁、高效的特性,在竞争激烈的编程语言市场中占据了一席之地。Google、腾讯、阿里等大公司纷纷选择使用Go语言来开发服务应用项目。当然,和其他的编程语言一样,Go语言也有其自身的缺陷。
特点及优势
Go语言的设计者们一直致力于降低构建简单、可靠、高效软件的门槛。相比于其他语言,Go语言具有众多令人兴奋不已的特点和优势:
1.自动垃圾回收降低了开发难度
内存和资源管理一直是一个让人非常抓狂的难题。在其他语言(如C或C++)中,使用内存前要先分配这段内存,使用完毕后再将其释放掉,一个小疏忽就可能引发内存泄漏,导致程序甚至系统崩溃。而Go语言的现代化垃圾回收机制显著地降低了开发难度,把无趣的内存管理交给专业的编译器去做,而让程序员专注于更有趣的事情。
2.更丰富的内置类型
Go语言是一种典型的实战派语言,它内置了一个其他静态语言通常用库方式来支持的字典类型(map),理由很简单:既然绝大多数开发者都需要用到这个类型,为什么还非要每个人都写一行import语句来包含一个库?
Go语言还新增了一个数据类型:数组切片(Slice)。我们可以将数组切片看作是一种可动态增长的数组,其功能与C++标准库中的vector类似,但有效地消除了反复写以下几行代码的工作量:
#include#include#include
using namespace std;
使用Go语言,开发者不用再费事添加依赖的包,既减少了输入工作量,又可以让代码更简洁。
3.支持函数多返回值
目前的主流语言中除Python外基本都不支持函数的多返回值功能,但很多情况下开发者非常需要这个功能。比如,我们要定义一个函数,用于返回个人的名字信息,而名字信息包含多个部分——姓氏、名字、中间字,在不支持多返回值的语言中有两种做法来实现名字信息的返回:
专门定义一个结构体:
struct name
{
char first_name[20];
char middle_name[20];
char last_name[20];
};
extern name get_name();//函数原型
name n = get_name();//函数调用
或以传出参数的方式返回:
extern void get_name(
char* first_name,
char* middle_name,
char* last_name);//函数原型
//先分配内存
char first_name[20];
char middle_name[20];
char last_name[20];
//函数调用
get_name(first_name,middle_name,last_name);
Go语言的多返回值功能让开发者既不用再只为了返回多个值而专门定义一个数据结构,也不用再区分参数列表中哪几个用于输入,哪几个用于输出。
使用Go语言返回名字信息可以这样写:
func getName(firstName,middleName,lastName string){
return "May","M","Chen"
}
fn,mn,ln,nn := getName()//函数调用
4.漂亮的错误处理
漂亮的错误处理规范是Go语言大的亮点之一。Go语言引入了defer关键字用于标准的错误处理流程,并提供了内置函数panic、recover完成异常的抛出与捕获。与C++和Java等语言中的异常捕获机制相比,Go语言的错误处理机制可以大量减少代码量,开发者无需再仅为了程序安全而添加大量一层套一层的try-catch语句。
5.匿名函数和闭包
在Go语言中,所有的函数也是值类型,可以作为参数传递。Go语言支持常规的匿名函数和闭包,比如下列代码就定义了一个名为f的匿名函数,开发者可以随意对该匿名函数变量进行传递和调用:
f := func(x,y,int) int{
return x+y
}
6.简洁的类型和“非侵入式”接口
Go语言的类型定义非常接近C语言中的结构(struct),甚至直接沿用了struct关键字。为了保持简洁,Go语言没有直接沿袭C++和Java的传统去设计一个超级复杂的类型系统,不支持继承和重载,而只是支持基本的类型组合功能。虽然看起来过于简洁,但Go语言依然能够实现C++和Java使用复杂的类型系统才能实现的功能。
而引入强大的“非侵入式”接口让开发者从以往对C++和Java开发中的接口管理问题中解脱了出来。
7.并发编程更轻盈更安全
Go语言引入了goroutine概念。goroutine是一种比线程更加轻盈、更省资源的协程。通过使用goroutine而不是裸用操作系统的并发机制,以及使用消息传递来共享内存而不是使用共享内存来通信,并发编程变得更加轻盈和安全。
主要应用场景
Golang非常适合用来做网络并发方面的服务,比如消息推送、监控、容器等。国内外的很多公司都使用了Go语言来开发服务及应用,比如:
Google核心的搜索和广告业务;
腾讯的Docker容器化
百度的运维BFE(Baidu Front End)项目,应对庞大的前端页面访问量。
小米的运维监控系统,小米商城、小米视频等团队也在使用Go语言
不足之处
尽管Go语言独特的垃圾回收机制和并发编程机制等设计使代码更简洁,并大大提高了程序的性能,但与Python、Java、C/C++等语言相比,Go语言还是太年轻。
1.软件包版本管理不完善
Go语言的软件包版本管理一直被开发人员吐槽。Go语言没有制定特定版本的依赖库,在不同时间构建时,创建的生成可能会基于不同版本的包。在这方面,Go语言还无法与Python、Java等语言的软件包管理系统相媲美。
2.错误信息难获得
Go语言的错误处理被人所诟病的一点是,开发者不能从函数上知道下层函数可能返回哪些类型的错误,很容易丢失错误发生的范围,难以提供有效的错误信息。
作为一门新兴的语言,Go语言难免存在种种缺陷。但出身名门的它拥有强大的后备力量,开源社区的用户不断地贡献新的轮子,Google也组建了一个独立的小组全职开发Go语言,在Google内部,Go语言有逐渐取代Java和Python主流地位的趋势。未来Go语言的身影应该会出现在越来越多的应用服务当中。
对大多数公司来说Golang的主要优势是和C++比有GC,和Java比更简洁,和Python比更快,这就在一个不错的位置上了,没有明显的短板。以大部分程序员的水平而言,Golang的缺点还还没有到能对他们产生困扰的程度,他们自己给自己造成的麻烦比语言给他们带来的麻烦多得多。
有的公司和程序员是被旧的语言逼疯了,C++老是内存泄漏或者crash,Java老是变成一大坨,Python老是重构火葬场,就觉得,我换个新语言,这些问题肯定都能解决了。而且往往换完发现的确有很大改善。
但我不得不泼一盆冷水:没用的,真的没用。
垃圾代码的产生永远是因为垃圾程序员,而不是垃圾语言。语言可以很垃圾,但归根结底,垃圾语言只是阻碍你写出好代码,而自由奔放地写出垃圾代码的锅必须全部扣在程序员的头上。
真的把Golang用好的程序员不多,大部分人写什么语言都是差不多的,并不会深入思考Golang的语言模型与其他语言有什么区别,goroutine、channel怎么用才更合理这些问题,以前用线程池,就搞个goroutine池;以前用队列,就去找个队列库。还有的干脆全局变量满天飞,goroutine结果全收集到全局变量里,加个大锁。这样的代码会有效率吗?会好维护吗?会简洁吗?
的确,在你刚刚换到这门语言的时候,你会发现之前你之前代码的那些问题全都没有了,感觉前途一片光明。遗憾的是,这是因为你仅仅才开始写了几个模块,还没有进入维护期。如果你保持着之前的水准,那些往日的恶习会让你的代码再次劣化,让往日的问题再度暴露出来。然后你会想,原来Golang也有这么多的毛病啊,也许我应该重新换成Java?然后再重复一遍这个历史。
不深入去钻研软件工程的规律和技术,不深入去学习一门语言的独有特色,理解语言的设计哲学,建立语言的一套使用方法论,仅仅妄想通过换一门新语言就解决问题,这是一条死路。许多忙着转Golang的程序员给我的感觉都是太浮躁,这样的状态很容易生产出新一批通往火葬场的垃圾代码,只要走着瞧罢了。反过来,如果借这个机会去深入学习如何写出的Golang代码,不失为职业生涯的一个重大转机,很快我们也能知道这么做了的人有哪些的。