41 | 驯服泛型:明确使用时机
该思维导图由 AI 生成,仅供参考
何时适合使用泛型?
场景一:编写通用数据结构时
- 深入了解
- 翻译
- 解释
- 总结
Go语言的泛型实现方案备受关注,本文介绍了三种不同的实现方案:Stenciling、Dictionaries和GC Shape Stenciling。其中,GC Shape Stenciling方案是Go 1.18泛型最终采用的实现方案。文章通过具体的示意图和示例,清晰地阐述了每种方案的特点和优缺点。此外,文章还提到了泛型对执行性能的影响,指出在一些性能敏感的系统中,了解泛型对执行性能的影响尤为重要。在Go 1.20版本中,由于将使用Unified IR替换现有的IR表示,Go泛型函数的执行性能将得到进一步优化。总的来说,本文通过深入浅出的方式,为读者提供了对Go泛型实现方案的全面了解,为读者提供了实用的指导建议。
《Tony Bai · Go 语言第一课》,新⼈⾸单¥59
全部留言(6)
- 最新
- 精选
- Geek14// 定义一个支持比较的接口,用于类型参数约束 type ordered interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64 | ~string } // 定义支持排序的泛型切片 type SortableSlice[T ordered] []T // 让泛型切片实现sort.Interface func (s SortableSlice[T]) Len() int { return len(s) } func (s SortableSlice[T]) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s SortableSlice[T]) Less(i, j int) bool { return s[i] < s[j] } // 定义一个泛型排序函数 func SortGeneric[T ordered](s SortableSlice[T]) { sort.Sort(s) }
作者回复: 👍
2023-01-06归属地:辽宁3 - Geek14请教老师两个问题: 1、在讲解泛型实现原理时,文中提到“C++ 语言路径:就像 C++ 的泛型实现方案那样,通过增加编译器负担为每个类型实参生成一份单独的泛型函数的实现,这种方案产生了大量的代码,其中大部分是多余的,……” 为啥“其中大部分是多余的”,每个类型实参一个单独的实现,这不是刚刚好吗,为啥会有多余的实现? 2、Dictionaries 方案没看明白。模板方案比较好理解。编译阶段为每个类型实参创建一个泛型函数的单独实现,单独实现后函数内使用的泛型类型都会是具体的类型。那Dictionaries 方案种泛型函数中的泛型类型是具体类型实参类型吗?如果是具体的实参的类型,是怎么做到? 希望老师有时间帮忙解答下疑惑。
作者回复: 都是好问题。 问题1:这句话来自于Russ Cox 的“泛型窘境”的文章。不知道你对c++的编译过程了解怎样。像c/c++这样的源码的编译分为两个阶段:编译和链接。其中编译阶段是以.c/.cpp为编译单元,将源码编译为一个个.o文件,每个编译单元的编译都是独立的。因此如果一个泛型函数在多个编译单元都会被调用(比如实参是int),那么每个编译单元编译时都会为int生成一份独立的泛型函数代码,这样就拖慢了编译器的编译时间。之后在链接阶段,链接器才会将位于各个.o中的这些冗余的重复代码进行清除,只保留一份。 问题2:调用泛型函数时传入的实参肯定是实参类型啊。这块编译器会将其转换为特定的函数调用,比如:f(dict.float64, 3.14)。至于具体实现,https://github.com/golang/proposal/blob/master/design/generics-implementation-dictionaries.md 这个proposal design给出了一个伪码的例子,可以看看那个。
2023-01-06归属地:辽宁23 - return老师讲的好呀,感谢老师。 期待老师新作品。
作者回复: 👍
2022-12-07归属地:广东1 - Calvin思考题: // sort.Interface -> IntSlice / StringSlice 泛型版 type xsl interface { ~int | ~string } type xSlice[T xsl] []T func (x xSlice[T]) Len() int { return len(x) } func (x xSlice[T]) Less(i, j int) bool { return x[i] < x[j] } func (x xSlice[T]) Swap(i, j int) { x[i], x[j] = x[j], x[i] } func sortX[T xsl](data xSlice[T]) { sort.Sort(data) } func TestXSlice(t *testing.T) { x1 := make(xSlice[int], 0, 5) x1 = append(x1, 3) x1 = append(x1, 10) x1 = append(x1, 2) x1 = append(x1, 0) x1 = append(x1, 9) sortX(x1) t.Logf("[]~int x = %#v", x1) type mystr string x2 := []mystr{"ab", "ca", "fc", "ce", "bf"} sortX(x2) t.Logf("[]~string x = %#v", x2) }
作者回复: 👍。
2022-11-10归属地:北京1 - lesserrortony bai 老师,文中的:“并且被保存在 ELF 的只读数据区段(.data)中”,这里的ELF是什么的缩写呢?
作者回复: ELF 是 Executable and Linkable Format的缩写。是linux上一种标准的可执行文件的格式。
2023-08-07归属地:广东 - 罗杰看一遍肯定是不够的,🉐️好好吸收
作者回复: 👍
2022-11-09归属地:北京