So trying out go for the first time today and keep running into an error to do with interfaces, I guess I don't understand them correctly. Ive tried looking around for an answer but the terminology that I'm used to is a little different from other languages so I can't piece it together. As practice I decided to implement a very simple linked list but the error I recieve is:
type INode* is pointer to interface, not interface
when calling .setNext(node *Inode)
What is the reason behind this? what piece of information am I missing with interfaces?
Heres the incomplete implementation:
package main
type object interface{}
type INode interface {
GetData() object
GetNext() *INode
setNext(node *INode)
}
type ILinkedList interface {
Link(node *INode)
Unlink(node *INode)
CurrentLength() int
RemoveAt(idx int)
}
type Node struct {
data object
next *INode
}
func (n *Node) GetData() object {
return n.data
}
func (n *Node) GetNext() *INode {
return n.next
}
func (n *Node) setNext(node *INode) {
n.next = node
}
type LinkedList struct {
cur *INode
last *INode
length int
}
func (l *LinkedList) Link(node *INode) {
if l == nil {
return
}
if l.cur == nil {
l.cur = node
l.last = node
} else {
l.last.setNext(node)
l.last = node
}
l.length = l.length + 1
}
This is because in Go, an interface is just a specification of behavior. This behavior can be implemented with either a pointer receiver or a value receiver. The interface doesn't care which one is ultimately used, just as long as it fulfills the interface contract.
See this example: https://play.golang.org/p/0AaBhB1MHBc
type I interface {
M()
}
type T struct {
S string
}
func (t T) M(){
fmt.Println("T.M fired");
}
type S struct {
S string
}
func (s *S) M(){
fmt.Println("*S.M fired");
}
func RunM(i I){
i.M()
}
func main() {
test1 := T{}
test2 := &S{}
RunM(test1)
RunM(test2)
fmt.Println("Hello, playground")
}
Both pointers to the S type and T types implement the interface I, and can be passed in to any func requiring an I. The interface doesn't care if it's a pointer or not.
You can read up about pointer receivers here: https://tour.golang.org/methods/4
I thought I would post a reference for those visiting in the future that have the same issue regarding pointers to interfaces:
When should I use a pointer to an interface?
Almost never. Pointers to interface values arise only in rare, tricky situations involving disguising an interface value's type for delayed evaluation.
It is however a common mistake to pass a pointer to an interface value to a function expecting an interface. The compiler will complain about this error but the situation can still be confusing, because sometimes a pointer is necessary to satisfy an interface. The insight is that although a pointer to a concrete type can satisfy an interface, with one exception a pointer to an interface can never satisfy an interface.
Consider the variable declaration,
var w io.Writer The printing function fmt.Fprintf takes as its first argument a value that satisfies io.Writer—something that implements the canonical Write method. Thus we can write
fmt.Fprintf(w, "hello, world ") If however we pass the address of w, the program will not compile.
fmt.Fprintf(&w, "hello, world ") // Compile-time error. The one exception is that any value, even a pointer to an interface, can be assigned to a variable of empty interface type (interface{}). Even so, it's almost certainly a mistake if the value is a pointer to an interface; the result can be confusing.