Export interfaces instead of structs from golang packages - go

Below you can find three different ways of calling a method Name() of a customer struct. The result is exactly the same but each one of the three package exports different things:
package main
import (
"customer1"
"customer2"
"customer3"
"fmt"
"reflect"
)
func main() {
c1 := customer1.NewCustomer("John")
fmt.Println(c1.Name())
c2 := customer2.NewCustomer("John")
fmt.Println(c2.Name())
c3 := customer3.NewCustomer("John")
fmt.Println(c3.Name())
}
Output
John
John
John
customer1.go (Export Customer struct and Name() method)
package customer1
type Customer struct {
name string
}
func NewCustomer(name string) * Customer{
return &Customer{name: name}
}
func (c *Customer) Name() string {
return c.name
}
customer2.go (Do not export customer struct. Export only Name() method)
package customer2
type customer struct {
name string
}
func NewCustomer(name string) *customer {
return &customer{name: name}
}
func (c *customer) Name() string {
return c.name
}
customer3.go (Do not export customer struct. Export Customer Interface)
package customer3
type Customer interface {
Name() string
}
type customer struct {
name string
}
func NewCustomer(name string) Customer {
return &customer{name: name}
}
func (c *customer) Name() string {
return c.name
}
My question is which approach you would recommend and why? Which is better in terms of extensibility and maintainability? Which one you would use for a large project?
It seems that customer3 approach is officially discouraged (// DO NOT DO IT!!!) as you can read here https://github.com/golang/go/wiki/CodeReviewComments#interfaces

Interfaces in Go work (and are used) a bit differently that what you'd expect if you come from other languages such as Java.
In Go, the object implementing the interface does not need to explicitly say it implements it.
That has subtle ramifications, such as the consumer of a type being able to decouple from the implementation even if the implementing side did not bother (or think about) creating an interface in the first place.
So, the idiomatic way in Go would be to use a variation of your first approach.
You'd define customer1.go exactly as you did (so implementation of the type is as simple as possible).
Then if necessary you can de-couple in the consumer (your main package in this case) by defining an interface there:
type Customer interface {
Name() string
}
func main() {
var c1 Customer
c1 := customer1.NewCustomer("John")
fmt.Println(c1.Name())
}
That way, your main implementation can work with any type that has a Name() method, even if the package implementing the type in the first place did not think about that need.
To achieve extensibility, this is usually also applied for functions you export that receive parameters.
If you are exporting a function like this:
func PrintName(customer Customer) {
fmt.Println(customer.Name())
}
Then that function can be invoked with any object that implements Customer (any of your implementations would work for example).

Related

Import cycles more than two levels go

So i have this import cycle to solve, and my project structure basically likes this:
model.go -> procedure.go -> function.go
In my function i need model and i use interface to handle it. Currently my code basically like this:
type imodel interface {
foo()
}
type model struct {
}
func (m *model) run() {
proc := &procedure{}
proc.run(m)
}
func (m *model) foo() {
//bla bla
}
type procedure struct {
}
func (p *procedure) run(model imodel) {
funct := &function{}
funct.run(model)
}
type function struct {
}
func (f *function) run(model imodel) {
model.foo()
}
My question is should i pass my model using interface thorough every class like that or there's any other workaround?
I would put all of these in the same package. Depending on circumstances, I may put them in different files in the same package.
Also, you do not seem to export imodel, so it would be package-internal and unless you have multiple concrete implementations, you do not need an interface. Then, "imodel" is a less than ideal name, the interface should be named model and each concrete type implementing the interface should be named after what it models.

Golang multi-method interface and struct naming

Golang docs provide a clear guidance on how to name single-method interface (by appending "-er"). But what is the best practice to name a multi-method interface that has only a single struct implementing it?
In C# the interface would have "I" prefix, in Java, the class will have "Impl" suffix. Are there similar guidelines for Golang?
The point of having an interface here is to be able to mock it for unit-testing of components that depend on it.
Here is a specific example of UserManager interface. It is going to be consumed by a web api controller that will translate HTTP requests into method calls on this interface. This web api controller will use most of the methods of UserManager.
type UserManager interface { // Should it be UserManagerInterface ?
GetUser(id int) User
CreateUser(user User)
DeleteUser(id int)
ResetPassword(id int, newPassword string)
VerifyEmail(id int)
}
type UserManagerImpl struct { // -Impl, or -Struct, or something else?
}
Coming from Java/C# to Go requires a paradigm shift.
Because they are implemented implicitly, interfaces are defined where they're consumed, not where they're implemented.
Because they're implemented implicitly, smaller interfaces are preferred over larger interfaces, hence the focus on single-method "Verber" interfaces. If you have a function that needs to read bytes, it can take a io.Reader, and the function can be supplied any type that has that method (regardless what other methods it has). You probably don't have a function that calls all 5 of the methods listed in your interface (if so, that function is probably doing too much).
If you feel like naming a struct and an interface the same thing and therefore need some kind of prefix/suffix, you're probably thinking about it the wrong way and might need to reconsider your design.
DBAL is one area where there is sometimes a real case for a larger interface (though it should probably still be composed of smaller interfaces). But in this case, "Impl" doesn't tell you anything - Java and C# love to have pointless interfaces, Go does not. If you'll only ever have one implementation, the interface is probably useless.
If you will have multiple implementations, the differences between them should guide your naming. For example, you might have a PostgresUserManager, a MongoUserManager, and a MockUserManager.
Do you really need UserManagerImpl struct be public? It's kinda common to have a public interface and the corresponding private implementation. Check this and this.
type Store interface {
RunRoot() string
GraphRoot() string
...
}
type store struct {
...
}
func New() Store {
return &store{}
}
func (s *store) RunRoot() string {
return s.runRoot
}
func (s *store) GraphRoot() string {
return s.graphRoot
}
I mean, if you came up with a decent name for the interface, you still can use it for the implementation. But in general, it's good to call things reflecting what they really are regardless of the best practices of the given language. Projects are unique, it's barely possible to make a list of best practices suitable for all the use cases of the language.
The same as #Ivan Velichko I also used to make Interfaces public and struct private like so:
type Service interface {
Do() error
}
type service struct {
dependency dependencies.Dependency
}
func (s *service) Do() error {
return s.depedency.Do()
}
func NewService() Service {
return &service{}
}
However if for some reasons you have to make structs or their properties public and you don't want to write a lot of getters or setters consider examples below:
Make interface name more specific to actions it does
According this articles:
Effective Go
Is there a naming convention for interface + struct pairs?
You should:
By convention, one-method interfaces are named by the method name plus an -er suffix or similar modification to construct an agent noun: Reader, Writer, Formatter, CloseNotifier etc.
type ServiceWorker interface {
HandleMessages() error
}
type Service struct {
dependency dependencies.Dependency
}
func (s *service) HandleMessages() error {
return s.depedency.Do()
}
func NewServiceWorker() Service {
return &service{
Property: "property"
}
}
Create function for getting/modifying struct
type Service interface {
Do() error
Service() *service // this will handle getting and modifying your struct
}
type service struct {
dependency dependencies.Dependency
Property string // property to want to expose
}
func (s *service) Do() error {
return s.depedency.Do()
}
func (s *service) Service() *service {
return s
}
func NewService() Service {
return &service{
Property: "property"
}
}
//...
func main() {
s := pkg.NewService()
fmt.Println("p1:", s.Service().Property) // p1: property
s.Service().Property = "second"
fmt.Println("p2:", s.Service().Property) // p2: second
}
Define getters and setters
Define getters and setters in more Java/C# way:
type Service interface {
Do() error
Get() service
Set() *service
}
type service struct {
dependency dependencies.Dependency
Property string // property to want to expose
}
func (s *service) Do() error {
return s.depedency.Do()
}
func (s service) Get() service {
return s
}
func (s *service) Set() *service {
return s
}
func NewService() Service {
return &service{
Property: "property"
}
}

Embedding of mutually dependent structures/interfaces

I have 3 structures that are similar about 70%. So I'd like to extract some common part and create some extensions with specific methods and fields.
Final structure will work as follows:
method .Start() from Common is called
Start() calls method .Name() from specific part the latter return a string
the returned result is being processed in (*Common).Process(), sometimes it should call specific's Format()
But! Specific part have to call Common part's method, for example GetVerbosity()
Like this:
package common
type Common struct {
Specificer
}
func (c *Common) Start() {
...
name := Specific.Name()
}
func (c *Common) GetVerbosity() {...}
type Specificer interface {
Name() string
Format() string
}
And specific part:
package specific1
// should implement common.Specificer interface
type Specific1 struct {
// unexported fields
}
func (s *Specific1) Name() string {...}
func (s *Specific1) Format() string {
// How to call it???
Common.Method()
}
This is similar to some frameworks - when another code calls your code, and also you call it's code.
How to implement this better? And how to create new structures?
I tried:
Embed Specific to Common, and embed vise versa:
type Common struct {
Specificer
}
type Specific1 struct {
common.Common
...
}
// But this is little bit insane:
func NewSpecific1() *common.Common {
var s = Specific1{}
return &common.Common{Specificer: &s}
}
Define 2 interfaces: Commoner and Specificer. And combined interface:
package common
type CommonSpecificer interface {
Commoner
Specificer
}
type Common struct {...} // implements all the methods from Commoner
func New() *Common {...}
//////
package specific1
type Specific1 struct { // implements all the methods from common.Specificer
Common
...
}
func NewSpecific1() *Specific1 {
c := common.NewCommon(...)
s := &Specific1{Common: c}
return s
}

Method vs Functions Usage golang

I know differences between func and method. But I am confusing for usages between:
prod:=Product{"title","brand","model"}
prod.Add()
or:
prod:=Product{"title","brand","model"}
products.Add(&prod) // products is package
These are two distinct cases, one which is a method belongs to Product instance and one is a global function belongs to products package.
type Product struct {
Title string
Brand string
Model string
}
// This method add value to a field in Product
func (p *Product) Add(field, value string) {
switch field {
case "Title":
p.Title = value
case "Brand":
p.Brand = value
case "Model":
p.Model = value
}
}
The above provide a method to add value to itself as an instance of Product, i.e.
product1 := &Product{}
product1.Add("Title", "first_title")
The second case is a public function exposed from a product package. In this case, an instance (or a pointer) of a Product must be supplied as an argument.
package products
func Add(p *Product, field, value string) {
// Same switch-case as above
}
Add function then can be used from any other package.
package main
import (
"path/to/products"
)
type Product struct {
// ...
}
func main() {
product1 := &Product{}
products.Add(product1, "Title", "first_title")
Normally in your scenario, the first approach is preferred since it encapsulates the functionality of managing its attributes to itself.
The second scenario might be seen as a "class method approach" (for those coming from OOP like Python or Java) where the package is similar to class and the exposed functions similar to class methods which are more generic and can be used across many types which implement the same interface, like so:
package products
// where p is a Product interface
func Add(p Product, field, value string) {
// Same switch-case as above
}
type Product interface {
someMethod()
}
And from another package:
package main
import (
"path/to/products"
)
type Car struct {
Title string
Brand string
Model string
}
type Ship struct {
// ...
}
type Airplane struct {
// ...
}
// All types implement `Product` and can be used in `products.Add`
func (c *Car) someMethod() {}
func (s *Ship) someMethod() {}
func (a *Airplane) someMethod() {}
func main() {
plane := &Airplane{}
products.Add(plane, "Model", "Boeing-747")
}
This is expected as per the spec:
The type of a method is the type of a function with the receiver as first argument.
See https://golang.org/ref/spec#Method_declarations
So when you declare the Add method on Product, you get a function that accepts a pointer to a Product as its first argument. So you end up with
func (p *Product) Add()
being translated to
func Add(p *Product)
So both your calls are valid and end up doing the same
Extending the fantastic answer by #Danilo:
package main
import "fmt"
type T struct {
i int
}
func (t *T) F() {
t = &T{1}
fmt.Println(t.i)
}
func F(t *T) {
fmt.Println(t.i)
}
func main() {
t := T{2}
(&t).F()
F(&t)
}
The type of the method func (t *T) F() is the type of the function func F(t *T) with the receiver (t *T) as first argument.

Polymorphism in Go - does it exist?

I am trying to make something real simple on Go: to have an interface with getter and setter methods. And it seems setter methods are not allowed.
Given this code:
package main
import "fmt"
type MyInterfacer interface {
Get() int
Set(i int)
}
type MyStruct struct {
data int
}
func (this MyStruct) Get() int {
return this.data
}
func (this MyStruct) Set(i int) {
this.data = i
}
func main() {
s := MyStruct{123}
fmt.Println(s.Get())
s.Set(456)
fmt.Println(s.Get())
var mi MyInterfacer = s
mi.Set(789)
fmt.Println(mi.Get())
}
Set method does not work, because in func (this MyStruct) Set(i int), this MyStruct is not a pointer, and the changes are lost as soon at the function exits. But making it this *MyStruct would not compile. Is there any workaround?
Here is a corrected version of your code (playground). This isn't exactly Polymorphism, but the use of an interface is good Go style.
package main
import "fmt"
type MyInterfacer interface {
Get() int
Set(i int)
}
type MyStruct struct {
data int
}
func (this *MyStruct) Get() int {
return this.data
}
func (this *MyStruct) Set(i int) {
this.data = i
}
func main() {
s := &MyStruct{123}
fmt.Println(s.Get())
s.Set(456)
fmt.Println(s.Get())
var mi MyInterfacer = s
mi.Set(789)
fmt.Println(mi.Get())
}
I once found this example of how to do polymorphism in Go:
http://play.golang.org/p/6Ip9scm4c3
package main
import "fmt"
type Talker interface {
Talk(words string)
}
type Cat struct {
name string
}
type Dog struct {
name string
}
func (c *Cat) Talk(words string) {
fmt.Printf("Cat " + c.name + " here: " + words + "\n")
}
func (d *Dog) Talk(words string) {
fmt.Printf("Dog " + d.name + " here: " + words + "\n")
}
func main() {
var t1, t2 Talker
t1 = &Cat{"Kit"}
t2 = &Dog{"Doug"}
t1.Talk("meow")
t2.Talk("woof")
}
To answer the question the in the title to post:
Go does not use classes, but provides many of the same features:
* message passing with methods
* automatic message delegation via embedding
* polymorphism via interfaces
* namespacing via exports
From: http://nathany.com/good/
Solving the code you supplied, I will leave to some more learned Gopher
###AD HOC polymophism
Ad hoc polymorphism is a general way of polymorphism implementation for statically typed languages. Polymorphism in Go is ad hoc polymorphism which is very close to Bjarne's Stroustrup definition:
Polymorphism – providing a single interface to entities of different types.
Interfaces
Go interface is really powerful tool designed specially for polymorphism implementation. Interface is a type abstraction (sets of methods) which provides a way to specify the behavior of an object: if something can do this, then it can be used here. Back to Straustrup's polymorphism definition: it is possible to use objects of different types as a type of a common interface if they implement the interface.
Playground with an example.
Parametric polymorphism
Wiki:
A function or a data type can be written generically so that it can handle values identically without depending on their type.
This kind of polymorphism is more regular for dynamically typed languages like Python or Ruby but Go implements it too! Go uses type empty interface interface{} for this purpose.
Type interface{}
From Tour Of Go:
The interface type that specifies zero methods is known as the empty interface:
interface{}
An empty interface may hold values of any type. Every type implements at least zero methods.
Empty interfaces are used by code that handles values of unknown type. For example, fmt.Print takes any number of arguments of type interface{}.
And it is possible to get particular type of an object with type assertion.
And again Tour Of Go:
A type assertion provides access to an interface value's underlying concrete value.
t := i.(T)
This statement asserts that the interface value i holds the concrete type T and assigns the underlying T value to the variable t.
There we have parametric polymorphism with static duck typing.

Resources