Interface Basics
type Name interface {
Method1(param type) returnType
Method2()
}
Defining an Interface
An interface type lists a set of method signatures. It doesn't provide any implementation itself -- it's purely a contract describing what a type must be able to do.
Example: Defining an Interface
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// Define an interface named Shape (a set of method signatures)
type Shape interface {
Area() float64
}
// Define a struct type named Circle
type Circle struct {
Radius float64
}
// Define the method Area on type Circle
func (c Circle) Area() float64 {
// Send 3.14159 * c.Radius * c.Radius back to the caller
return 3.14159 * c.Radius * c.Radius
}
// main is where the program starts running
func main() {
// Declare Shape and set it to Circle{Radius: 2}
var s Shape = Circle{Radius: 2}
fmt.Println(s.Area())
}
Login to try C/C++/Java/PHP code in the editor
Implicit Satisfaction
Unlike languages where a type must explicitly declare which interfaces it implements, Go decides automatically: if a type has methods matching an interface's signatures, it satisfies that interface, with no declaration needed.
Example: Implicit Satisfaction
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// Define an interface named Greeter (a set of method signatures)
type Greeter interface {
Greet() string
}
// Define a struct type named English
type English struct{}
func (English) Greet() string { return "Hello" }
// Define a struct type named Spanish
type Spanish struct{}
func (Spanish) Greet() string { return "Hola" }
// main is where the program starts running
func main() {
// Short declaration: create greeters and infer the type
greeters := []Greeter{English{}, Spanish{}}
// Loop over greeters; the blank identifier _ ignores the index
for _, g := range greeters {
fmt.Println(g.Greet())
}
}
Login to try C/C++/Java/PHP code in the editor
Why Small Interfaces Win
Because satisfying an interface only requires having the right methods, small interfaces (often a single method) are easy for many different types to satisfy, making code more flexible and reusable -- this is why io.Reader and io.Writer, each with one method, are so central to Go's standard library.
Example: Why Small Interfaces Win
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// Define an interface named Stringer (a set of method signatures)
type Stringer interface {
String() string
}
type Money int
// Define the method String on type Money
func (m Money) String() string {
// Sprintf builds a formatted string instead of printing it
return fmt.Sprintf("$%d", m)
}
// main is where the program starts running
func main() {
// Declare Stringer and set it to Money(50)
var s Stringer = Money(50)
// Print the values followed by a newline
fmt.Println(s.String())
}
Login to try C/C++/Java/PHP code in the editor
- Expecting to explicitly declare 'implements InterfaceName' like Java -- Go interfaces are satisfied implicitly by matching methods.
- Defining an interface with too many methods, making it hard for types to satisfy -- idiomatic Go favors small, focused interfaces.
- Assuming an interface value with a concrete type set is directly comparable to that concrete value with == in every case, without considering nil interface subtleties.
- An interface defines a set of method signatures a type must implement to satisfy it.
- Go interfaces are satisfied implicitly -- there's no implements keyword.
- Any type with the right methods automatically satisfies an interface, even ones you didn't write.
- Idiomatic Go favors small interfaces, often with just one or two methods.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: