I started a new go projects a few days ago, and I use golangci-lint to make my code in good style. I found gochecknoinits is one of linters of golangci-lint, and it tells me not to use init.
In my opinion, I can put simple initial code in init for convenience. Without init, I must write a Init function and find somewhere to call it before use that package. This can be forgotten or be done multiple times.
So, is it really bad to use init in go?
Package init() functions are a handy tool, sometimes necessary, but should not be overused. They are often used to initialize some global variables, but even global variables should be avoided as much as possible.
Quote from github.com/leighmcculloch/gochecknoinits:
Init functions cause an import to have a side effects, and side effects are hard to test, reduce readability and increase the complexity of code.
There is your answer. When you import a package, its init() functions are called and may do whatever they want to. They may change things some of your (unrelated) tests depend on, so whether your tests pass could depend on whether you import a specific package.
Further reading: Go: No globals, no init functions
Related
In my early days of learning Go and trying to use package github.com/jessevdk/go-flags. I checked the Fly example referenced in another go-flags thread, but it apparently does not use AddCommand (at least per my grep).
The godoc article recommends defining a global parser instance and to implement each command in a separate file. Each of those command files should define a go init function which calls AddCommand on the global parser.
Making my parser global was easy enough. Confused on the init() setups:
1) My understanding is that init() order execution is random, other than your main's init running last.
2) If so, I can't ensure that my NewParser() call in my configuration code has been called prior my AddCommand() calls.
3) My code compiles, but a --help doesn't show any defined commands, making me think that indeed, the AddCommand() was called before the NewParser()
/* Just a guess */
4) QED I'm confused!
Does anybody have a recommended example I could go learn from?
I know this might be controversial or not very broad but I'm going to try to be very specific and relate to other questions.
Ok so when I make a Go program what things should I be thinking in terms of how I should organize my project? (E.g. should I think ok I'm going to have controllers of some sort so I should have a controller subdirectory that's going to do this so I should have that)
How should I structure a package?
For example the current program I'm working on I'm trying to make a SteamBot using this package
But while I'm writing it I don't know if I should export certain methods into their own own files, e.g. I'd have something like
func (t *tradeBot) acceptTrade() {}
func (t *tradeBot) declineTrade() {}
func (t *tradeBot) monitorTrade() {}
func (t *tradeBot) sendTrade() {}
each method is going to have quite a bit of code so should I export each method into its own file or just have 1 file with 3000 lines of code in it?
Also using global variables so that I can set one variable and then leave it and be able to use it in multiple functions, or is this bad and I should pass the variables as arguments?
Also should I order my files like:
package
imports
constants
variables
functions
methods
Or do I just put things where I need them?
The first place to look for inspiration is the Go standard library. The Go standard library is a pretty good guide of what "good" Go code should look like. A library isn't quite the same as an application, but it's definitely a good introduction.
In general, you would not break up every method into its own file. Go tends to prefer larger files that cover a topic. 3000 lines seems quite large, though. Even the net/http server.go is only 2200 lines, and it's pretty big.
Global mutable variables are just as bad in Go as in any language. Since Go relies so heavily on concurrent programming, global mutable variables are quite horrible. Don't do that. One common exception is sync structures like sync.Pool or sync.Once, which sometimes are package global, but are also designed to be accessed concurrently. There are also sometimes "Default" versions of structures, like http.DefaultClient, but you can still pass explicit ones to functions. Again, look through the Go standard library and see what is common and what is rare.
Just a few tips that you hopefully find useful:
Organize code into multiple files and packages by features, not by layers. This becomes more important the bigger your application becomes. package controllers with one or two controllers is probably ok, but putting hundreds of unrelated controllers in the same package doesn't make any sense. The following article explains it very well: http://www.javapractices.com/topic/TopicAction.do?Id=205
Global variables sometimes make code easier to write however they should be used with care. I think unexported global variables for things like logger, debug flags, etc are ok.
I am having a tough time grasping the idea of completely avoiding globals in Ruby.
To my understanding, if I define a method, the method would be considered global because I can call the method later on in the script. Same goes for classes. Can you completely avoid globalsl?
Research has pointed my inconclusively towards closures and singleton methods but I am still having trouble understanding how I would 'completely avoid globals.'
EDIT: I have also programmed a bit in JavaScript and used closure as follows to avoid the use of any globals: (function(){...})(); Can something similar be done in Ruby?
It is important to understand the reasoning behind avoiding globals. The main reason is avoiding global state. By storing variable information in a global variable, you are allowing components of the program to behave differently when used in the same way at different times. This usually results in unintended side-effects, causing testing and maintenance issues. Global classes or methods are unable to change (not considering reflection) and are not an issue because of that.
Another thing you may have associated with globals is namespace pollution, which can be partially resolved by nesting namespaces in a way that groups components semantically. Those are still global, though and thus not really avoidable.
Modules and Classes as globals are not a problem.
You could use a module to conceal a class, but ultimately you're going to have some globals.
Avoiding global variables and methods would be advised, though.
By default, Go treats unused import as error, forcing you to delete the import.
I want to know if there exists some hope to change to this behavior, e.g. reducing it to warning.
I find this problem extremely annoying, preventing me from enjoying coding in Go.
For example, I was testing some code, disabling a segment/function. Some functions from a lib is no longer used (e.g. fmt, errors, whatever), but I will need to re-enable the function after a little testing. Now the program won't compile unless I remove those imports, and a few minutes later I need to re-import the lib.
I was doing this process again and again when developing a GAE program.
Adding an underscore (_) before a package name will ignore the unused import error.
Here is an example of how you could use it:
import (
"log"
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
To import a package solely for its side-effects (initialization), use
the blank identifier as explicit package name.
View more at https://golang.org/ref/spec#Import_declarations
The var _ = fmt.Printf trick is helpful here.
I have the same problem. I understand the reasoning for why they implemented the language to disallow unused imports and variables, but I personally find this feature annoying when writing my code. To get around this, I changed around my compiler to allow optional flags for allowing unused variables and imports in my code.
If you are interested, you can see this at https://github.com/dtnewman/modified_golang_compiler.
Now, I can simply run code with a command such as go run -gcflags '-unused_pkgs' test.go and it will not throw these "unused import" errors. If I leave out these flags, then it returns to the default of not allowing unused imports.
Doing this only required a few simple changes. Go purists will probably not be happy with these changes since there is good reason to not allow unused variables/imports, but I personally agree with you that this issue makes it much less enjoyable to code in Go which is why I made these changes to my compiler.
Use goimports. It's basically a fork of gofmt, written by Brad Fitzpatrick and now included in the go tools packages. You can configure your editor to run it whenever you save a file. You'll never have to worry about this problem again.
Use if false { ... } to comment out some code. The code inside the braces must be syntactically correct, but can be nonsense code otherwise.
If you are using the fmt package for general printing to console while you develop and test then you may find a better solution in the log package.
A lot of people have already commented with valid justification and I also acknowledge the original author's intention. However, Rob Pike mentioned in different forums that Go is the outcome of simplification of the processes that a few other mainstream programming languages either lack or not easy to achieve. It's Go's language semantics as well as to make the compilation faster, there are a lot of things that are adopted which initially seems inefficient.
To make it short, unused imports are considered as errors in Go as it blots the program and slows down the compilation. Using import for side effect (_) is a workaround, however, I find this confusing at times when there is a mix of valid imports with side effects along with side effects imported purely for the purpose of debugging/testing especially when the code base is large and there is a chance to forget and not delete unintentionally which may confuse other engineers/reviewers later. I used to comment out the unused ones, however, popular IDEs such as VS code and Goland can use goimports easily which does the insertion and deletion of the imports pretty well. Please refer to the link for more info, https://golang.org/doc/effective_go.html#blank_import
put this on top of your document and forget about unused imports:
import (
"bufio"
"fmt"
"os"
"path/filepath"
)
var _, _, _, _ = fmt.Println, bufio.NewReader, os.Open, filepath.IsAbs
In Go, public names start with an upper case letter and private names start with a lower case letter.
I'm writing a program that is not library and is a single package. Is there any Go idiom that stipulates whether my identifiers should be all public or all private? I do not plan on using this package as a library or as something that should be imported from another Go program.
I can't think of any reason why I'd want a mixture. It "feels" like going all private is the proper choice.
I don't think I got any concrete answer, but Nate was closest with telling me to think of "exporting vs non-exporting" instead of "public and private".
This leads me to believe that not exporting anything is the best approach. In the worst case scenario, if I end up importing code from my application in another package, I will have to rethink what should be exported and what shouldn't be. Which is a good thing IMO.
If you are attempting to adjust your mindset to be more Go idiomatic, you should stop thinking of variables, functions, and methods as public or private. The more accurate term is exported or not exported. It definitely has a more C like feel to it.
As others have stated exporting really isn't needed for application program code. If for organizational reasons you decide to break your program up into packages, you could use sub-packages. At work we've decided to do just this. We have:
projectgopath/src/projectname
projectname/subcomponent1
projectname/subcomponent2
So far I am really liking this structure. It aids in separation of concerns, but does not go to the extent of making a package outside of the main project. The intent is clear. The sub-package's intended use is for this program only...
The new go build and go install commands seem to deal very well with it. We group components together in packages and expose only the necessary bits via exports.
In the described situation both approaches are equally valid, so it's more or less a matter of personal preferences. In my case I'm using camelCase identifiers for package main, mostly out of habit.
A lot of my go files started their life in isolated commands and were moved to packages as they could be reused by a few commands around the same topic.
I think you should make private all that couldn't possibly be called from elsewhere (supposing one day you make it an importable package) and make public the big functions that can be understood from elsewhere (if any) and structs fields when they are orthogonal (I mean when a change of the value of one field doesn't break the consistency of the struct value).