英文:
Go: function callback returning implementation of interface
问题
我有一个处理资源解析的系统(将名称匹配到文件路径等)。它解析文件列表,然后保留指向返回接口实现实例的函数的指针。
更容易通过示例来说明。
resource.go
package resource
var (
tex_types map[string]func(string) *Texture = make(map[string]func(string) *Texture)
shader_types map[string]func(string) *Shader = make(map[string]func(string) *Shader)
)
type Texture interface {
Texture() (uint32, error)
Width() int
Height() int
}
func AddTextureLoader(ext string, fn func(string) *Texture) {
tex_types[ext] = fn
}
dds.go
package texture
type DDSTexture struct {
path string
_tid uint32
height uint32
width uint32
}
func NewDDSTexture(filename string) *DDSTexture {
return &DDSTexture{
path: filename,
_tid: 0,
height: 0,
width: 0,
}
}
func init() {
resource.AddTextureLoader("dds", NewDDSTexture)
}
DDSTexture
完全实现了 Texture
接口,我只是省略了那些函数,因为它们很大并且不是我问题的一部分。
在编译这两个包时,出现以下错误:
resource\texture\dds.go:165: cannot use NewDDSTexture (type func(string) *DDSTexture) as type func (string) *resource.Texture in argument to resource.AddTextureLoader
我该如何解决这个问题,或者这是接口系统的一个错误吗?再次强调:DDSTexture
完全实现了 resource.Texture
。
英文:
I got a system that handles the resolving of resources (matching a name to a file path, etc). It parses a list of files and then keeps pointers to a function that returns an instance of an implementation of an interface.
It's easier to show.
resource.go
package resource
var (
tex_types map[string]func(string) *Texture = make(map[string]func(string) *Texture)
shader_types map[string]func(string) *Shader = make(map[string]func(string) *Shader)
)
type Texture interface {
Texture() (uint32, error)
Width() int
Height() int
}
func AddTextureLoader(ext string, fn func(string) *Texture) {
tex_types[ext] = fn
}
dds.go
package texture
type DDSTexture struct {
path string
_tid uint32
height uint32
width uint32
}
func NewDDSTexture(filename string) *DDSTexture {
return &DDSTexture{
path: filename,
_tid: 0,
height: 0,
width: 0,
}
}
func init() {
resource.AddTextureLoader("dds", NewDDSTexture)
}
DDSTexture
fully implements the Texture
interface, I just omitted those functions because they're huge and not part of my question.
When compiling these two packages, the following error arises:
resource\texture\dds.go:165: cannot use NewDDSTexture (type func(string) *DDSTexture) as type func (string) *resource.Texture in argument to resource.AddTextureLoader
How would I resolve this problem, or is this a bug with the interface system? Just reiterating: DDSTexture
fully implements resource.Texture
.
答案1
得分: 5
是的,DDSTexture
完全实现了resource.Texture
。
但是,命名类型NewDDSTexture(type func(string)*DDSTexture)
与无名类型func(string)*resource.Texture
不同:它们的**类型标识**不匹配:
> 如果两个函数类型具有相同数量的参数和结果值,相应的参数和结果类型相同,并且两个函数都是可变参数或都不是,则它们是相同的。参数和结果名称不需要匹配。
>
> 命名类型和无名类型始终不同。
即使为函数定义了命名类型,也无法工作:
type FuncTexture func(string) *Texture
func AddTextureLoader(ext string, fn FuncTexture)
无法将NewDDSTexture(类型为func(string)`*DDSTexture`)作为参数传递给AddTextureLoader中的类型`FuncTexture`
在这里,结果值类型不匹配DDSTexture
与resource.Texture
:
即使一个实现了另一个的接口,它们的底层类型仍然不同):你不能将一个赋值给另一个。
你需要让NewDDSTexture()
返回Texture
(不是指针,因为它是一个接口)。
func NewDDSTexture(filename string) Texture
参见这个示例。
正如我在“在golang中将结构指针转换为接口指针”中解释的那样,通常不需要指向接口的指针。
英文:
Yes, DDSTexture
fully implements resource.Texture
.
But the named type NewDDSTexture (type func(string) *DDSTexture)
isn't the same as the unamed type func (string) *resource.Texture
: their type identity doesn't match:
> Two function types are identical if they have the same number of parameters and result values, corresponding parameter and result types are identical, and either both functions are variadic or neither is. Parameter and result names are not required to match.
>
> A named and an unnamed type are always different.
Even if you defined a named type for your function, it wouldn't work:
type FuncTexture func(string) *Texture
func AddTextureLoader(ext string, fn FuncTexture)
cannot use NewDDSTexture (type func(string) `*DDSTexture`)
as type `FuncTexture` in argument to `AddTextureLoader`
Here, the result value type don't match DDSTexture
vs. resource.Texture
:
Even if one implements the interface of the other, their underlying type still differ): you cannot assign one to the other.
You need for NewDDSTexture()
to return Texture
(no pointer, since it is an interface).
func NewDDSTexture(filename string) Texture
See this example.
As I explained in "Cast a struct pointer to interface pointer in golang", you usually don't need a pointer to an interface.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论