Golang. Encapsulation via interfaces

How we can use all power of encapsulation in golang?
To achieve that we can use so-called interfaces. Below you can see one example of that approach. Our Notifier interface is public and the notifier struct is private. It means that all external clients will be able to use notifiers package publicly only via public interface while other things are hidden. So it’s the power of using encapsulation.

package notifiers

import "fmt"

type Notifier interface {
	Send()
}

type notifier struct {
	client string
}

func NewNotifier(client string) Notifier {
	return &notifier{client: client}
}

func (n *notifier) Send() {
	fmt.Printf("Notifier sent notification via client: %v\n", n.client)
}

package main

import "notifiers"

func main() {
	notifiers.NewNotifier("html client").Send()
}
But what if we need to get access to the state of returning struct instance from the package instead of being able to work only with the public interface? In that case, we can change the return type in the signature of the public constructor NewNotifier.

func NewNotifier(client string) *notifier {
	return &notifier{client: client}
}
And it will be workable. But if you try to run golint then you will get the next error message:

exported func NewNotifier returns unexported type *notifier, which can be annoying to use (golint)


There is only one thing we can do to fix it. This is to make the return struct public.

package notifiers

import "fmt"

type Notifier struct {
	client string
}

func NewNotifier(client string) *Notifier {
	return &Notifier{client: client}
}

func (n *Notifier) Send() {
	fmt.Printf("Notifier sent notification via client: %v\n", n.client)
}
As you can see, the Notifier interface had to be removed. Thus, we threw more details out. In my opinion, it’s a less abstract approach. Despite this, we can still use encapsulation both at the package and at the level of public structure (by using private fields).

No comments :

Post a Comment