Ways to avoid stuttering in go package and struct names? - go

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).

Related

Is this a special form of Go type assertion?

I am a total novice Go programmer.
I ran across this in the Kubernetes source code:
var (
_ = Queue(&FIFO{}) // FIFO is a Queue
)
Queue is declared earlier like this:
type Queue interface { // etc.
FIFO is declared earlier like this:
type FIFO struct { // etc.
So is my first excerpt a kind of type assertion? It doesn't seem to fit the syntax described by the Go Tour's lesson-let on the subject.
I certainly can take it on faith that this block is ensuring that a FIFO "is a" Queue, but I want to understand exactly what's going on here, and I am too much of a novice to know where to look in the Go language specification (the section on type assertions, which seems to be what this is semantically, didn't seem to cover this case, nor did the section on interface types).
It's a Type Conversion which is a little different than a type assertion.

How can I write a function that takes either one of many types in go?

I'm trying go for a small project and tried to write these functions:
func fatal(reason string) {
println(reason)
os.Exit(1)
}
func fatal(err error) {
fatal(err.Error())
}
After digging about a bit and finding this answer, which referenced the docs on overloading I realised that what I was trying to do was illegal in go.
What I want is a simple api that allows me to call fatal with either a string or an error in order to simplify my logic. How do I achieve this or a similar goal?
It would feel inelegant to have func fatal(reason string) along with func fatalErr(err error), is that what's needed? Am I missing a different feature of the language that allows me to do what I want?
The most common way to do this would be to define the method as func fatal(err interface{}) then do type assertions or use a type switch within it's body to handle each of the different types. If I were coding for your example it would look like this;
func fatal(err interface{}) {
if v, ok := err.(string); ok {
fmt.Println(v)
}
if v, ok := err.(error); ok {
fmt.Println(v.Error())
} else {
// panic ?
}
}
Also; here's a quick read about type switches and assertions that may be helpful; http://blog.denevell.org/golang-interface-type-assertions-switch.html
You can also check out effective-go as it has sections on both features.
Use log.Fatal() instead. https://golang.org/pkg/log/#Fatal
You can use interface{} but it is not recommended because you lose all the benefits of type checking when you do that. The Go authors get to use interface{} because they understand the appropriate level of additional testing and checks to do when using interface{}. It's much easier (even for intermediate and advanced gophers) to use builtin and standard library functions when something like this is required.
Go does not have algebraic or/sum types either. The standard workaround is to define an and/product type with pointers (e.g. struct{*string, *error}) and go to the effort of making sure you only ever make one of the fields non nil at any point in time.
Function overloading is not supported in the language. From the official Golang site it says,
Method dispatch is simplified if it doesn't need to do type matching as well. Experience with other languages told us that having a variety of methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice. Matching only by name and requiring consistency in the types was a major simplifying decision in Go's type system.
Regarding operator overloading, it seems more a convenience than an absolute requirement. Again, things are simpler without it.
https://golang.org/doc/faq#overloading
One potential solution would be to define a high level function that type checks and handles different types similarly to how you would overload multiple functions. See #evanmcdonnal's solution for a great example.

Finding functions that return a specific type

Perhaps this is a silly question, but is there a way to find all functions (in the standard library or GOPATH) that return a specific type?
For example there are many functions that take io.Writer as an argument. Now I want to know how to create an io.Writer and there are many ways to do so. But how can I find all the ways easily without guessing at packages and looking through all the methods to find those that return an io.Writer (or whatever other type I'm after)?
Edit: I should extend my question to also find types that implement a specific interface. Sticking with the io.Writer example (which admittedly was a bad example for the original question) it would be good to have a way to find any types that implement the Writer interface, since those types would be valid arguments for a function that takes takes an io.Writer and thus answer the original question when the type is an interface.
Maybe not the best way but take a look at the search field at the top of the official golang.org website. If you search for "Writer":
http://golang.org/search?q=Writer
You get many results, grouped by categories like
Types
Package-level declarations
Local declarations and uses
and Textual occurrences
Also note that io.Writer is an interface, and we all know how Go handles interfaces: when implementing an interface, there is no declaration of intent, a type implicitly implements an interface if the methods defined by the interface are declared. This means that you won't be able to find many examples where an io.Writer is created and returned because a type might be named entirely different and still be an io.Writer.
Things get a little easier if you look for a non-interface type for example bytes.Buffer.
Also in the documentation of the declaring package of the type the Index section groups functions and methods of the package by type so you will find functions and methods of the same package that return the type you're looking for right under its entry/link in the Index section.
Also note that you can check the dependencies of packages at godoc.org. For example you can see what packages import the io package which may be a good starting point to look for further examples (this would be exhausting in case of package io because it is so general that at the moment 23410 packages import it).
In my days coding I'm personally rare in need to find functions returning Int16 and error(func can return few values in Go, you know)
For second part of your question there exists wonderful cmd implements written by Dominik Honnef go get honnef.co/go/implements
After discover type that satisfy your conditions you can assume constructor for type (something like func NewTheType() TheType) would be just after TheType declaration in source code and docs. It's a proven Go practice.

Do short variable declarations lead to poorly structured code in Go? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
From looking at a lot of Go code on GitHub, I have noticed that Go coders love the short variable declaration (:=)and use it very often. Here's an example Coding Style. But this usage seems far too often to create poorly structured code: Very long functions that bundle lots of functionality together, because Short variable declarations may appear only inside functions. If you want to set up a package that encapsulates something akin to a class with members that several short, modularized functions operate on, as good structured programming and OOP practices mandate, you can't really use short variable declarations effectively for member variables. I tend to get uneasy whenever I see any function that's more than 10 or 15 lines long - I know something's probably not right with that design.
Personally, I'm not a big fan of short variable declarations except for local initializion of loop counters, etc. Aside from the above mentioned issue, I like to see clearly the type I'm working with. Particularly when looking over new code, short variable declarations assume that the reader knows what the function initializing the variable is returning, or obliges them to go and find out, or deduce it from the context. So, that code becomes less readable and requires the reader to stop, and perhaps search somewhere for its meaning, whereas avardeclaration might make things immediately clear.
(I suppose one way write better code and still use short variable declarations would be to avoid the use of package global members entirely and parameterize all your functions - not necessarily a bad thing - but this probably creates more work than you will save using short variable declarations.)
As a result I have been opting to use this sort of design for my packages, similar to the way declaration and initialization work in traditional OOP languages such as Delphi and C++:
package myPackage
import (
"importA"
"importB"
)
var m_member1 *importA.T
var m_member2 *importB.T
func init() {
m_member1 = new(importA.T)
m_member2 = new(importB.T)
}
Then I have clearly typed, initialized and encapsulated package members that are available for use in the package. Yes, this does violate the good practice of initializing only when necessary, but I don't have to do this in init() either - can do it on an as needed basis, when the member is used for the first time, although that has other potential complications. (Be that as it may, since initialization of class members in a constructor has been common practice for a long time, I don't have much of problem with this, regardless.)
Is this non-idiomatic, "bad" code in Go? Is the abundant use of short variable declarations, with their IMO negative consequences, considered a good thing? Frankly I fail to see how it could be. I tend to think that perhaps short variable declarations are being used too much by programmers who just love the short syntax, and the result is a lot of bloated looking spaghetti style code. Am I missing something?
Edit: Since the question as stated caused a good deal of confusion, I'll try to illustrate with a simple example (this may or may not compile - wrote quickly just to illustrate)
If I write:
package main
import
(
"packageA"
"packageB"
)
func DoStuff(){
a:=PackageA.T
a.Dostuff()
}
Then it will be very easy to continue and write:
func doStuff(){
a:=PackageA.T
b:=PackageB.T
Dostuff(a)
DoMorestuff(b)
DoEvenMorestuff(a,b)
DoLotsofstuff(a,b)
.....
}
func main(){
DoStuff()
}
IMO bundled, bloated, poorly structured code.
______________________
But when I write
package main
import
( "packageA"
"packageB"
)
var a packageA.T
var b packageB.T
init(){
a=new(packageA.T)
b=new(packageB.T)
}
Then I can write:
func dostuff(){
a.Write()
}
func doMorestuff(){
b.Write()
}
func doEvenMorestuff(){
a.Read(b)
}
func doLotsofstuff(){
a.ReadWrite(a,b)
b.WriteRead(b,a)
}
func main(){
dostuff()
doMorestuff()
doEvenMorestuff()
doLotsofstuff()
}
A modularized pipeline style design, which cannot be implemented with the short variable declaration form. The best that can be done using the short form is nested, parameterized functions, which are generally not a very good design choice either.
Some complained that this amounts to globals, but in a well designed, encapsulated package with a minimal public interface, that is no more of an issue than declaring variables local to a function. Packages should be atomic. Member variables have been an accepted component of OOP design "forever" and when used properly, following the rules of OOP and structured programming, they are not globals, but locals to the package or module or class which encapsulates them.
Granted, there is no feature of any language that cannot be used, or abused. My question is simply that short variable declarations seem to be ripe for abuse and force certain design decisions that are less than desirable, unless used very discreetly. I'm asking if there is a way to use the form that will circumvent the issues I have with them and afford me their ease of use without the drawbacks.
Edit 2:
Perhaps this is something of a compromise:
package main
import
(
"packageA"
"packageB"
)
func dostuff(a PackageA.T){
a.Write()
}
func doMorestuff( b PackageB.T ){
b.Write()
}
func doEvenMorestuff(a a PackageA.T, b PackageB.T ){
a.Read(b)
}
func doLotsofstuff(a a PackageA.T, b PackageB.T ){
a.ReadWrite(a,b)
b.WriteRead(b,a)
}
func doStackofStuff(){
a:=PackageA.T
b:=PackageB.T
dostuff(a)
doMorestuff(b)
doEvenMorestuff(a,b)
doLotsofstuff(a,b)
}
func main(){
doStackofStuff()
}
Still bundled up in main() but that's not really a complaint - doStackofStuff() is my interface call. In "real code" I would write a separate package for all of it, and only DoStackofStuff() would be public and callable from main() - the rest would be encapsulated. The implementation is broken up in doStackofStuff(), yet using the short form without nesting.
The answer is actually very simple. The only alternative to short variable declaration e.g. a := 2 is the long variable declaration e.g. var a int = 2.
Does either of them promote spaghetti code or make functions inherently longer? No.
I think you are mixing a few issues here that are not connected:
If you need to emulate classes and structs in Go - don't use modules for them. Use structs. Build "constructors" for them. That's it. I'd hardly even call it emulation, even though it's not 100% identical to C++ or Java classes. I mean, why not just do something like
type Foo struct {
Bar string
Baz int
}
func NewFoo(bar string, baz int) *Foo {
return &Foo{
bar,
baz,
}
}
//and if you want static state - just do this
var DefaultFoo *Foo
func init() {
DefaultFoo = NewFoo("foo", 1)
}
I don't fully see why doing := inside functions will create spaghetti code. Can you make your point clearer on that? The most harm it can do is scope collisions if you're not careful - like in this example:
var x int = 3
func main() {
if x == 3 {
x := 5
fmt.Println(x) // will print 5
}
fmt.Println(x) //will print 3
}
going back to your example - it's not bad design to import types from a different module (e.g. have a static http client initiated in a module's init() function). But you have to make sure you are really not mixing up responsibility between the two packages.

How to get all defined types?

package demo
type People struct {
Name string
Age uint
}
type UserInfo struct {
Address string
Hobby []string
NickNage string
}
another package:
import "demo"
in this package, how can I get all the types exported from the demo package?
Using go/importer:
pkg, err := importer.Default().Import("time")
if err != nil {
fmt.Println("error:", err)
return
}
for _, declName := range pkg.Scope().Names() {
fmt.Println(declName)
}
(note, this returns an error on the Go Playground).
Go retains no master list of structs, interfaces, or variables at the package level, so what you ask is unfortunately impossible.
Drat, I was hoping that Jsor's answer was wrong, but I can't find any way to do it.
All is not lost though: If you have the source to 'demo', you could use the parser package to fish out the information you need. A bit of a hack though.
Do you come from some scripting language? It looks so.
Go has good reasons to propagate to let not slip 'magic' into your code.
What looks easy at the beginning (have access to all structs, register them automatically somewhere, "saving" coding) will end up in debugging and maintenance nightmare when your project gets larger.
Then you will have to document and lookup all your lousy conventions and implications.
I know what I am talking about, because I went this route several times with ruby and nodejs.
Instead, if you make everything explicit you get some feature, like renaming the People struct to let
the compiler tell you where it is used in your whole code base (and the go compiler is faster than you).
Such possibilities are invaluable for debugging, testing and refactoring.
Also it makes your code easy to reason about for your fellow coders and yourself several months after you have written it.

Resources