I have been doing a bit of go programming of late and while trying to follow Effective Go style guidelines, I sometimes find it difficult to avoid stuttering when naming packages and interfaces and structs.
As an example.
I might have a console package with a Console.go file containing a Console interface a console struct and a New function.
//console/Console.go
package console
type Console interface {
Print(s String)
}
type console struct {
....
}
func (c *console) Print(s String){
....
}
func New() Console{
return &console{}
}
Now when I use this somewhere I end up using a console.Console
type everywhere.
When I have two or more structs in a package I end up things like con := console.NewConsole()
I don't mind having large mostly flat package structures but I do like to keep my code organized as much as possible. I am ok with the idea of IO.Reader and IO.Writer but what to do when the package is the same as the thing but still needs to be separated. (Yes I am aware that the given example could be Console.Writer but lets pretend its something completely different)
So my questions are: Is this stutter effect something I should even worry about? (ie. Is it bad form?) Does anyone have any tips in avoiding it?
Stuttering type names are generally fine - it's not unusual to have a foo.Foo
, because package foo
is dedicated to defining type Foo
. There's absolutely nothing wrong with that.
What you want to avoid is unnecessary stuttering; this would be things like foo.NewFoo
when simply foo.New
is sufficiently precise, or foo.FooBar
and foo.FooBaz
where foo.Bar
and foo.Baz
would work just as well.
Consider the standard library's html/template
, which defines a type (template.Template
) and a constructor (template.New
).
My experience is that you will not get away with New() unless when you only want one struct in a package, which isn't convenient when working from one generic designed model.
Also a risk of having many packages is cycling imports, because very often structs refer to each other. You will limit yourself very much when you only allow one struct in a package.
By the way, you have this code: func New() *Console In which Console is an interface to the struct console. Why don't you return *console from your constructor, because that is what it is delivering anyway, my idea is that func New() *console is better.