Is it leagle to partially implement an interface?


(Moon Wang) #1

Is it leagle to partially implement an interface?

type I1 interface {
F()
}

type T1 struct {
I1
}

func test( i1 I1) {
i1.F() // runtime error: invalid memory address or nil pointer dereference [recovered]
}

It’s kind of different from other languages. Is this behavior specified explicitly in the document?
Can anyone share the design thinking of this behavior?


(Curtis Allyn Green) #2

It’s not a compile error its a runtime error. An interface defines a signature that other types can implement. Your T1 struct can hold any type that has an F() function that takes no parameters. Here’s an example: https://play.golang.org/p/UeIoI5iXBEk


(Moon Wang) #3

thanks Green! I wonder if you are able to append more information to my modified question?


(Curtis Allyn Green) #4

I think it’s important to think about the interface simply as a signature. It basically defines the rule of what makes another object an acceptable form to work with.

Here is an example that better illustrates the point with what you were trying to begin with: https://play.golang.org/p/-ZVo1tBIyJ6

Also here is a link to the Tour of Go section on methods, it’s important to go through the whole section as it explains methods and interfaces in depth: https://tour.golang.org/methods/1

And finally, this article does a great job explaining the design intent of interfaces:


(Jakob Borg) #5

Implementing only part of an interface and delegating the rest to an embedded interface of the same type is perfectly valid. It’s just that in your example that delegated-to interface is nil.

For example, lets take net.Conn which is a fairly large interface. If I wanted a connection that counted bytes read from it I could implement it like this, without having to worry about the methods I don’t care about:

type countingConn struct {
  read int
  net.Conn
}

func (c *countingConn) Read(data []byte) (int, error) {
  n, err := c.Conn.Read(data)
  c.read += n
  return n, err
}

The new countingConn type is a net.Conn by way of having embedded one, overriding just one of the methods.

It’s also great for testing, where I can pass a type implementing the methods I know will be under test and embed an interface (which might be nil to prove they are not called) for the rest.