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