Golang中如何声明泛型指针接口或切片指针接口参数的方法

Golang中如何声明泛型指针接口或切片指针接口参数的方法 0

例如:

type AnyPtr[T any] interface {
    *T
}

type AnyPtrSlice[T any] interface {
    []*T
}

func FuncName[T AnyPtr[E] | AnyPtrSlice[E], E any](data T) (err error) {
}


type ModelAA struct {
    A int
    B int
}

func TestAddV2(t *testing.T) {
    var a = ModelAA{
        A: 1, B: 2,
    }
    _ = FuncName(&a)
}

这种方法会被编译器报告为无法推断 E。是否有其他写法?


更多关于Golang中如何声明泛型指针接口或切片指针接口参数的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你好 @wake2012,欢迎来到论坛。

也许你出于某些在代码片段中不明显的原因需要那两个 Any* 接口,但我已将它们移除以简化代码。在给定代码的上下文中,以下函数签名在语义上等同于你使用 Any* 接口的定义:

func FuncName[T *E | []*E, E any](data T) (err error)

这个错误信息似乎不合理,因为 &a 的类型显然是“指向 ModelAA 的指针”,而不是“指向 ModelAA 的指针切片”。但你可以帮助编译器,在调用函数时指定用于 TE 的类型:

package main

import "testing"

func FuncName[T *E | []*E, E any](data T) (err error) {
	return nil
}

type ModelAA struct {
	A int
	B int
}

func TestAddV2(t *testing.T) {
	var a = ModelAA{
		A: 1, B: 2,
	}
	_ = FuncName[*ModelAA, ModelAA](&a)
}

在 Go Playground 中运行此代码

(另请参阅语言规范中的类型推断

更多关于Golang中如何声明泛型指针接口或切片指针接口参数的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中,要声明泛型指针接口或切片指针接口参数的方法,可以使用类型约束组合的方式。以下是几种可行的写法:

方案1:使用类型集约束

type AnyPtr[T any] interface {
    *T
}

type AnyPtrSlice[T any] interface {
    []*T
}

type PtrOrSlice[T any] interface {
    AnyPtr[T] | AnyPtrSlice[T]
}

func FuncName[T PtrOrSlice[E], E any](data T) error {
    // 处理逻辑
    return nil
}

type ModelAA struct {
    A int
    B int
}

func TestAddV2(t *testing.T) {
    var a = ModelAA{A: 1, B: 2}
    _ = FuncName(&a)
}

方案2:使用~操作符和类型约束

type Pointer[T any] interface {
    ~*T
}

type PointerSlice[T any] interface {
    ~[]*T
}

type PtrConstraint[T any] interface {
    Pointer[T] | PointerSlice[T]
}

func ProcessData[T PtrConstraint[E], E any](data T) error {
    // 处理逻辑
    return nil
}

type ModelAA struct {
    A int
    B int
}

func TestAddV2(t *testing.T) {
    var a = ModelAA{A: 1, B: 2}
    _ = ProcessData(&a)
}

方案3:使用类型断言处理

type AnyPtr[T any] interface {
    *T
}

type AnyPtrSlice[T any] interface {
    []*T
}

func FuncName[T any](data T) error {
    switch v := any(data).(type) {
    case AnyPtr[any]:
        // 处理指针类型
        return nil
    case AnyPtrSlice[any]:
        // 处理切片类型
        return nil
    default:
        return errors.New("unsupported type")
    }
}

type ModelAA struct {
    A int
    B int
}

func TestAddV2(t *testing.T) {
    var a = ModelAA{A: 1, B: 2}
    _ = FuncName(&a)
}

方案4:使用两个独立的泛型参数

type AnyPtr[T any] interface {
    *T
}

type AnyPtrSlice[T any] interface {
    []*T
}

func HandlePtr[T AnyPtr[E], E any](data T) error {
    // 处理指针
    return nil
}

func HandleSlice[T AnyPtrSlice[E], E any](data T) error {
    // 处理切片
    return nil
}

type ModelAA struct {
    A int
    B int
}

func TestAddV2(t *testing.T) {
    var a = ModelAA{A: 1, B: 2}
    _ = HandlePtr(&a)
}

这些方案都能避免编译器无法推断类型参数E的问题。第一种方案使用类型集约束组合是最直接的方式,第二种方案使用~操作符可以处理类型别名,第三种方案使用类型断言在运行时处理,第四种方案将功能拆分为独立的函数。

回到顶部