我如何学习 Go 编程
Go 是一种相对较新的编程语言,没有什么比一门新的编程语言更能让开发者疯狂了,哈哈!和许多新技术发明一样,Go 的诞生也源于一次实验。它的创造者的目标是发明一种既能克服其他语言的弊端,又能保留其优点的语言。Go 于 2012 年 3 月首次发布。自那时起,Go 吸引了来自各个领域和学科的众多开发者。
今年第二季度,我加入了ViVA XD,这是一个机上娱乐平台,致力于通过每一次旅行改变世界。我们选择 Go 来构建整个基础设施。Go 的性能、快速简便的开发流程对我们来说仍然是一个很棒的选择。
在本文中,我将简要介绍 Go 语言,并以此激发进一步阅读的兴趣。
入门
我之前没有使用过 Go,在学习一门新的编程语言之前,我首先查看了Golang 官方网页。我找到了适合我的操作系统的安装说明、教程和很棒的文档。这很可怕(作为我使用的第一种静态类型语言)。有人推荐使用Go 之旅,这是一个交互式 Go 教程(与 Go 捆绑在一起),让我熟悉了 Go 的语法和文字。我在几天内完成了 Go 之旅,并了解了 Go 环境中变量、类型、结构、指针、列表等的工作方式。此时,我并没有真正掌握 Go 的所有内容,我使用其他语言的经验让我在 ViVA XD 的第一个任务中获得了足够的知识。Go 做得非常出色,让我们将源代码编译为适用于任何平台的单个二进制文件。我们的应用程序在 Linux 上运行,因此如果我们的开发人员在 Mac 上工作,她可以轻松地将其编译下来,GOOS=linux go build
并且在几秒钟内就可以准备好 Linux 版本。
深入研究
我熟悉了 Go 语言的语法和其他重要部分,例如 goroutines、并发、错误处理、包、接口、双值赋值等。
没有例外
在 Go 中,函数通常返回一个值和一个错误,但并不仅限于此。函数可以返回多个值。在 Go 中处理错误很简单,我们检查第二个返回值(或者说函数返回错误的位置)。这种结构提供了一种将错误从一个点链接到另一个点的好方法。
type Server struct {}
func main() {
err := s.Run()
}
func (s *Server) Run() (err error) {
http.HandleFunc("/", s.handleHomeRequest)
err = http.ListenAndServe(":4000", nil)
if err != nil {
return err
}
return nil
}
变量和声明
在 Go 中,所有变量都必须定义。我们不能进行如下赋值x = 2
。
package main
import (
"fmt"
)
func main() {
var num int
num = 20
fmt.Printf("The number is %d\n", num)
}
我们声明一个num
类型的变量int
。Go 默认为变量赋值为零。整数赋值为0,布尔值赋值为false
,字符串赋值为""
,等等。这种模式看起来可能比较繁琐,Go 也提供了一个方便的 运算符:=
。
因此,我们可以将上面的声明重写为num := 29
只要变量是新的,
:=
就可以使用。
双值赋值
Go 中的接口用于实现其在其他语言中的设计初衷,即对具有相似行为的代码进行逻辑分组,而不是为了减少代码量。
在 Go 中,每种类型至少实现零个方法,这意味着每种类型都实现了一个特殊的零方法interface{}
。当我们不知道变量是什么类型时,这非常有用。
var someData interface{}
err := json.Unmarshal(raw_bytes, &someData)
if err != nil {
log.Error(err)
}
为了从中获取类型,我们使用类型断言。它是一个简单的语句,如果断言失败,赋值将具有该类型的默认值。另一种方法是使用双值赋值。我们在类型断言语句中赋值第二个值,该值将包含一个布尔值,用于指示断言是否成功。
jsonStruct := someData.(map[string]interface{})
num := jsonStruct["num"].(int)
str, ok := jsonStruct["str"].(string)
if !ok {
log.Error("error converting to string")
}
同样适用于从地图中检索值
data := make(map[string]int)
data["result"] = 20
val, ok := data["result"] // returns false if key isn't found
if !ok {
log.info("Value for key not found!!")
}
Goroutines
大多数现代编程语言,例如 Python、Java 等,都起源于单线程环境。它们中的大多数都支持多线程,但仍然面临并发执行、竞争条件、线程锁定和死锁等问题。这些问题使得使用这些语言创建多线程应用程序变得非常困难。
在 Java 中(根据我的研究,我没有 Java 经验),创建新线程的内存效率很低。每个线程大约消耗 1MB 的内存堆。如果启动数千个线程,它们会给堆带来巨大的压力,并可能因内存不足而导致程序关闭。此外,两个或多个线程之间的通信非常困难。
Go 于 2009 年发布,当时多核处理器已经面世。Go 的构建充分考虑了并发性。Go 使用了goroutines
线程,而不是线程。线程会从堆中消耗近2KB 的内存。因此,Go 可以随时运行数百万个 goroutine。
使用 goroutines 的一些好处
- Goroutines 允许您在共享数据结构时避免使用互斥锁。
- Goroutines 的启动时间比线程更快。
- Goroutines 使用通道,这是一种用于在它们之间进行安全通信的内置方式。
- Goroutine 和 OS 线程之间并不是 1:1 的映射关系。单个 Goroutine 可以在多个线程上运行。Goroutine 会被复用到少量的 OS 线程中。
Rob Pike撰写的有关并发的更多内容
用 Go 写的?易于维护
Go 有意省略了现代 OOP 语言的许多特性。
- 没有类。所有内容都分成包。Go 只有结构体。
- 不支持继承。Go 的代码很容易理解,因为没有需要注意的超类。
- 无例外
- 没有仿制药
- 无注释
- 没有构造函数
越来越好
在查阅了所有官方 Go 资源之后,我一直在寻找更多关于 Go 语言的知识,并发现了一些很棒的 Go 入门资料。例如, Go by example、Go Book、Effective Go等等。
这些资源曾经帮助过我,现在仍然在帮助我,尽管我有时觉得这个话题很令人沮丧,但现在一切都变得有趣了。
结论
Go 与其他面向对象语言截然不同,但它也有自己的优势。Go 由 Google 提供支持,并且被 IBM、Intel、Medium、Adobe 等一些大公司使用(https://github.com/golang/go/wiki/GoUsers)。
在学习 Go 之前我有编程经验,大多数概念对我来说并不新鲜,即使你是一个完全的初学者,Go 仍然很容易上手。
想分享你是如何开始学习 Go 的吗?欢迎在评论区留言分享 🙂
文章来源:https://dev.to/codehakase/how-i-learned-go-programming