Golang中如何将值(非指针)返回给泛型类型?

Golang中如何将值(非指针)返回给泛型类型? 我有一个可以正常工作的函数:

package main

type CISettings interface {
	Clone() CISettings
	Merge(other CISettings)
}

type Settings struct{}

func (s *Settings) Clone() CISettings {
	return &Settings{}
}

func (s *Settings) Merge(other CISettings) {
}

func ParseCISettings[T CISettings](settings T) error {
	sett := settings.Clone()
	settings.Merge(sett)
	return nil
}

func main() {
	sett := Settings{}
	ParseCISettings[*Settings](&sett)
}

链接

我遇到了一个难题,不明白为什么当我尝试返回 settings 时,下面这个签名就不起作用了:

ParseCISettings[T CISettings](settings T, err error)

链接

我无法理解编译器试图告诉我什么。如果我使用值接收器,它可以工作,但 Merge 方法不应该那样实现,它需要一个指针接收器


更多关于Golang中如何将值(非指针)返回给泛型类型?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

8 回复

我不知道你想表达什么,如果可以的话,写一些伪代码。

更多关于Golang中如何将值(非指针)返回给泛型类型?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你理解错了问题: 我想返回一个新的类型 Settings,而不是把它传进去。

你能具体说明一下你到底想实现什么吗?解析函数应该有哪些参数,它会返回什么?因为现在我有点困惑。

我对你预期的结果仍然有点困惑,但也许你正在尝试做类似这样的事情:

Go Playground - The Go Programming Language

?

谢谢,这已经很接近我想要的。 但无论解析函数做什么,我都想返回一个 Settings 值(或者指向它的指针)。但我不知道如何构造这样的东西,因为 var v T 不起作用。或者,在使用 T 作为参数的泛型函数中,我该如何构造一个新值?

type Settings struct{}

func (s *Settings) Clone() CISettings {
	return &Settings{}
}

func (s *Settings) Merge(other CISettings) {
}

这是一个非常简单的接口问题。在你的代码实现中,是 *Settings 实现了 CISettings 接口,而不是 Settings

你可以尝试像这样调用它:

func main() {
	sett := Settings{}
	ParseCISettings(&sett)
}

它告诉你不能使用 Settings 类型作为接口,因为该类型没有实现这个接口。错误出现在这里的 main 函数中:

ParseCISettings[Settings]()

你为指针 *Settings 实现了 Clone 和 Merge 两个方法!

func (s *Settings) Clone() CISettings {
	return &Settings{}
}

func (s *Settings) Merge(other CISettings) {}

你需要将其更改为值本身,或者更改在 main 函数中传递的泛型类型:

ParseCISettings[*Settings]()

在Go泛型中,当约束接口包含指针接收器方法时,类型参数T会被推断为指针类型。你的问题在于CISettings接口的Clone()方法返回的是CISettings接口类型,而不是具体的泛型类型T。

以下是修复后的代码:

package main

type CISettings interface {
	Clone() CISettings
	Merge(other CISettings)
}

type Settings struct{}

func (s *Settings) Clone() CISettings {
	return &Settings{}
}

func (s *Settings) Merge(other CISettings) {
}

// 修复:明确返回类型为T,并使用类型断言
func ParseCISettings[T CISettings](settings T) (T, error) {
	sett := settings.Clone()
	settings.Merge(sett)
	
	// 类型断言确保返回正确的类型
	if t, ok := sett.(T); ok {
		return t, nil
	}
	return settings, nil
}

func main() {
	sett := &Settings{}
	result, _ := ParseCISettings[*Settings](sett)
	_ = result
}

或者使用更简洁的类型参数约束:

package main

type CISettings[T any] interface {
	Clone() T
	Merge(other T)
}

type Settings struct{}

func (s *Settings) Clone() *Settings {
	return &Settings{}
}

func (s *Settings) Merge(other *Settings) {
}

func ParseCISettings[T CISettings[T]](settings T) (T, error) {
	sett := settings.Clone()
	settings.Merge(sett)
	return sett, nil
}

func main() {
	sett := &Settings{}
	result, _ := ParseCISettings[*Settings](sett)
	_ = result
}

关键点:

  1. Clone()返回CISettings接口,但函数签名要求返回具体的T类型
  2. 需要类型断言将接口转换回具体的泛型类型
  3. 或者重构接口定义,使Clone()返回具体的泛型类型T

编译器错误是因为类型不匹配:settings.Clone()返回的是CISettings接口类型,而函数签名要求返回T类型(在实例化时是*Settings)。

回到顶部