美文网首页
define generic type by using int

define generic type by using int

作者: 9_SooHyun | 来源:发表于2023-06-27 20:07 被阅读0次

define generic type by using interface in golang

1.泛型起点: interface contains type constraints

在 Go 1.18 版本中,泛型被引入。

在之前的 Go 版本中,interface只是方法的集合,但在 1.18 版本中,为了引入泛型而扩展了原有interface的使用方式,从此interface可以额外表达【类型限制】的语义

interface can contain Type Constraints

2.interface before Go 1.18 without Type Constraints

Go 1.18 前的 interface 是鸭子类型(duck typing)的一种具体实践,实现了 Go 风格的 Duck typing。(注:python大量的鸭子类型,而不需要定义接口。不同语言中鸭子类型的实现不完全相同。golang中使用interface实现鸭子类的方式非常显式和直接)

interface,或者说鸭子类型的关注点在于对象的行为,能做什么;而不是关注对象所属的类型

因此,an interface only defines a set of methods

interface本身就是广义的泛型,是不限制具体实现的泛型

3.interface after Go 1.18 with Type Constraints

为了引入泛型,Go 1.18 后的interface不仅定义行为,还能够限制接口的实现,也就是限制具体实现所属的类型

interface 成为【可以限制具体实现】的泛型,即interface can contain Type Constraints

eg.

type I struct {
    int | int32 | float64  // 限制接口I的实现必须是 int | int32 | float64 的实例对象
}

注意,实际上,接口应当只定制协议,而不应该去限制具体实现。带有 Type Constraints 的 interface 让接口的语义变得模糊不清,将 Type Constraints 纳入 interface 未必是一个好的设计。你见过要限制品牌、材质的充电器的接口协议么?

于是,golang对于带/不带 Type Constraints 的 interface 的使用场景也是有区别的,带有 Type Constraints 的 interface 只能用作泛型的类型限制,保证类型参数的值必须在特定范围内

带有 Type Constraint 的 interface 只能用作泛型中的类型限制。从这种意义上看,interface with Type Constraint 可以认为是新的类型

// You can edit this code!
// Click here and start typing.
// https://go.dev/play/p/4Z84Y-SPFqg
package main

import "fmt"

type IWithTypeConstraint interface {
    ~int32 | ~int64
}

type IWithoutTypeConstraint interface {
}

func main() {
    // var i IWithTypeConstraint = int32(1) // compile failed. cannot use type IWithTypeConstraint outside a type constraint: interface contains type constraints
    // fmt.Println(i)

    var i IWithoutTypeConstraint = int32(1)
    fmt.Println(i)
}

4.泛型的设计

  • Go的泛型实现的是类型参数化。泛型通过方括号[]定义类型参数(类型参数和一般参数一样,都是参数,只是用途不同)在Go语言的泛型方案中,泛型函数 和 泛型类型 都需要显式地声明类型参数(type parameter),并向类型参数传参以实例化 泛型函数 和 泛型类型
  • 在编译时,Go编译器会为每个实际使用的泛型类型生成特定的代码,从而在运行时避免额外的类型检查和类型转换开销

5.泛型的语法

[TypeParameter typeConstraint] eg [T Any]

首先需要定义泛型参数,如 T, 在结构或函数名称后面方括号里面使用。T 可以是任何类型或者接口,即[T]实际上是[T Any]

type Node[T] struct {
    value T
}

T可以加约束条件:
type parameter with constraints

type Node[T comparable] struct {
    value T
}

You can declare your costom type constraint as an interface.

If you declare a type constraint interface with three methods, then use it with a type parameter in a generic function, type arguments used to call the function must have all of those methods.

Constraint interfaces can also refer to specific types

类型限制是泛型的一部分,它允许您限制泛型类型参数可以接受的具体类型。这可以帮助您编写更加安全、可预测的泛型代码。在使用类型限制时,您可以指定一个接口作为限制,泛型类型参数必须满足这个接口。这意味着,泛型类型参数必须实现这个接口所定义的所有方法。

// https://go.dev/play/p/LpSyeLQmhkd

package main

import "fmt"

type Addable interface {
    // define generic type constraints by using interface
    ~int | ~float64
}

func PrintSum[T Addable](a, b T) {
    fmt.Println(a + b)
}

func main() {
    PrintSum(1, 2)     // 输出 3
    PrintSum(1.1, 2.2) // 输出 3.3
}

总结

  • An interface without type constraints, only defines a set of methods, is a pure interface, and is the protocol itself

  • Interfaces without type constraints, not pure interfaces, should be treated as new types for generics

相关文章

网友评论

      本文标题:define generic type by using int

      本文链接:https://www.haomeiwen.com/subject/uimnydtx.html