来自于 Go 语言第一课

泛型的定义:
泛型编程的中心思想是对具体的、高效的算法进行抽象,以获得通用的算法,然后这些算法可以与不同的数据表示法结合起来,产生各种各样有用的软件”。说白了就是将算法与类型解耦,实现算法更广泛的复用。

泛型解决的问题:

  1. 数学计算:写出通用的方法来操作 int 、 float 类型;
  2. 集合类型:例如用泛型来写堆、栈、队列等。虽然大部分类似的需求可以通过 slice 和channel 来解决,但是始终有一些情况难以避免要设计特殊的集合类型,如有序 Set和优先级队列;
  3. slice 和 map 的辅助方法:典型的如 map-reduce API;

泛型定义

我们知道,普通函数的参数列表是这样的:
func Foo(x, y aType, z anotherType)

这里,x, y, z 是形参(parameter)的名字,也就是变量,而 aType,anotherType 是形参的类型,也就是类型。

我们再来看一下泛型函数的类型参数(type parameter)列表:

func GenericFoo[P aConstraint, Q anotherConstraint](x,y P, z Q)

这里,P,Q 是类型形参的名字,也就是类型,aConstraint,anotherConstraint 代表类型参数的约束(constraint),我们可以理解为对类型参数可选值的一种限定。

但在泛型函数声明时,我们并不知道 P、Q 两个类型参数具体代表的究竟是什么类型,因此函数参数列表中的 P、Q 更像是未知类型的占位符。

约束(constraint)
约束(constraint)规定了一个类型实参(type argument)必须满足的条件要求。如果某个类型满足了某个约束规定的所有条件要求,那么它就是这个约束修饰的类型形参的一个合法的类型实参。

Go 语言能力由低到高划分为以下 5 个级别
初级:已经学习完 Go 基础语法课程,能够编写一些简单 Go 代码段,或者借助于
Google/Baidu 能够编写相对复杂的 Go 代码段;这个阶段的你基本具备阅读 Go 项目
代码的能力;

中级:能够独立编写完整的 Go 程序,例如功能简单的 Go 工具等等,或者借助于
Google/Baidu 能够开发一个完整、简单的 Go 项目。此外,对于项目中涉及到的其他
组件,我们也要知道怎么使用 Go 语言进行交互。在这个阶段,开发者也能够二次开发
一个相对复杂的 Go 项目;

高级:不仅能够熟练掌握 Go 基础语法,还能使用 Go 语言高级特性,例如 channel、
interface、并发编程等,也能使用面向对象的编程思想去开发一个相对复杂的 Go 项
目;

资深:熟练掌握 Go 语言编程技能与编程哲学,能够独立编写符合 Go 编程哲学的复杂
项目。同时,你需要对 Go 语言生态也有比较好的掌握,具备较好的软件架构能力;

专家:精通 Go 语言及其生态,能够独立开发大型、高质量的 Go 项目,编程过程中较
少依赖 Google/ 百度等搜索工具,且对 Go 语言编程有自己的理解和方法论。除此之
外,还要具有优秀的软件架构能力,能够设计、并部署一套高可用、可伸缩的 Go 应
用。这个级别的开发者应该是团队的技术领军人物,能够把控技术方向、攻克技术难
点,解决各种疑难杂症。

Go语言中常用的那些代码优化点

第一点:使用 pkg/errors 而不是官方 error 库

第二点:在初始化 slice 的时候尽量补全 cap
arr := make([]int, 0, 5)
make 中设置了 cap 的长度,就是 slice 的大小,但是实际运行的时候,会少运行了一个growslice 的命令,能够提升我们程序的运行性能。这个 growslice 的作用就是扩充 slice 容量,每当我们的 slice 容量小于我们需要使用的slice 大小,这个函数就会被触发。

当然,我们并不是每次都能在 slice 初始化的时候,就准确预估到最终的使用容量,所以我
这里说的是“尽量补全 cap”

第三点:初始化一个类的时候,如果类的构造参数较多,尽量使用 Option写法
Option 写法,顾名思义,就是将所有可选的参数作为一个可选方式,一般我们会设计一个“函数类型”来代表这个 Option,然后配套将所有可选字段设计为一个这个函数类型的具体实现。(所需要的参数放在结构体中,初始化结构体传参数)

第四点:巧用大括号控制变量作用域
这个大括号里面的变量和逻辑是一个完整的部分,他们内部创建的变量不会泄漏到外部。


goper
413 声望25 粉丝

go 后端开发