临近春节,总算可以多抽一些时间来学习一下Golang,书是在多看上买的电子书《Go语言编程》,比纸板的实体书便宜多了,趁着多看搞活动的时候买的。电子书的方便不言而喻,我的手机上,Kindle上,iPad上都可以看,而且注解和进度还可以无缝同步。话题转移回来,哥为啥突然痴迷Golang,跟它的语言特性有关,Golang虽然非常年轻,可谓结合了前辈很多种语言的精华之处。总的说来,是一门学学习成本不高,又容易很快上手,让你爱不释手的语言。
从此篇blog开始,尝试着以学习笔记的方式记录一下Golang学习的心得,毕竟,一个好的脑袋不如一支烂笔尖,留作日志,以后还可以随时来温习一下。
大多数程序都是以Hello World开始的,Golang也不例外:
从Hello World开始
1 | package main |
Golang的语言特性
包管理
Golang中采用包的概念,包的名字由package关键字命名,这种概念比较类似于C#中的namespace(命名空间)。你可以根据你的需要,创建不同名字的包,也可以把不同的源代码文件放在一个包中。Golang中的包,包括系统默认提供的包,和用户的包。
与package关键字对应的,就是import命令了。import命令,后面跟上包的名字,表示需要引入的包。import,类似于C#中的using语句。引入包后,就可以调用包所提供的功能了。比如hello world程序中的: fmt.Println
有些包的名字比较长,Golang允许你给包取一个别名,后面引用的时候就通过别名来调用,这样方便多了,让码农们可以少敲很多代码。比如:
1 | import pkg "github.com/xxx/xxx" |
这里的pkg,就是包的别名了。
更加简洁的语法
也许你能从上面的Hello World程序一窥究竟,Golang的语法跟C比较类似,不过感觉又比C语言更加简洁。Golang的每一行语句,不需要用分号结束,程序在编译的时候,会自动为你加上。另外,跟C一样,主程序都是从main函数开始的,不过就连Golang的main函数也变得更加简洁:
- 不需要返回值
- 没有argv结构来获取程序启动时的参数,因为程序的参数是从os.Args来获取的
- Golang的函数声明关键字是func
- 关于函数的花括号,风格跟js的程序一致,而且是强行规定的,也就是说,如果你把函数后的花括号放在了第二行,你会直接得到一个编译错误
自动垃圾回收
一提到自动垃圾回收,总感觉是新时代的一些比较高级的语言才具有的一种特质,因为在C/C++中,还没有这样的功能。一些粗心的程序员,常常在malloc或者new了一块内存后,忘了free/delete内存,导致程序运行时内存泄漏。这也是手动管理内存不太方便的地方。另外,对于在某个函数中分配的内存,使用的地方却在函数之外,怎样在适当的时候释放这些内存,也成为一个常见的问题。
Golang的设计者充分体谅码农们的不容易,提供自动垃圾回收的机制。
此外,跟C相比,Golang中虽然也有指针,不过功能也不如C那样“强大”。如大家所熟知,C/C++中的指针可以直接进行一些运算操作,实际上就是直接改变指针的地址,这样做虽然比较自由,其实也比较危险。当指针地址改变甚至超出预期后,指向内存一块不可知的地方,常常造成内存访问越界,甚至直接导致程序崩溃。C/C++允许指针进行随意的地址运算,也是C/C++中垃圾回收实现起来有难度的地方。
函数支持多返回值
这一点,不得不说是Golang的一个亮点。这个特性让开发者可以从原来用各种比较别扭的方式返回多个值的痛苦中解脱出来,既不用再区分参数列表中哪几个用于输入,哪几个用于输出,也不用再只为了返回多个值而专门定义一个数据结构。
在用C#开发的时候,哥就深有体会,返回多个返回值,要不就都通通用out关键字,要不就自定义一个对象,把多个返回值都包装起来。
新的错误处理语法
跟其他的语言不一样的地方,Golang引入了defer关键字用于标准的错误处理流程,并提供内置函数panic、recover完成异常的抛出与捕获。比起其他语言的try-catch机制,和大量的括号嵌套,语法看起来会更加简洁,易读性更高。
匿名函数和闭包
这一点也是吸取了后来一些语言的特性,你可以将一个函数赋值给某个变量,也可以让某个函数返回一个函数。
关于反射
反射是从Java语言开始,提供的一种获取对象类型信息的一种高级机制,后来的一些高级语言,几乎都支持反射。无一例外,Golang也支持反射。
关于并发编程
Golang提供一套更容易使用的实现机制,goroutine是Golang带来的让人眼前一亮的特性。
Go语言引入了goroutine概念,它使得并发编程变得非常简单。通过使用goroutine而不是裸用操作系统的并发机制,以及使用消息传递来通信而不是使用共享内存来通信,Go语言让并发编程变得更加轻盈和安全。通过在函数调用前使用关键字go,我们即可让该函数以gor-outine方式执行。goroutine是一种比线程更加轻盈、更省资源的协程。Go语言通过系统的线程来多路派遣这些函数的执行,使得每个用go关键字执行的函数可以运行成为一个单位协程。当一个协程阻塞的时候,调度器就会自动把其他协程安排到另外的线程中去执行,从而实现了程序无等待并行化运行。