Interfaces

suggest change

An interface defines a set of methods on a type.

Interfaces are used to abstract behavior.

For example: a standard library defines io.Reader interface:

type Reader interface {
    Read(d []byte) (int, error)
}

Most functions that operate on streams of binary data (e.g. json decoder) take io.Reader as a source of data. That way we can implement Reader interface for physical files, bytes in memory, network connections and have json.Decode work on all those sources.

Here’s how to define and implement a simple interface:

// Stringer is an interface with a single method
type Stringer interface {
	String() string
}

// User struct that implements Stringer interface
type User struct {
	Name string
}

func (u *User) String() string {
	return u.Name
}

// Any type can implement an interface. Here we create
// an alias of int type an implement Stringer interface

type MyInt int

func (mi MyInt) String() string {
	return strconv.Itoa(int(mi))
}

// printTypeAndString accepts an interface. 's' can be any value
// that implements Stringer interface
func printTypeAndString(s Stringer) {
	fmt.Printf("%T: %s\n", s, s)
}

func main() {
	u := &User{Name: "John"}
	printTypeAndString(u)

	n := MyInt(5)
	printTypeAndString(n)
}
*main.User: John
main.MyInt: 5

Unlike most other languages, interfaces are satisfied implicitly.

We don’t have to explicitly declare that struct User implements interface Stringer.

Interfaces can only contain methods, not data. You can use struct embedding if you want to re-use both methods and data.

You can only define methods on types defined in the same package. We had to define type alias MyInt because we can’t add methods to built-int type int.

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents