〇、声明
教程名称:《Go语言-零基础入门教程》
教程出处:1024课堂
教程地址:1024casts.com/courses/go-…本文性质为个人学习笔记,是笔者学习教程的笔记和心得,如有疑问,敬请指正。 本文为全书笔记,分为多个章节,对于比较长篇幅的小节笔记拆分为独立的小节笔记,并通过连接方式添加到本文。
笔者熟悉 C# 和 JavaScript,在学习 Go 的过程中会时长与 C# 和 JavaScript 作比较,如果有对相关语言理解错误的地方请多指正,共同成长。学习顺序和原视频教程略有不同,同时也夹杂着视频以外的知识点。如果读者觉得不够循序渐进可以直接学习原视频。
人穷志不短,虽然买不起 Mac OS X,但用 Windows 也很好学,下载 Go>>
一、基本介绍
1.1 Go 语言简史
语言入门第一章一般都是要先介绍语言的创始者,我们换换场子……先。
1.1.1 语言诞生年份
| 序号 | 语言 | 年份 |
|---|---|---|
| 1 | C | 1970 |
| 2 | C++ | 1979-1983 |
| 3 | R | 1980 |
| 4 | Python | 1990 |
| 5 | Visual Basic | 1991 |
| 6 | JavaScript | 1995 |
| 7 | PHP | 1995 |
| 8 | Java | 1995 |
| 9 | C# | 2000 |
| 10 | Go | 2009 |
1.1.2 Go 的诞生
每个语言诞生都有属于他的故事和目的,了解故事的背景有助于体悟语言本身存在的意义。那么什么是数据 Go 的故事呢?
要说起 Go 语言,不得不说他有个好爹,大将之子,名门之后,绝对一身好血统,说起他爹大家一定都很熟悉,那就是 Google(当然,他也有个很有名的儿子 Docker)。调查结果显示,2019 年,程序员最想学习的编程语言 Top 3 分别是 Go、Kotlin 和 Python,其中 Go 以 37.2% 的比例排在首位。
Go 语言自己应该是不知道他有多可爱,但作为他生身之父的 Google 自然懂得。
- 计算机硬件技术更新频繁,性能提高很快。目前主流的编程语言发展明显落后于硬件,不能合理利用多核多CPU的优势提升软件系统性能。
- 软件系统复杂度越来越高,维护成本越来越高,目前缺乏一个足够简洁高效的编程语言。
现有的编程语言:- 风格不统一
- 计算能力不够
- 处理大并发不够好
- 企业运行维护很多 C/C++ 的项目,C/C++ 程序运行速度虽然很快,但是编译速度却很慢,同时还存在内存泄漏的一系列的困扰需要解决
其实我也不知道,抄来的,转载信息见本章最后一节。
同时,关于 Go 语言特性方面将在下一章介绍(其实我还没学废)
O(∩_∩)O哈哈~
1.1.3 Go 语言用途
Go 语言保证了既能达到静态编译语言的安全和性能,又达到了动态语言开发维护的高效率,使用一个表达式来形容 Go 语言:Go = C + Python,说明 Go 语言既有 C 静态语言程序的运行速度,又能达到 Python 动态语言的开发。
Go 语言的目标是希望提升现有编程语言对程序库等依赖性(dependency)的管理,这些软件元素会被应用程序反复调用。由于存在并行编程模式,因此这一语言也被设计用来解决多处理器的任务。
Go 语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。对于高性能分布式系统领域而言,Go 语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于游戏服务端的开发而言是再好不过了。
1.1.4 本章参考
1.2 语言特性
Go 语言具有众多语言特性,下面就其中几个优秀且具有代表性的特性简单谈谈。
1.2.1 垃圾回收机制
说起垃圾回收功能,不得不把 C/C++ 拿出来和 C#、Java、Python 比较。
垃圾回收可能会带来严重的空间和时间开销,实现和移植垃圾回收会使得语言本身设计更复杂。还有,垃圾回收将使语言不适合做许多底层的工作,而这却正是 C/C++ 的一个设计目标。虽然 C/C++ 没有垃圾回收机制,但是 C++ 的设计者 Bjarne Stroustrup 说过,他喜欢垃圾回收的思想,“它是一种机制,能够简化设计、排除掉许多产生错误的根源。需要垃圾回收的基本理由是很容易理解的:用户的使用方便以及比用户提供的存储管理模式更可靠。”(参见The Design and Evolution of C++(豆瓣))
我们再说说 C# 的垃圾回收机制,说 C# 得先说说 .NET Framework(框架)、LI(中间语言)、CLR(公共语言运行时),CLR 是 .NET Framework 的一部分,C#、VB 等使用 .NET Framework 提供的编译器编译成 LI 语言在 CLR 上运行。CLR 和 Java 虚拟机相类似,.NET Framework 把资源分为托管资源和非托管资源,由 CLR 管理的存在于托管堆上的称为托管资源,非托管资源是不由 CLR 管理的,是否托管资源类型是固定的(这里不作介绍)。于是,托管资源就由 CG(垃圾回收器)在 CLR 觉得合适的时候进行回收,非托管资源不会自动回收,需要开发者自定义代码进行资源回收处理。
Java 的垃圾回收机制是完全自动的,java 堆内存的时候调用垃圾回收机制,也可以通过代码调用 GC 方法提示虚拟机进行垃圾回收,但也不会马上进行垃圾回收。但是 Java 也有内存资源和非内存资源的概念,非内存资源不受垃圾回收机制管控,需要通过代码人工处理,比如文件的 Close()。
Python 的垃圾回收机制也是完全自定的,当然也可以通过代码人工触发垃圾回收,和 Java 的最大区别应该是,Python 所谓万物皆对象,没有所谓非内存需要人工关闭回收的说法。Python 垃圾回收机制
曾几何时,内存管理是程序员开发应用的一大难题。传统的系统级编程语言(主要指C/C++)中,程序员必须对内存小心的进行管理操作,控制内存的申请及释放。稍有不慎,就可能产生内存泄露问题,这种问题不易发现并且难以定位,一直成为困扰开发者的噩梦。言归正传,Go 语言作为现代语言,GC 必不可少,Go 的 GC 模式和 Python 非常相近,而在 Go 的发展历程中,GC 功能一度成为 Go 的吐槽对象(好好吧,我也是听来的,不多说)
笔者了解还不够,也就不深入介绍了,如果上述描述有误还请留言指正,谢谢!
1.2.2 内置数据类型
首先,说说强类型和弱类型。Go 语言是强静态类型,下面简单列出编程语言类型划分:
- 动态典型: Python, Ruby, PHP, JavaScript, VBScript
- 静态典型: C/C++, C#, Java, Go
- 强定义典型: C/C++, C#, Java, Go
- 弱定义典型: PHP, Asp, Ruby, Python, ABAP, Javascript, Unix shell
其实对于静态类型的语言中,也并非不会出现动态类型,比如 C# 在 .NET 4.0 以后就有了 dynamic 类型,dynamic 类型可以是任何类型,运行时确认具体类型,类似于 JavaScript 中始终用 var 定义变量,var 可以在运行中实时更改成新的类型。
很多教程和博文中都把内置数据类型作为 Go 的一大语言特性,但是并没有明确原有。笔者为什么要有次疑问呢?因为现如今熟知的语言大多包含全面的数据类型,在没有明确说明 Go 的内置数据类型有什么特别之处的情况下,这一点被提及就缺少点价值了。
其次,Go 语言具有更多的内置数据类型,仅整形就有这些划分:uint8、uint16、uint32、uint64、uint、int8、int16、int32、int64、int。(其实如 C# 也是有很多种类型),类型的种类更多,可供随意挑选(但是设计者绝对没有考虑过重度选择恐惧症程序员们的心情)。但是类型多并不代表你可以随性所欲,比如在实际项目中,类型的设定往往和数据库相关(仅使用数据库或数据库连接类相匹配的类型),也往往需要考虑业务对接时候第三方的类型设定,总之,更多的选择并不代表你用友了更多的自由。【Go】那么多数值类型,应该选哪个?
1.2.3 函数多返回值
多返回值的设计确实很有意思,不少语言的设计都只有单返回值,比如 C#,但是随着语言及开发需求的发展,C#也添加了支持多返回的方式(通过参数作返回),而且还支持 in, out 双向模式的 ref(引用),下面是 C# 的方法:
/// <summary>
/// 多返回测试
/// </summary>
/// <param name="context1"></param>
/// <param name="context2"></param>
/// <returns></returns>
public string FuncTowReturn(out string context1, out string context2)
{
context1 = "扩展返回1";
context2 = "扩展返回2";
return "默认返回";
}
/// <summary>
/// 传引用
/// </summary>
/// <param name="context1"></param>
/// <param name="context2"></param>
/// <returns></returns>
public string FuncRef(ref string context1, ref string context2)
{
context1 = "修改扩展返回1";
context2 = "修改扩展返回2";
return "新的默认返回";
}
/// <summary>
/// 测试
/// </summary>
public void Demo()
{
string str1, str2;
var str0 = FuncTowReturn(out str1, out str2);
Console.WriteLine($"方法 FuncTowReturn 有多个返回,分别是{str0},{str1},{str2}");
str0 = FuncRef(ref str1, ref str2);
Console.WriteLine($"方法 FuncRef 单返回,单额外通过引用修改参数值,返回分别是{str0},{str1},{str2}");
}
而 Go 语言本身就设计了多返回,而不是通过参数方式实现,下面给出一个简单的例子(摘抄自《Go 语言圣经》多返回值),不需要深究,看看结构就好!
func main() {
for _, url := range os.Args[1:] {
links, err := findLinks(url)
if err != nil {
fmt.Fprintf(os.Stderr, "findlinks2: %v\n", err)
continue
}
for _, link := range links {
fmt.Println(link)
}
}
}
// findLinks performs an HTTP GET request for url, parses the
// response as HTML, and extracts and returns the links.
func findLinks(url string) ([]string, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
return nil, fmt.Errorf("getting %s: %s", url, resp.Status)
}
doc, err := html.Parse(resp.Body)
resp.Body.Close()
if err != nil {
return nil, fmt.Errorf("parsing %s as HTML: %v", url, err)
}
return visit(nil, doc), nil
}
1.2.4 错误处理
1.2.5 匿名函数和闭包
1.2.6 类型和接口
- struct关键字
- 不支持集成和重载
- 支持类型组合
- 接口
1.2.7 并发编程
- goroutine(go 关键字)
- channel
- 使用“消息传递”来共享内存,非使用“共享内存”来通信
1.2.8 反射
1.2.9 语言交互性
- Go和C有着天然的联系
- Cgo 工具
2021-03-25 13:00 本小节对应视频知识点比较概括,笔记暂写到这,准备查阅额外资料进行补偿描述
1.3. Go 程序 Hello World
来一段我们经典代码吧:
package main
import "fmt"
func main() {
/* 这是我的第一个简单的程序 */
fmt.Println("你好, 🌈彩虹兄弟!")
}
运行结果如下:
PS D:\Temp\Golang> go run GoFirst
你好, 🌈彩虹兄弟!
PS D:\Temp\Golang>