go 语言介绍

背景

一直有在零散的时间用go写点代码,正好借着最近比较有时间写东西的契机,给这个看着年轻,实际也已经发展10几年,并在当下众多开发领域都有不可忽视作用的语言做个介绍吧

golang 的起点

golang 的诞生可以说是时代造就了它,它也成就了研发工具、云原生和高性能服务开发百花齐放的时代

本节主要参考文章:

Go at Google: Language Design in the Service of Software Engineering
翻译-Google 里的 Go 语言:服务于软件工程的语言设计

煎鱼-为什么要开发 Go 这门新语言?

开发痛点

  • 当时谷歌使用的语言:C++、Java 和 Python ,已经不适用于计算层面的需求,对于多核处理、大规模计算 和 web应用编程层面,遇到的问题都只能绕过,而不是直接解决

ced by multicore processors, networked systems, massive computation clusters, and the web programming model

  • 软件规模:千万行代码,数千程序员共同维护(言外之意就是效率太低了,语言和开发者两个层面)

  • 编译时间太长,几分钟到几小时都有(特别讲了 C++ #include 在编译上的消耗: Dependencies in C and C++)

  • 依赖混乱,跨语言构建麻烦

  • 难以编写自动化工具

译者注: 结合原文之后的内容来看,最主要的两类问题就是 大规模的 C++ 项目编译时间长,以及多种语言维护成本高的问题

发明者

Robert Griesemer: 参与过谷歌 V8 引擎的开发,Sawzall 语言(谷歌内部用的日志分级打印库,之后被 go 的日志库替代)、JVM 和 strongtalk 系统(用于类型检查,现在不维护了)

Rob Pike:Unix 开发者之一,为 Unix 编写过终端,后续编写过 sam、acme 文本编辑器,再之后和 Ken Thompson 一起创造了 UTF-8

Ken Thompson: Unix 开发者之一,B语言(C语言的前身)的发明者,后面 Dennis Ritchie 基于 B 语言又开发了 C语言。1983 年 Ken 和 Dennis 一同获得了图灵奖

扩展: Russ Cox,你可以在 golang 的很多 issue 中看到他的身影,他也是go代码提交次数最多的

go 语言介绍_第1张图片

推荐阅读: 图灵奖历届得主、golang talk

吉祥物

名字: Gopher(囊地鼠)

由 Rob Pike 的妻子 Renee French 创作,官网甚至还有细节描述呢

go 语言介绍_第2张图片

go 语言介绍_第3张图片

go 是什么样的语言

为了解决前面说的问题,go 必须有下面的特点:

  • 高效率、可扩展、满足生产力需求
  • 必须有可扩展性,对于代码量多、依赖多、开发者多的大型项目 必须能很好运作
  • 自带 GC,并在对象内存申请、释放空间上进行优化,保证GC尽量不影响业务运行
  • 符合C的编程习惯,让程序员能丝滑切换(如: 静态类型对象)
  • 必须足够现代化,在多核处理、网络、web 应用开发上需要更加方便,也要支持更多新特性,如内置的并发编程方案

时间和版本

golang 版本来源: 从 1.10 到最新

go 语言介绍_第4张图片

go 语言特点

go 语言特点

本节中,笔者将结合自己平时开发过程中使用到的 go 比较核心的特性进行基本介绍,这些也是 go 和其他编程语言最不同的地方,包括 基本语法、基本指令、函数、关键字、基本类型、打包方式等

语法

  • 通过大括号划分代码块,保证大项目下依旧结构清晰
  • 不需要分号,虽然加了也不会报错
  • 不需要小括号,比如在 if a < b 判断语句、for 循环中的判断,都不需要
  • 未使用的 import / 局部变量将报错,保证编译不会引入多余的代码,提升编译效率

执行

  • go build: 统一的打包语句
  • 编译后生成一个可执行文件

debug

  • pprof: 自带性能指标库,可通过火焰图、命令行查看堆栈情况、堆大小、各协程调用耗时等

函数

  • 接口不需要显式说明继承,只要实现了接口的方法即算是继承
  • 接口可以通过 指针接收器(pointer receiver) 或 **值接收器(value receiver)**实现,分别适合 setter 和 getter 的实现,大对象的方法也适合用 指针接收器 避免频繁拷贝(参考: 什么时候适合用什么接收器?)
  • 方法可以作为对象传递,可以作为 map 的 value、声明匿名方法、定义闭包(闭包常用于定义配置方法,如 trpc 的 server.Opts 及其具体实现方法)
  • 不支持重载,用开发必须增加少量代码的代价换来了 代码可读性和编译性能(一些讨论)
  • 建议使用组合(composition),而不是继承(inheritance)(对比: java 类在多次继承后,要找到只在基类实现的方法的源代码,需要跳很多次才能找到,相反,组合的结构就很清晰,只有一层)

错误处理

  • 没有异常机制,通过 error + 函数返回值 直接返回报错,在外部及时处理错误(也促使开发者封装好会出现 error 的代码块,减少主函数的层级)
  • 通过 panic + recover 机制捕获协程中发生的严重错误(如空指针)

基本类型和关键字

  • 切片(slice)和数组(array): 切片包含数组、长度(len)和容量(cap)
  • map: 非协程安全的 map(slice 也是非协程安全的,go 设计上就是让 channel 成为唯一的协程间通信对象)
  • defer: 常用于释放资源、panic 处理
  • make: 申请切片、map 和 channel 的空间
  • init 方法: 被引用的时候,包内的所有 init 方法会自动执行。单个包内的 init 方法执行顺序按 文件名字段序 -> 方法从上到下 的顺序执行,参考
  • 声明对象的方式: 通过 var 指定对象名称和类型,或直接 a := 1,编译器自动识别字段类型
  • const: 声明常量
  • iota: 枚举,只能是数值
  • 空白标识符: 下划线(_),可用于忽略返回值,迭代 slice 或者 map 时忽略 下标/key,以及 init import(只执行包的 init 方法,不需要显式调用包的资源,如: import _ “net/http/pprof”)
  • select case: 多个 Channel 同时读取方式
  • 总共只有[25个关键字](https://articles.wesionary.team/know-about-25-keywords-in-go-eca109855d4d),相比: C99 有 37 个,C++11 有 84 个

原生库和方法

  • time: 时间,方法有 time.Parse, time.Now, time.DateTime(常量 2006-01-02 15:04:05)等
  • io.ReadAll: 数据流
  • bytes.Buffer: 字符串缓冲
  • strings、maps、slices: 集合类型的工具方法,如 strings.ReplaceAll、maps.Clone、slices.Sort 等
  • regexp: 正则
  • net/http: http 核心库
  • sort: 1.19 之前的数组排序库
  • log/slog: 1.21 新增的日志库,支持等级和格式化打印
  • sync: 协程之间同步、状态共享的相关组件库。Mutex: 锁;Once: 只执行一次;WaitGroup: 等待n个协程执行;Pool: 协程间复用对象;Cond: 等待和唤醒

反射

  • reflect.TypeOf: 获取对象的具体类型
  • reflect.Kind: 获取对象的类别(和类型的区别: 具体值或指针的类别为 interface / pointer,类型可以拿到具体的 struct或接口类型)
  • reflect.ValueOf: 获取对象的具体值
  • struct tag: 标注 struct 内属性的附加信息,一般用于 json序列化、yaml 内容解析、orm 字段映射等场景

并发

  • 协程(Routine): 用户层的“线程”,通过 go func() 开启并发
  • 管道(Channel): 协程间的通信方式
  • 上下文(Context): 协程间传递数据、父协程控制子协程状态的媒介

运行时(Runtime)

  • GPM: Go 进程的核心,协程(Goroutine)、处理器(Processor)、系统线程(Machine)
  • GC: 三色标记法、混合写屏障等

包管理

  • 从 git 路径引用依赖,没有“官方仓库”的说法,去中心化的设计
  • 以 git tag 或者 commit id 作为版本标识
  • 对象和方法是否对外可见,通过首字母大小写来标识,大写为开放,简单明了

工具

  • gofmt、goformat、staticcheck: 代码格式化
  • test、bench、fuzz: 普通测试、并发测试、混沌测试
  • doc: 文档,go 的文档可在源码中通过注释编写,并自动生成

以上就是自己常接触的原生库了,可以从 go源码的src目录 更多的实现细节

自己写的和go有关的博客

golang 编程规范查漏补缺

golang-使用 go test 输出单元测试覆盖率

golang-单元测试和mock框架的介绍和推荐

golang-使用 godoc 工具编写代码注释

golang-文章翻译-go高效编程

golang-文章翻译-go常见的10种错误

vscode 使用技巧(vscode+go插件的开发环境)

go 学习方法总结

官网

Go 的官网其实是最好的学习资料,教程、博客、社区动态都有,绝对适合作为入门资料的第一位

下面说明官网中右上角各个栏目的内容

go 语言介绍_第5张图片

为什么使用 Go(Why Go)

大体就是 Go 在一些通用领域的使用场景,以及在大厂的使用情况

Case Studies: 大厂的使用场景,如 Google、CloudFare、Meta、Netflix 等

Use Cases: 在云服务、网络通信、命令行工具、网页/客户端应用 和 运维和可持续开发(DevOps、SRE)领域的应用
每一个领域下都有比较流行的开源项目的推荐

Security: 如何提升自己工程的安全性,如通过 govulncheck 检查项目存在哪些已知漏洞

Learn

非常适合上手的 go tour,几乎覆盖了 go,可以说练习完所有示例就会写 go 代码了

Docs

所有官方文章: 可以挑讲原理的文章看,如 Using and understanding Go 中的 A Guide to the Go Garbage Collector 以及 References 中的 The Go Memory Model

Effective Go: 上手之后,进一步了解 go 编程风格的必读文章

std: 标准库文档

faq: 囊括了从其他语言迁到 go 语言的常见问题,也体现了 go 的设计思想

社区

blog: go 博客,社区新动态

开源项目和代码推荐

go

go 本身的源码就很好阅读,也和 go 本身语法比较简洁有关。如果你想了解 go 的基础库的原理,大可不用搜一堆博客,一点点地消化别人的总结,读go源码就是最好的学习go原理的方法
包括: sync, runtime, context, reflect,这些都是 go 的核心库

web 应用

开发后台必须要掌握的就是 web 框架,当然不同公司对它的定制化也会不同,如果想从简单的入手,使用官方推荐的 gin 就行。想参考大厂实际用的,可参考国内开发者开源的 web 框架(功能比较全),如字节的 hertz、go-zero、goframe 等

中间件

gorm: 数据库 orm 库
redis: redigo
kafka: sarama

云原生和监控

如 Kubernetes、Istio、Prometheus、Grafana 等,也能接触到当下比较流行的项目

命令行工具

以往我们需要用工具进行文档格式转换、爬虫、文件批量下载等场景,可能会主要以 python 项目作参考,因为它语法简单,执行方便,你需要的只是一个 python 环境

现在,拥有类似特性的 go 让我们多了一个选项,同样的需求,也可以看 go 社区有没有现成的方案。甚至 go 只需要编译好的可执行文件,更加方便

具体用哪个工具因需求而异,可以参考别人的整理,这里列几个可能比较常用的:

hugo: 博客网站生成,类似 hexo

buffalo: 快速生成 web 项目

vhs: 终端录制

pget: 并发下载

fsnotify: 系统文件监听

lux: 网站视频下载工具(不能下载需要登录才能下的超高画质)

migrate: 跨不同类型数据库迁移

博客推荐

golang 在国内大厂实践还是比较多的,因此国内开发者写的博客也不会缺少。本着技术的学习方法来说,这里推荐两个博主 分别对应前沿动态,和深度剖析原理

煎鱼: go 语言开发者,对 go 社区动态、新版本特性的跟踪比较及时,类似的博主还有 polarisxu

go语言设计与实现: go 原理和设计思想,这个博客对技术的思考方式值得应用到所有技术的学习上: 从为什么这么设计的问题基础上,去理解技术实现细节

你可能感兴趣的:(golang,golang,开发语言,后端)