2

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 Answer 1

5

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I tried for NewDDSTexture() to return a Texture already, but that results in: *resource.Texture is pointer to interface, not interface.
@JesseBrands right. I have removed the pointer from my answer, and added a link to stackoverflow.com/a/27178682/6309, where I explain that you usually don't need/use a pointer to an interface.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.