Best practices for Go language-Go interfaces
Original connection:/golang/golang-interfaces/
Interfaces in Go allow us to temporarily treat different types as the same data type, because both types implement the same behavior. They are at the heart of the Go programmer toolbox and are often used incorrectly by new Go developers, resulting in unreadable and often errors.
What is the interface in Golang
In Go, an interface is a custom type that other types are able to implement, which gives Go developers a powerful way to use abstraction. Interfaces are named collections of method signatures, and when other types implement all the required methods, they implicitly implement the interface.
In Go, interfaces are custom types that other types can implement, which provides Go developers with a powerful way to use abstraction.Interfaces are collections of method signatures that implicitly implement interfaces when other types implement all required methods.
For example, in Goerrors
It's the interface, standarderror
The interface is simple, a type should be considered aserror
, all you need to do is define aError ()
Method, which does not accept any arguments and returns a string.
type error interface { Error() string }
mistakeerror
The simplicity makes writing logs and metrics implementation easier. Let's define a structure that represents network problems:
type networkProblem struct { message string code int }
Then we can define an Error() method:
func (np networkProblem) Error() string { return ("network error! message: %s, code: %v", , ) }
Now we can use it anywhere we accept the errornetworkProblem
An instance of struct.
func handleErr(err error) { (()) } np := networkProblem{ message: "we received a problem", code: 404, } handleErr(np) // prints "network error! message: we received a problem, code: 404"
Best practices for writing interfaces
Writing a clean interface is difficult. Frankly, you're dealing with abstractions in your code any time, and simplicity can quickly turn into complexity if you're not careful. Let's review and keepinterfaces
Some rules of thumb for neatness.
- Keep interfaces small Keep interfaces small enough
- Interfaces should have no knowledge of satisfying types
- Interfaces are not classes
1. Keep interfaces small enough
If there is only one piece of advice that you take away from this article, make it this: keep interfaces small! Interfaces are meant to define the minimal behavior necessary to accurately represent an idea or concept.
If you only get one piece of advice from this article, it is: Keep the interface smaller!Interfaces mean the definition of the minimum behavior required to accurately represent an idea or concept.
Below is a large interface standardExample of HTTP package, it is a good example of defining the minimum behavior:
type File interface { Readdir(count int) ([], error) Stat() (, error) }
Any type that satisfies the interface’s behaviors can be considered by the HTTP package as a File. This is convenient because the HTTP package doesn’t need to know if it’s dealing with a file on disk, a network buffer, or a simple []byte.
Any type that satisfies the behavior of the interface can be treated as an HTTP packageFile
. This is convenient because the HTTP package does not need to know whether it is processing files on disk, network buffers, or[]byte
。
2. Interfaces Should Have No Knowledge of Satisfying Types
An interface should define what is necessary for other types to classify as a member of that interface. They shouldn’t be aware of any types that happen to satisfy the interface at design time.
An interface should define what other types are necessary for as members of that interface. They should not know any type that occurs to satisfy the interface when designing.
For example, suppose we are building an interface to describe the necessary constituent elements to define a car.
type car interface { Color() string Speed() int IsFiretruck() bool }
Color() and Speed() make perfect sense, they are methods confined to the scope of a car. IsFiretruck() is an anti-pattern. We are forcing all cars to declare whether or not they are firetrucks. In order for this pattern to make any amount of sense, we would need a whole list of possible subtypes. IsPickup(), IsSedan(), IsTank()… where does it end??
Color()
andSpeed()
Very reasonable, they are ways to limit the scope of the car.IsFiretruck ()
It is an anti-pattern. We are forcing all cars to declare whether they are fire trucks or not. To make this pattern any sense, we need a complete list of possible subtypes. IsPickup () , IsSedan () , IsTank () … Where does it end?
Instead, the developer should have relied on the native functionality of type assertion to derive the underlying type when given an instance of the car interface. Or, if a sub-interface is needed, it can be defined as:
Instead, when given an instance of a car interface, the developer should rely on the native functionality of the type assertion to derive the underlying type. Alternatively, if a subinterface is required, it can be defined as:
type firetruck interface { car HoseLength() int }
It inherits the methods required by the car and adds an additional method required to make the car a fire truck.
3. The interface is not a class
- Interfaces are not classes, they are slimmer. Interfaces are not classes, they are smaller
- Interfaces don’t have constructors or deconstructors that require that data is created or destroyed.
- Interfaces aren’t hierarchical by nature, though there is syntactic sugar to create interfaces that happen to be supersets of other interfaces.
- Interfaces define function signatures, but not underlying behavior. Making an interface often won’t The interface defines function signatures, but does not define underlying behavior. Making an interface does not usually not interfere with your code in terms of structure methods. For example, if the five types satisfy the error interface, they all require their own version of the Error() function.
More information about the interface
Empty interface
No method is specified for an empty interface, so every type in Go implements an empty interface.
interface{}
It’s for this reason that developers sometimes use a map[string]interface{} to work with arbitrary JSON data, although I recommend using anonymous structs instead where possible.
For this reason, developers sometimes usemap[string]interface{}
To handle anyJSON data, although I recommend using it where possibleAnonymous structure。
Zero value of an interface
Interfaces can be nil, in fact, it’s their zero value. That’s why when we check for errors in Go, we’re always checking if err != nil, because err is an interface.
The interfaces can be nil, in fact, this is their zero value. This is why when we check for errors in Go, we always checkerr != nil
,becauseerr
It is an interface.
Interface on pointer
It’s a common “gotcha” in Go to implement a method on a pointer type and expect the underlying type to implement the interface, it doesn’t work like that.
In Go, it is a common "get it" to implement a method on a pointer type and expect the underlying type to implement an interface, and it doesn't work that way.
type rectangle interface { height() int width() int } type square struct { length int } func (sq *square) width() int { return } func (sq *square) height() int { return }
Though you may expect it to, in this example the square type does not implement the rectangle interface. The *square type does. If I wanted the square type to implement the rectangle interface I would just need to remove the pointer receivers.
While you may want to do this, in this example, the square type does not implement a rectangular interface. It uses*square
. If I want the square type to implement a rectangular interface, I just need to remove the pointer receiver.
type rectangle interface { height() int width() int } type square struct { length int } func (sq square) width() int { return } func (sq square) height() int { return }
This is the end of this article about the best practices of Go interface interface. For more information about Go interface interface interface, please search for my previous articles or continue browsing the following related articles. I hope everyone will support me in the future!