• Geek14
    2023-01-06 来自辽宁
    // 定义一个支持比较的接口,用于类型参数约束 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) }

    作者回复: 👍

    
    2
  • Geek14
    2023-01-06 来自辽宁
    请教老师两个问题: 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给出了一个伪码的例子,可以看看那个。

    共 2 条评论
    2
  • return
    2022-12-07 来自广东
    老师讲的好呀,感谢老师。 期待老师新作品。

    作者回复: 👍

    
    1
  • Calvin
    2022-11-10 来自北京
    思考题: // 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) }
    展开

    作者回复: 👍。

    
    1
  • lesserror
    2023-08-07 来自广东
    tony bai 老师,文中的:“并且被保存在 ELF 的只读数据区段(.data)中”,这里的ELF是什么的缩写呢?

    作者回复: ELF 是 Executable and Linkable Format的缩写。是linux上一种标准的可执行文件的格式。

    
    
  • 罗杰
    2022-11-09 来自北京
    看一遍肯定是不够的,🉐️好好吸收

    作者回复: 👍

    
    