在具有泛型变量的结构体上的方法

huangapple go评论93阅读模式
英文:

Method on struct with generic variable

问题

我有以下使用泛型的代码。我知道不能在方法中使用泛型,但可以在类型中使用。从技术上讲,我的代码符合这两个限制,但仍然出现错误。

./main.go:12:9: 无法使用未实例化的泛型类型 GenericCacheWrapper[T any]

实例化在 main 函数的第一行。

有没有办法实现这个?这可能被认为是 Golang 的一个 bug 吗?

package main

import (
	"encoding/json"
	"fmt"
)

type GenericCacheWrapper[T any] struct {
	Container T
}

func (c GenericCacheWrapper) MarshalBinary() (data []byte, err error) {
	return json.Marshal(c.Container)
}

func (c GenericCacheWrapper) UnmarshalBinary(data []byte) error {
	return json.Unmarshal(data, &c.Container)
}

func main() {
	wrapper := GenericCacheWrapper[int]{Container: 4}
	data, err := wrapper.MarshalBinary()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}

https://go.dev/play/p/9sWxXYmAcUH

英文:

I have following code that uses generics. I know that one can't use generics with methods, but can with types. Technically, my code complies with both restrictions, but still I get en error

./main.go:12:9: cannot use generic type GenericCacheWrapper[T any] without instantiation

The instantiation is on the first line of main function.
Is there any way to achieve this? May this be considered a Golang bug?


import (
	"encoding/json"
	"fmt"
)

type GenericCacheWrapper[T any] struct {
	Container T
}

func (c GenericCacheWrapper) MarshalBinary() (data []byte, err error) {
	return json.Marshal(c.Container)
}

func (c GenericCacheWrapper) UnmarshalBinary(data []byte) error {
	return json.Unmarshal(data, &c.Container)
}

func main() {
	wrapper := GenericCacheWrapper[int]{Container: 4}
	data, err := wrapper.MarshalBinary()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}

https://go.dev/play/p/9sWxXYmAcUH

答案1

得分: 4

你只需要在GenericCacheWrapper的末尾添加[T],或者如果你想明确表示在函数中实际上没有使用T,则添加[_]

package main

import (
	"encoding/json"
	"fmt"
)

type GenericCacheWrapper[T any] struct {
	Container T
}

func (c GenericCacheWrapper[T]) MarshalBinary() (data []byte, err error) {
	return json.Marshal(c.Container)
}

func (c GenericCacheWrapper[T]) UnmarshalBinary(data []byte) error {
	return json.Unmarshal(data, &c.Container)
}

func main() {
	wrapper := GenericCacheWrapper[int]{Container: 4}
	data, err := wrapper.MarshalBinary()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}

这个规则在语言规范中定义:

一个泛型类型也可以有与之关联的方法。在这种情况下,方法的接收者必须声明与泛型类型定义中相同数量的类型参数。

但是背后的原因并不是很清楚,可能是为了使编译器/类型检查器的实现更容易。

相关链接:https://stackoverflow.com/questions/71274361/go-error-cannot-use-generic-type-without-instantiation

英文:

You just have to add [T] to the end of GenericCacheWrapper or [_] if you want to make it clear that you are not actually using T in the functions.

package main

import (
	"encoding/json"
	"fmt"
)

type GenericCacheWrapper[T any] struct {
	Container T
}

func (c GenericCacheWrapper[T]) MarshalBinary() (data []byte, err error) {
	return json.Marshal(c.Container)
}

func (c GenericCacheWrapper[T]) UnmarshalBinary(data []byte) error {
	return json.Unmarshal(data, &c.Container)
}

func main() {
	wrapper := GenericCacheWrapper[int]{Container: 4}
	data, err := wrapper.MarshalBinary()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}

This rule is defined in the language spec:

> A generic type may also have methods associated with it. In this case, the method receivers must declare the same number of type parameters as present in the generic type definition.

But the reason behind this isn't very clear, perhaps to make implementation of the compiler/type checking easier.

Related: https://stackoverflow.com/questions/71274361/go-error-cannot-use-generic-type-without-instantiation

huangapple
  • 本文由 发表于 2022年4月19日 21:04:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/71925447.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定