17

I would like to understand the interface type with a simple example of it's use in Go (Language).

I read the web documentation, but I don't get it.

Speccy
  • 694
  • 8
  • 30
  • Did you read this in the docs?? http://golang.org/doc/effective_go.html#interfaces_and_types. Also try this one http://diveintogo.blogspot.com/2010/03/classic-inheritance-in-go-lang.html – Justin Aug 12 '11 at 17:11
  • 1
    Yup, I read the docs... Thanks for the links – Speccy Aug 13 '11 at 03:44
  • Usage of interface in Go? Decouple code. See https://stackoverflow.com/a/62297796/12817546. Call a method “dynamically”. See https://stackoverflow.com/a/62336440/12817546. Access a Go package. See https://stackoverflow.com/a/62278078/12817546. Assign any value to a variable. See https://stackoverflow.com/a/62337836/12817546. –  Jul 10 '20 at 09:52

4 Answers4

49

The idea behind go interfaces is duck typing. Which simply translates into: If you look like a duck and quack like a duck then you are a duck. Meaning that if your object implements all duck's features then there should be no problem using it as a duck. Here is an example:

package main

import (
    "fmt"
)

type Walker interface {
    Walk() string
}

type Human string
type Dog string

func (human Human) Walk() string { //A human is a walker
    return "I'm a man and I walked!"
}

func (dog Dog) Walk() string { //A dog is a walker
    return "I'm a dog and I walked!"
}

//Make a walker walk
func MakeWalk(w Walker) {
    fmt.Println(w.Walk())
}

func main() {
    var human Human
    var dog Dog
    MakeWalk(human)
    MakeWalk(dog)
}

Here a Human is a Walker and a Dog is a Walker. Why? Because they both.. well... Walk. They both implement the Walk () string function. So this is why you can execute MakeWalk on them.

This is very helpful when you want different types to behave in the same manner. A practical example would be file type objects (sockets, file objects) - you need a Write and a Read function on all of them. Then you can use Write and Read in the same fashion independent of their type - which is cool.

Alex Plugaru
  • 2,209
  • 19
  • 26
  • 8
    Thanks! This is really what I wanted to know. Much clearer than in the go tutorial. – Speccy Aug 13 '11 at 03:52
  • What benefits interfaces give in context of golang? If i'm using interfaces for 2 objects, and my interface has 3 methods, does that mean my 2 objects should implement these 3 methods? – Avdept May 18 '15 at 18:18
  • @Avdept yes, you have to implement the same signature as the interface for your type. Not sure what you mean by benefit. – Alex Plugaru Jun 04 '15 at 14:15
2

Another working example showing the interaction between an interface and a structure

package main

import "fmt"

type Info interface {
Noofchar() int
Increment()
}

type Testinfo struct {
noofchar int     
}

func (x *Testinfo) Noofchar() int {
return x.noofchar
}
func (x *Testinfo) Increment() {
x.noofchar++
}

func main(){
var t Info = &Testinfo{noofchar:1}
fmt.Println("No of char ",t.Noofchar())
t.Increment()
fmt.Println("No of char ",t.Noofchar())
}
Worlock
  • 406
  • 1
  • 4
  • 15
0

To add to the excellent answer by @AlexPlugaru here and by @NickCraig-Wood at https://stackoverflow.com/a/18854285/12817546.

package main

import . "fmt"

func main() {
    cat("Bird").Eat()      // Bird
    eater.Eat(cat("Milk")) // Milk
    Break(cat("Fish"))     // Fish
    Lunch().Eat()          // Mice
    Tea(true)           // Bird
}

type cat string
type eater interface{ Eat() }

func (c cat) Eat()  { Println(c) }
func Break(e eater) { e.Eat() }
func Lunch() eater  { return cat("Mice") }
func Tea(b bool) {
    if b {
        cat("Bird").Eat()
    }
}

Methods on a struct or any other concrete type are resolved statically. See cat("Bird").Eat() and eater.Eat(cat("Milk")). The only way to have dynamically dispatched methods is through an interface. See Break(cat("Fish")) and Lunch().Eat(), http://www.golangbr.org/doc/faq#How_do_I_get_dynamic_dispatch_of_methods.

Tea(true) calls a method dynamically without using an interface. See https://talks.golang.org/2014/taste.slide#19. But interfaces—by design and convention—encourage us to write composable code. See https://talks.golang.org/2014/go4gophers.slide#21.

The result: simple pieces connected by small interfaces. See https://talks.golang.org/2012/chat.slide#5. Better to have many small simple things than one big complex thing. See https://talks.golang.org/2014/go4gophers.slide#24.

You can also hide anything in a private package and just expose specific types, interfaces, and factory functions. See Break(cat("Fish")) and Lunch().Eat(), https://code.tutsplus.com/tutorials/lets-go-object-oriented-programming-in-golang--cms-26540

  • Decouple code with an interface. See https://stackoverflow.com/a/62297796/12817546. Call a method “dynamically”. See https://stackoverflow.com/a/62336440/12817546. Access a Go package. See https://stackoverflow.com/a/62278078/12817546. Assign any value to a variable. See https://stackoverflow.com/a/62337836/12817546. –  Jul 10 '20 at 09:18
0

In this example, I'm using the interface to demonstrate how to achieve polymorphism in Golang.

package main 


import(
    "fmt"
    "math"
)

func main(){
    rect := Rectangle{20,50}
    cir := Circle{2}

    //According to object you passed in getArea method, 
    // it will change the behaviour and that is called Polymorphism.
    fmt.Println("Area of Rectangle =",getArea(rect))
    fmt.Println("Area of Circle =",getArea(cir))

}

//Interface Shape with one area method
type Shape interface{
     area() float64
}

//Creating Rectangle and Circle type using struct 
type Rectangle struct{
    height float64
    width float64
}

type Circle struct{
    radius float64
}

//Receiver function, which implements struct's area methods
func(r Rectangle) area() float64{
    return r.height * r.width
}

func(c Circle) area() float64{
    return math.Pi * math.Pow(c.radius,2)
}

//passing interface as arguments, which can calculate shape of any mentioned type
//All the struct are tied together because of the Interface.
func getArea(shape Shape) float64{
    return shape.area()
}
Alok Tripathi
  • 874
  • 10
  • 9