在最新的go1.18版中增加了期盼已久的泛型支持
泛型是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。
如果没有泛型,对于golang语言这种强类型语言,针对不同类型的函数解决方式:
以int64和int类型为例:
func CompareInt64(a, b int64) bool { if a >= b { return true } return false}func CompareInt(a, b int) bool { if a >= b { return true } return false}func Compare(a, b interface{}) bool { switch a.(type) { case int64: a1 := a.(int64) b1 := b.(int64) if a1 >= b1 { return true } return false case int: a1 := a.(int) b1 := b.(int) if a1 >= b1 { return true } return false default: return false }}
使用泛型
golang支持泛型函数和泛型类型
// 泛型函数func F[T any](p T) (args T){ ... }
[T any]为类型约束,any 表示任意类型,(args T)为参数。
使用泛型实现上例
func Compare[T int64|int](a, b T) bool { if a >= b { return true } return false}
参数多的话也可这样
type TT interface { int | int64}func Compare[T TT|int](a, b T) bool { if a >= b { return true } return false}
有了泛型后:
package mainimport ( "fmt")// 泛型切片type Name[T any] []Ttype TestSilce [T int | float64] []Tfunc ListElem[T int | float64 | string](params []T) { for _, elem := range params { fmt.Printf("类型=%T,val=%+v\n", elem, elem) } return}func main() { v := Name[string]{"a", "b"} fmt.Printf("类型=%T,val=%+v\n", v, v) ListElem(v) l := TestSilce[int]{1, 2, 3} fmt.Printf("类型=%T,val=%+v\n", l, l) ListElem(l)}
预声明标识符 comparable是一个接口,表示可以使用==or进行比较的所有类型的集合!=。它只能用作(或嵌入)类型约束。
package mainimport "fmt"type Number interface { int64 | float64}type M[K string ,V any] map[K]Vfunc main() { // Initialize a map for the integer values ints := M[string, int64]{ "first": 34, "second": 12, } // Initialize a map for the float values floats := map[string]float64{ "first": 35.98, "second": 26.99, } fmt.Printf("Generic Sums: %v and %v\n", SumIntsOrFloats[string, int64](ints), SumIntsOrFloats[string, float64](floats)) fmt.Printf("Generic Sums, type parameters inferred: %v and %v\n", SumIntsOrFloats(ints), SumIntsOrFloats(floats)) fmt.Printf("Generic Sums with Constraint: %v and %v\n", SumNumbers(ints), SumNumbers(floats))}// SumIntsOrFloats sums the values of map m. It supports both floats and integers// as map values.func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {var s Vfor _, v := range m {s += v}return s}// SumNumbers sums the values of map m. Its supports both integers// and floats as map values.func SumNumbers[K comparable, V Number](m map[K]V) V { var s V for _, v := range m { s += v } return s}
package mainimport "fmt"type Number interface { int64 | float64}type Stack[V Number] struct { size int64 value []V}func (s *Stack[V]) Push(v V) { s.value = append(s.value, v) s.size++}func main() { s := &Stack[int64]{} s.Push(1) fmt.Printf(" %T and %v\n",s,s)}
package mainimport "fmt"type Ch[T any] chan Tfunc main() { ch := make(Ch[int], 1) ch <- 10 res := <-ch fmt.Printf("类型=%T,val=%+v", res, res)}
函数和 类型声明 的语法 现在接受 类型参数。
参数化函数和类型可以通过在它们后面加上方括号中的类型参数列表来实例化。
新标记~已添加到 运算符和标点符号集中。
预声明标识符 any是空接口的别名。它可以代替 interface{}.
接口类型 的语法 现在允许嵌入任意类型(不仅仅是接口的类型名称)以及联合和~T类型元素。此类接口只能用作类型约束。一个接口现在定义了一组类型和一组方法。
预声明标识符 comparable是一个接口,表示可以使用==or进行比较的所有类型的集合!=。它只能用作(或嵌入)类型约束。
加入泛型后对编译性能有影响,编译速度慢了15%。
https://go.dev/doc/tutorial/generics
https://blog.csdn.net/Jcduhdt/article/details/123937721