Classes in Golang. Another way to implement an interface

This is not another article on “Is Go an OOP Language?” I just want to show one simple technique that allowed me to quickly understand the idea of ​​interfaces in go and, in principle, the ideology of the language.

Let’s say we have a trivial task – to create a structure that implements the “Duck” interface, which includes three methods: fly, swim, quack. Conventionally, it will look like this:

type Duck interface {
  Fly() error
  Swim() error
  Quack(string) error
}

Next, let’s create a Goose structure:

type Goose struct {
  Name string
}

In typical OOP languages ​​like Java, we would simply write: class Goose implements Duck, after which all the methods of the Duck interface would have to be implemented in the Goose class. In golang, things are a little different. To force a structure to implement interface methods, we need to assign an instance of the structure to a variable of the interface type:

var whiteGoose Duck = Goose{Name: "White"}

This is a typical implementation of interfaces in golang as presented in official tutorial, and which, perhaps, everyone who has worked with interfaces in go has encountered. After such an assignment, we receive a warning that this structure does not have the methods of the Duck interface implemented.

Only after we have implemented all the interface methods in the structure, this message will disappear.

func (g Goose) Fly() {

}
func (g Goose) Swim() {

}
func (g Goose) Quack(sound string) {
  fmt.Println(sound)
}

This is the standard and most common implementation, but it has several disadvantages. First, we get a compilation error only when we try to assign an instance of a structure to an interface. But what if we’re not going to create instances? What if we write an SDK that will be used by users in the future at their discretion? Second, what if we want to make the structure private? Let’s say we want to hide the implementation of the methods, and to work in the client code, use only initialization and interfaces with a description of the signatures of the methods used. How can we achieve something more like class Goose implements Duck ?

To do this, we just need to create a constructor. Indeed, what prevents us from writing a function that will be responsible for initializing an object? And to force the structure to implement the methods we need, it is enough to specify our interface as the return value. Such a constructor would look something like this:

func NewGoose(name string) Duck {
  return goose{name}
}

And in the client code, we just have to call this constructor:

var greyGoose = NewGoose("Grey")

As a result, we have a structure with the described fields, methods and a full-fledged constructor for initialization – why is the classic class not familiar to most readers? 🙂

Of course, technically this is absolutely the same thing, but now the advantages that I mentioned are available to us, and also (from my own experience and looking at the developers who came to the project after me) such a constructor makes life much easier. Golang is a fairly new language with its own specifics, but nothing prevents you from using it as you like.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *