-
Notifications
You must be signed in to change notification settings - Fork 1
Coding Standards
All packages should define an interface and at least one implementation of that interface. Types should be in a separate file or optionally a subdirectory.
All service properties should be private and all interfaces should include a function (s Service) Props() Props { return s.props }
method that returns the service's properties.
project
│ README.md
│ main.go
│
└───pkg
│ │
│ └───foo
│ │ │ interface.go
│ │ │ types.go
│ │ │ service.go
│ │
│ └───bar
│ │ interface.go
│ │
│ └───types
│ │ │ types.go
│ │
│ └───implementation1
│ │ │ service.go
│ │
│ └───implementation2
│ │ service.go
│
└───cmd
...
To use a package, import the interface.
package foobar
import "pkg/foo"
// Props are passed to the New function
type Props struct {
FooService foo.Interface
}
// Service implements the package interface
type Service struct {
props Props
}
// New returns a new service
func New(props Props) *Service {
return &Service{
props: props,
}
}
// Props returns the service's props
function (s Service) Props() Props {
return s.props
}
...
Tests should be categorized into one of three types:
- Unit
- Integration
- End-to-end (e2e)
Tests should be denoted in two ways. First, the test file name should end in the test type. e.g. foo_unit_test.go
. Secondly, use a build tag inside the test file.
// +build unit
func TestFooBar(t *testing.T) {
...
}
Each category of test can then be run as such: $ go test -tags=unit
Note to Adam:
Below is another pattern to consider. This pattern is more commonly seen in Go projects (e.g. Docker, IPFS).
Response to Miguel:
I'm fine with just, just so long as Foo foo.Foo
and/or mystore foo.MyStore
are interfaces so the package can be unit tested
project
│ README.md
│ main.go
│
└───pkg
│ │
│ └───foo
│ │ │ foo_test.go
│ │ │ foo.go
│ │
│ └───bar
│ │ bar.go
│ │
│ └───types
│ │ │ types.go
│ │
│ └───qux
│ │ │ qux.go
│ │
│ └───baz
│ │ baz.go
│
└───cmd
...
package foobar
import "pkg/foo"
// Config is the configuration settings for the package constructor.
type Config struct {
Foo foo.Foo
}
// Foobar is the structure that holds information regarding the instance.
type Foobar struct {
mystore foo.MyStore
}
// NewFoobar returns a new foobar instance.
func NewFoobar(config *Config) *Foobar {
f := foo.NewFoo()
return &Service{
myStore: f.MyStore,
}
}
// MyStore returns the mystore instance.
function (foobar *Foobar) MyStore() {
return foobar.myStore
}
...
Projects are named as follows: <project>-<library>-<language>
and examples are <project>-<library>-<language>-example-<example_name>
per this issue.