Loading... # 0x00 这次golang正式更新了泛型(之前的1.17 和1.18 Beta 1 中的只是测试版,其中有一些用法和正式版有较大的差别),是一次重大的更新,原以为在GO2.0的时候更新。 # 0x01 类型形参(Type Parameters) 在之前想要实现一些通用的功能还是比较麻烦的,而且代码冗余。 比如实现gorm添加json类型字段: ```golang type Table struct { AField A BField B } type A struct { AText string } func (A) GormDataType() string { return "json" } func (a *A) Scan(value interface{}) error { return json.Unmarshal(value.([]byte), a) } func (a A) Value() (value driver.Value, err error) { src, err := json.Marshal(a) return string(src), err } type B struct { BText string } func (B) GormDataType() string { return "json" } func (b *B) Scan(value interface{}) error { return json.Unmarshal(value.([]byte), b) } func (b B) Value() (value driver.Value, err error) { src, err := json.Marshal(b) return string(src), err } ``` 可以看到`A`和`B`中的`GormDataType` `Scan` `Value`方法几乎都是重复的,假如再添加`C` `D`那么就要添加6个重复发方法。 <br/> 而golang 1.8开始正式支持泛型,那么利用泛型可以降低这样的代码冗余 使用泛型再次实现上述内容: ```golang type Table struct { AField JSON[A] BField JSON[B] } type A struct { AText string } type B struct { BText string } type JSON[T any] struct { Data T } func (JSON[T]) GormDataType() string { return "json" } func (m *JSON[T]) Scan(value interface{}) error { return json.Unmarshal(value.([]byte), &m.Data) } func (m JSON[T]) Value() (value driver.Value, err error) { src, err := json.Marshal(m.Data) return string(src), err } ``` 可以看到我这里定义了一个`JSON[T any]`的类型专门处理json类型,此后添加`C` `D`字段就只需要定义相关的结构体并且添加`JSON[C]` `JSON[D]`即可。 <br/> 其中`any`类型也是这次更新后的新类型字段,但`any`其实就是`interface`类型的别称 源码: ```golang // src/builtin/builtin.go 95行 // any is an alias for interface{} and is equivalent to interface{} in all ways. type any = interface{} ``` 个人感觉`any`相比`interface`在传参等场合更直观 比如: ```golang func Println(v ...any){} func Println(v ...interface){} ``` 当然,在定义接口时还是得用`interface`字段 <br/> ## 判断类型 ```golang func (m *JSON[T]) Test() { switch any(m.Data).(type) { case A: fmt.Println("A") case B: fmt.Println("B") } } ``` [#1014950980](https://github.com/golang/go/issues/45380#issuecomment-1014950980) # 0x02 类型集合(Type Sets) 类型集合允许定义一个类型具有不同类型的集合 例如: ```golang type Test interface { int|float64 } ``` 定义了一个`Test`类型,表示为`int` `float64`类型的集合 <br/> 如果不用泛型那怎么写呢 不使用泛型: ```golang func Add(a, b interface{}) interface{} { switch a.(type) { case int: return a.(int)+b.(int) case float64: return a.(float64)+b.(float64) } return 0 } ``` 使用泛型: ```golang func Add[T int | float64](a, b T) T { return a + b } ``` 这样一对比使用泛型就简洁多了 <br/> 应用: ```golang type Num interface { int | int64 | int32 | float64 | float32 | uint | uint8 | uint16 | uint64 } func Add[T Num](a, b T) T { return a + b } func Sub[T Num](a, b T) T { return a - b } ``` <br/> # 0x03 类型约束 ```golang type T interface { int | float64 | ~string } ``` 其中的`~string`表示定义的`T`类型集合也支持底层类型是`string`的类型 比如: ```golang type A interface { ~string } func Splic[T A](a, b T) T { return a + b } var BString string func main() { var a string = "a" var b BString = "b" Splic(a, b) } ``` 其中`BString`是自定义的一个底层为`string`的类型,如果没有加`~`的话会报错 Last modification:April 29, 2022 © Allow specification reprint Support Appreciate the author AliPayWeChat Like 0 如果觉得我的文章对你有用,请随意赞赏
One comment
rehttNb