打开Go语言之门
前言
开始学习Go语言已经差不多半年了,这是第一次正式写下一篇学习总结。又恰逢新学期开始,就把这篇当作新学期的第一篇周报吧。
本周主要是把半年来稀稀拉拉学到的Go语言基础知识有系统性地看了一遍。我对Go语言的了解更多还是从我的舍友,也正是受到他的影响我才会开始学习Go语言并进行记录。
这一周的学习内容就像本文的标签一样,Go语言基础。因为已经学习了很久,所以基础知识就不再本文中赘述。
学习思考
关于Go语言的学习,笔者已经看了四五本不同的基础书籍了,每本书的开头都是以Go语言的优点来开篇,那2024年的第一篇博客也从这个问题开始吧。
Go语言好在哪?
说到Go语言的好处,想必都能想到什么简洁、高效等等。而真正吸引我开始学习Go语言的,还是我的舍友告诉我Go语言的代码有着严格的格式要求,不同人写的代码排版风格几乎一致,这一下就激起我学习Go语言的兴趣。因为笔者在刚开始学习编程的时候并没有养成良好的代码习惯,导致我的代码在很长一段时间里都只有我自己看得懂,于是迫切找到一个大家代码风格都差不多的语言重新开始学习。随着后来对Go的学习,我也了解到它更多的优点。接下来我们来看一下Go语言到底好在哪?
语法简洁
Go语言相对于其他语言更容易上手,开发效率更高。这意味着Go易于学习、易于使用并且易于其他开发人员阅读。Go 没有大量的功能集,尤其是与 C++ 等语言相比。Go 的语法让人想起 C,这使得长期 C 开发人员学习起来相对容易。
从学术的角度讲Go语言其实非常平庸,不支持许多高级的语言特性;但从工程的角度讲,Go的设计是非常优秀的:规范足够简单灵活,有其他语言基础的程序员都能迅速上手。更重要的是Go自带完善的工具链,大大提高了团队协作的一致性。比如gofmt自动排版Go代码,很大程度上杜绝了不一致的问题。
自带垃圾回收功能
对比其他语言,Go语言的优势显著。比如Java虽然也具备垃圾回收功能,但它是解释型语言,需要安装JVM才能运行;C语言虽然不用解释,可以直接编译运行,但是它不具备垃圾回收功能,需要开发者自己管理内存的申请和释放,容易出问题。而Go语言具有两者的优势。
并发性良好
Go语言就是为了并发而生的,其在设计时的创新就是 goroutines 和通道。
Goroutines 是 Go 面向线程的轻量级方法,而通道是 goroutines 之间通信的优先方式。创建 Goroutines 的成本很低,只需几千个字节的额外内存,正由于此,才使得同时运行数百个甚至数千个 goroutines 成为可能。
Goroutines的轻便主要体现在以下两个方面:
- 上下文切换代价小:Goroutine 上下文切换只涉及到三个寄存器(PC / SP / DX)的值修改;而对比线程的上下文切换则需要涉及模式切换(从用户态切换到内核态)、以及 16 个寄存器、PC、SP…等寄存器的刷新;
- 内存占用少:线程栈空间通常是 2M,Goroutine 栈空间最小 2K;
关于Go语言的调度机制,可以看一下这篇文章——https://www.zhihu.com/question/21409296/answer/1040884859
除了以上的三个优点以外,Go语言还有如强大的生态系统、支持跨平台操作以及拥有强大的标准库等优点。
什么是静态语言
在打开任何一本关于Go语言基础的书籍时,首先映入眼帘的就是Go语言是一个静态语言,那么什么是静态语言,Go语言为什么会设计成静态语言,静态语言和动态语言又有什么区别。这些问题困扰了我很久,接下来将会解释以上问题。
静态语言是一种编程语言,其特征是在编译时进行类型检查和绑定。在编写代码时,变量的类型需要明确指定,而且在编译阶段这些类型信息是固定的,不会在运行时发生变化。其特征如下:
- 类型检查: 在编译阶段进行,变量类型需要在声明时明确,并且编译器会检查变量的使用是否符合类型规定。
- 编译时绑定: 函数调用和变量引用在编译时就已经确定,生成对应的机器代码。
- 性能优化: 静态类型信息允许编译器进行更多的优化,生成更高效的代码。
- 严格的错误检查: 由于类型信息在编译时就已知,因此静态语言通常有较为严格的类型检查,编译器可以在编译阶段捕获许多潜在的错误。
静态语言主要有:Java、C、C++、C#、Swift 和 Go
动态语言是一种编程语言,其特征是在运行时进行类型检查和绑定。在编写代码时,变量的类型通常不需要显式指定,而是在运行时根据上下文动态确定。其特征如下:
- 类型检查: 在运行时进行,变量的类型可以在代码执行期间改变。
- 运行时绑定: 函数调用和变量引用在运行时确定,这允许更大的灵活性和动态性。
- 较少的编译时优化: 缺乏静态类型信息会减少编译器进行某些优化的能力。
- 更灵活: 相对于静态语言,动态语言通常更灵活,适用于快速开发和迭代。
动态语言主要有:Python、JavaScript、Ruby、PHP
静态语言与动态语言的区别:
- 类型检查时机: 静态语言在编译时进行类型检查,而动态语言在运行时进行类型检查。
- 类型灵活性: 静态语言要求在编写代码时明确指定变量的类型,而动态语言允许变量在运行时根据上下文动态确定类型。
- 编译时绑定 vs. 运行时绑定: 静态语言的函数调用和变量引用在编译时绑定,而动态语言在运行时绑定,允许更大的灵活性。
- 性能优化: 静态语言由于在编译阶段有更多的类型信息,通常可以进行更多的编译时优化,因此在一些性能方面具有优势。动态语言通常在运行时进行解释,因此可能在性能上略逊于静态语言。
- 错误检查: 由于在编译时进行类型检查,静态语言通常能够在更早的阶段捕获潜在的错误,而动态语言在运行时才能发现。
Go语言被设计成静态语言的主要原因涉及到一系列的设计目标和哲学,其中一些因素包括:
性能优化: 静态语言通常在编译阶段进行类型检查,这使得编译器可以在生成机器代码时进行更多的优化。Go语言的设计目标之一是提供出色的性能,静态类型信息允许编译器在编译时对代码进行更多的优化,提高程序的执行效率。
并发支持: Go语言的并发模型以及轻量级线程(goroutines)的概念需要在编译时对程序的结构有清晰的了解。静态类型信息使编译器能够更好地理解并发代码,减少在运行时发生竞争条件和死锁的可能性。
简单性和可读性: Go语言的设计注重简单性和可读性,静态类型系统可以帮助开发者更容易理解代码。类型信息作为一种文档形式,使得代码更加自解释,减少了理解代码所需的认知负担。
错误检查: 静态类型检查可以在编译时捕获潜在的类型错误,提高代码的可靠性。这有助于减少在运行时因为类型错误引起的 bug,提高了代码的稳定性。
团队协作: 在大型项目和团队中,静态类型系统可以提供更好的协作支持。类型信息可以帮助开发者了解函数和变量的用法,使得团队成员之间更容易沟通和协作。
编程工具的支持: 静态类型信息为IDE(集成开发环境)和其他编程工具提供了更多的信息,从而提供更强大的代码分析和自动补全功能,提高了开发效率。
总的来说,Go语言之所以选择静态类型,是为了在性能、并发性、可读性和团队协作等方面达到一种平衡,使得开发者能够更容易地编写高性能、可维护和并发安全的代码。
小结
至此,本周的学习总结也就完成了,内容较少,原因是还有一些更复杂的东西想留着专门来写。所以本文就只是写了在学了Go语言的基础语法,即打开了Go语言之门之后,我的疑问和相对应的解答。除了解语法之外,我也在尝试着跟着大佬来完成一些项目,详细的就等完成之后的总结吧。
下周的学习目标是更深层次地学习Go语言的进阶语法并推动项目进程。