netpoetica (2) [Avatar] Offline
#1
I have read through this section a couple of times and I am still not quite understanding the function of _ before a package name. I'm actually relatively familiar with Golang and have never come across this, so I thought I might bring attention to it maybe for some further explanation in a new version?

I was able to get some clarification from the Go docs at http://golang.org/doc/effective_go.html#blank

I think it's a way of having "multiple mains", or other processes running within your main that are not actually dependencies, maybe? I know it says we'll get to it later but I was kind of hung up on just trying to grok at least a high-level conceptualization of what was going on

Message was edited by:
netpoetica
Bill Kennedy (69) [Avatar] Offline
#2
Re: Confusion about _ (underscore), listing 2.5
The blank identifier serves two purposes. It can be used to ignore a return value from a function call. The second is what you are seeing with the import statement. The compiler will throw an error if you import a package and never reference an identifier from that package. This is purely because Go wants code to be readable and having imports that are not being "used" is not good practice.

There is one special case where this breaks down and it is when a package has an init() function and you want to make sure it gets identified and executed. During compilation the compiler will traverse the imports and if it find an init() function, those functions will be scheduled to be executed before main. In the sample program I need the compiler to find the init() function in that package. By using the blank identifier I escape from the compiler error and the compiler will find and execute the init() function.

This all works because we can alias a package name in an import statement:

import (
fmt "github.com/bill/format"
)

Here I am telling the compiler to alias the name format to fmt when referencing this package.

When we use the blank identifier in this context:

import (
_ "github.com/bill/format"
)

We are using the blank identifier as the alias name and this gives us the behavior of being able to declare an import without the need of referencing an identifier from the package. Now the import stands and the compiler can find the init() function and life is good.
netpoetica (2) [Avatar] Offline
#3
Re: Confusion about _ (underscore), listing 2.5
Thanks Bill,

I've got my head pretty well-wrapped around the fact that you're telling the compiler, "hey, I'm including a package that I am not going to actually reference throughout my code, but it has an init() function that I will use for setup" - I think, though, that coming from a non-Go background, there is a lot of O_O going on.

I think it's making a little bit more sense. I think I'm struggling to understand the difference between main() and init(), and there is really poor documentation about init. This behavior for Init is very quirky, especially for anyone coming from elsewhere to Go.

The best documentation I could find was this, and it's very brief and with minimal explanation: https://golang.org/doc/effective_go.html#initialization (actually your explanation in your previous post was substantially more enlightening than this documentation).

For me, and maybe this is just me personally, I would expect init() to be a function I would intentfully call at the top of my main() function, something like:

import (
"fmt"
dataSetup "github.com/netpoetica/data"
)

func main() {
ds := dataSetup.init();
fmt.Println(ds.myData)
}

Which appears to have substantially less magic. I am under the impression that the quirky usage of the Init function is a Go programmer convention - it might be helpful to call it out as such. Considering the quirkiness of Go in general it might even be helpful to create some sort of "go programmer convention" inidicator, which, throughout the book, will call out things that might leave newcomers confused.

Thanks again! I appreciate the thorough explanation!
Bill Kennedy (69) [Avatar] Offline
#4
Re: Confusion about _ (underscore), listing 2.5
This is make things worse for you then. You can have multiple init functions in the same source code file. LOL

If you want to create your own Init() function and call it from main, that is fine. Just remember the init() function is there to initialize things before main begins.