Interface

Interface is a reference type which contains some method definitions. Any type which implements all the methods defined by a reference type will satisfy this interface type automatically. Through interface, you can approach object-oriented programming. Check the following example:

  1. package main
  2. import "fmt"
  3. type Foo interface {
  4. foo()
  5. }
  6. type A struct {
  7. }
  8. func (a A) foo() {
  9. fmt.Println("A foo")
  10. }
  11. func (a A) bar() {
  12. fmt.Println("A bar")
  13. }
  14. func callFoo(f Foo) {
  15. f.foo()
  16. }
  17. func main() {
  18. var a A
  19. callFoo(a)
  20. }

The running result is:

  1. A foo

Let’s analyze the code detailedly:

(1)

  1. type Foo interface {
  2. foo()
  3. }

The above code defines a interface Foo which has only one method: foo().

(2)

  1. type A struct {
  2. }
  3. func (a A) foo() {
  4. fmt.Println("A foo")
  5. }
  6. func (a A) bar() {
  7. fmt.Println("A bar")
  8. }

struct A has 2 methods: foo() and bar(). Since it already implements foo() method, it satisfies Foo interface.

(3)

  1. func callFoo(f Foo) {
  2. f.foo()
  3. }
  4. func main() {
  5. var a A
  6. callFoo(a)
  7. }

callFoo requires a variable whose type is Foo interface, and passing A is OK. The callFoo will use A‘s foo() method, and “A foo“ is printed.

Let’s change the main() function:

  1. func main() {
  2. var a A
  3. callFoo(&a)
  4. }

This time, the argument of callFoo() is &a, whose type is *A. Compile and run the program, you may find it also outputs: “A foo“. So *A type has all the methods which A has. But the reverse is not true:

  1. package main
  2. import "fmt"
  3. type Foo interface {
  4. foo()
  5. }
  6. type A struct {
  7. }
  8. func (a *A) foo() {
  9. fmt.Println("A foo")
  10. }
  11. func (a *A) bar() {
  12. fmt.Println("A bar")
  13. }
  14. func callFoo(f Foo) {
  15. f.foo()
  16. }
  17. func main() {
  18. var a A
  19. callFoo(a)
  20. }

Compile the program:

  1. example.go:26: cannot use a (type A) as type Foo in argument to callFoo:
  2. A does not implement Foo (foo method has pointer receiver)

You can see also *A type has implemented foo() and bar() methods, it doesn’t mean A type has both methods by default.

BTW, every type satisfies the empty interface: interface{}.

The interface type is actually a tuple which contains 2 elements: <type, value>, type identifies the type of the variable which stores in the interface while value points to the actual value. The default value of an interface type is nil, which means both type and value are nil: <nil, nil>. When you check whether an interface is empty or not:

  1. var err error
  2. if err != nil {
  3. ...
  4. }

You must remember only if both type and value are nil means the interface value is nil.

Reference:
The Go Programming Language.