Go Interfaces
Interfaces in Go provide a way to specify the behavior of an object. They’re a powerful tool for achieving abstraction and polymorphism, allowing you to write more flexible and reusable code. Unlike some languages, interfaces in Go are implicitly satisfied. This means you don’t explicitly declare that a type implements an interface. If a type has the methods defined by the interface, it automatically implements it.
Defining an Interface
An interface is defined using the interface
keyword, followed by the interface name and a set of method signatures.
type Speaker interface {
Speak() string
}
This Speaker
interface defines a single method Speak()
which returns a string.
Implementing an Interface
Let’s create two types, Dog
and Cat
, that both implement the Speaker
interface:
type Dog struct {
name string
}
func (d Dog) Speak() string {
return "Woof! My name is " + d.name
}
type Cat struct {
name string
}
func (c Cat) Speak() string {
return "Meow! My name is " + c.name
}
Notice that neither Dog
nor Cat
explicitly states that it implements Speaker
. They simply define the Speak()
method with the correct signature.
Using Interfaces
The power of interfaces comes from the ability to use them as generic types. Here’s a function that accepts anything that implements the Speaker
interface:
func MakeSpeak(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
dog := Dog{name: "Fido"}
cat := Cat{name: "Whiskers"}
MakeSpeak(dog) // Output: Woof! My name is Fido
MakeSpeak(cat) // Output: Meow! My name is Whiskers
}
The MakeSpeak
function doesn’t care whether it’s given a Dog
, a Cat
, or any other type, as long as it implements the Speaker
interface.
Empty Interface
The empty interface interface{}
is a special case. It has no methods, meaning every type in Go implicitly implements it. This is useful when you want to write functions that can operate on values of any type.
func PrintAnything(v interface{}) {
fmt.Println(v)
}
func main() {
PrintAnything(5) // Output: 5
PrintAnything("hello") // Output: hello
PrintAnything(true) // Output: true
}
Type Assertions
When using the empty interface, you might need to determine the underlying type of a value. This is done using a type assertion:
func PrintType(v interface{}) {
if s, ok := v.(string); ok {
fmt.Println("It's a string:", s)
} else {
fmt.Println("It's not a string")
}
}
Interfaces in Go are a crucial part of the language, facilitating code reuse, flexibility, and strong typing. Understanding their implicit nature and versatile applications is key to writing effective Go programs.