soupdiver
soupdiver

Reputation: 3673

Hint needed for practical use of interfaces

I wanted to be 'clever' but for the moment I'm stuck :D

I have slices of different types and wrote a function to eliminate duplicates in these slices.

I created an interface which defines a function to return an identifier.

My function to eliminate duplicates is implemented against that interface.

But when trying to compile I get an error where I'm not totally sure how to solve this.

package main

type IDEntity interface {
    EntityID() int64
}

type Foobar struct {
    ID int64
}

func (s *Foobar) EntityID() int64 {
    return s.ID
}

func EliminateDuplicatesInSlice(sliceIn []*IDEntity) []*IDEntity {
    m := map[int64]bool{}

    for _, v := range sliceIn {
        if _, seen := m[v.EntityID()]; !seen {
            sliceIn[len(m)] = v
            m[v.EntityID()] = true
        }
    }
    // re-slice s to the number of unique values
    sliceIn = sliceIn[:len(m)]

    return sliceIn
}

func main() {
    foo1 := &Foobar{
        ID: 1,
    }

    foo2 := &Foobar{
        ID: 2,
    }

    foo3 := &Foobar{
        ID: 3,
    }

    testSlice := []*Foobar{foo1, foo2, foo2, foo3}

    EliminateDuplicatesInSlice(testSlice)
}

Output is:

go run test.go
# command-line-arguments
./test.go:19: v.EntityID undefined (type *IDEntity is pointer to interface, not interface)
./test.go:21: v.EntityID undefined (type *IDEntity is pointer to interface, not interface)
./test.go:45: cannot use testSlice (type []*Foobar) as type []*IDEntity in argument to EliminateDuplicatesInSlice

I'm most confused about (type *IDEntity is pointer to interface, not interface).

Can someone please clarify?

Upvotes: 0

Views: 72

Answers (1)

T. Claverie
T. Claverie

Reputation: 12246

Unlike struct, having a pointer to an interface is useless. Your interface must declare EntityID() int64, so if you have a variable a of type IDEntity, then you can do a.EntityID(). However, if you have a pointer to an interface, then you can't call its methods.

This is about the type of the receiver for your methods. In your example, *Foo implements IDEntity, but Foo doesn't. So, *Foo is an IDEntity, but Foo isn't.

About your code, you have two lines to fix:

  • Change the prototype of EliminateDuplicateInSlice to func EliminateDuplicatesInSlice(sliceIn []IDEntity) []IDEntity
  • Change the type of the slice you pass to this function from []*Foo to []IDEntity

Upvotes: 2

Related Questions