Go doesn't have classes, but it does have methods. Methods are functions that are associated with a specific type. They allow you to define behavior for your types, similar to how methods work in object-oriented programming languages.
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
Compare it to the CalculatePerimeter
function we created earlier. The Area
method is associated with the Rectangle
type and can be called on any instance of Rectangle
. It's no longer need an explicit parameter to pass the rectangle instance; instead, it uses the input r
to access the fields of the rectangle.
Methods is just a function with a special input argument. The input is the instance of the type on which the method is called. It allows you to access the fields and methods of that instance. Besides only accessing value like code above, you can also declare methods on pointer receivers. This is useful when you want to modify the receiver or avoid copying large structs. The syntax is similar, but you use a pointer type for the receiver.
You can also declare methods on non-struct types. Let's demonstrate this with a string
type. The strings
package in Go provides many methods for manipulating strings already, such as Contains
, Index
, and ToUpper
. You can also define your own methods on the string
type if the need arises. The condition is that you need to define a new type based on the string
type, and then you can define methods on that new type.
An interface is a type that defines a set of methods. It allows you to specify a contract that types must adhere to. Interfaces are a powerful feature in Go, enabling polymorphism and code reuse. You can define an interface using the interface
keyword, followed by a list of method signatures.
type Shape interface {
Area() float64
}
In the code above, we define an interface named Shape
with a single method Area
. Any type that implements this method can be considered a Shape
. This allows you to write functions that accept any type that implements the Shape
interface.
The empty interface interface{}
is a special case in Go. It can hold values of any type, making it a powerful tool for writing generic code. Since all types implement at least zero methods, the empty interface can be used to accept any value.
var i interface{}
i = 42
i = "Hello"
i = []int{1, 2, 3}
A value of an interface type can hold any value that implements the methods defined in the interface. This allows you to write functions that can work with different types without knowing their concrete types at compile time.
In the code above, the PrintArea
function accepts a parameter of type Shape
. This demonstrates polymorphism in Go - the ability to process objects differently depending on their data type or class. Any type that implements the Area
method can be passed to this function, regardless of its concrete implementation. The function doesn't need to know whether it's working with a rectangle, circle, or any other shape; it only cares that the object can calculate its area.
This polymorphic behavior allows you to write more flexible, maintainable code that's decoupled from specific implementations. You can add new shapes like triangles or hexagons later without modifying the existing PrintArea
function, as long as they implement the Area
method. This is a powerful feature for creating extensible systems where components can vary independently.
In Go, interfaces are implemented implicitly - a type automatically satisfies an interface if it has all the required methods. Unlike other languages, Go doesn't use an "implements" keyword or any explicit declaration. This design creates a clean separation between interface definitions and their implementations, allowing types to implement interfaces from any package without prior coordination or planning.
Type assertion is a way to retrieve the concrete value from an interface. You can use the syntax value, ok := i.(T)
to assert that the interface i
holds a value of type T
. If the assertion is successful, ok
will be true, and value
will hold the concrete value. If the assertion fails, ok
will be false, and value
will be the zero value of type T
.
The concept of interface is a bit tricky. You can read more about it in the Interface Explained by Alex Edwards; a well-known Go developer and educator, and his blog is a great resource for learning Go. You can also check out the Go Blog for more articles and tutorials on Go programming in which you might encounter articles that can help you understand the concept of interface better.