Import cycles

First off, the spec provides an example of how to reference a symbol in an imported package, using different import alias options. I’ve already provided my own examples earlier, and it’s pretty straight forward, so we’ll just breeze through this part. Import declarations … Consider a compiled a package containing the package clause package math, which exports function Sin, and installed the compiled package in the file identified by "lib/math". This table illustrates how Sin is accessed in files that import the package after the various types of import declaration.


Valid import paths

Today we’re looking at one of the more essoteric parts of the spec. Import declarations … Implementation restriction: A compiler may restrict ImportPaths to non-empty strings using only characters belonging to Unicode’s L, M, N, P, and S general categories (the Graphic characters without spaces) and may also exclude the characters !"#$%&’()*,:;<=>?[]^`{|} and the Unicode replacement character U+FFFD. Other than what’s stated in the quote, we’re not going to look at an exhaustive list of what is and isn’t guaranteed to be supported by a Go implementation.


Relative imports

Newcomers to Go often try to use relative imports, and then are usually bitten by random weird problems. They seem to work sometimes, and not other times. What’s the deal? import "./foo" Import declarations … The interpretation of the ImportPath is implementation-dependent but it is typically a substring of the full file name of the compiled package and may be relative to a repository of installed packages. Okay. So this bit of the spec doesn’t help a whole lot.


Working with versioned imports

We’re continuing today our discussion of imports. Yesterday we left off with using explicit package names in an import clause when the package name differs from the last element of the import path. Is that the only reason to explicitly name your imports? No. Sometimes you need to disambiguate between two imports with the same package name. Or maybe you just like a shorter name. import ( log "github.com/sirupsen/logrus" // Shorter names are nice stdlog "log" // Oh, but we need to reference this package, too ) There is one exception to the rule “Name your packages the same as the last element of your import path,” though: v2+ releases.

Subscribe to Boldly Go: Daily

Every day I'll send you advice to improve your understanding of Go. Don't miss out! I will respect your inbox, and honor my privacy policy.

Unsure? Browse the archive.


Import declarations

Today we have a very important topic… Import declarations An import declaration states that the source file containing the declaration depends on functionality of the imported package (§Program initialization and execution) and enables access to exported identifiers of that package. The import names an identifier (PackageName) to be used for access and an ImportPath that specifies the package to be imported. ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .


Packages

I’m back! I took an extra week off, from what I planned, due to chaotic circumstances, but I’m back again now. I’m also in a new timezone—America/Central. So my daily emails may begin coming on a different erratic schedule than the previous erratic schedule you were accustomed to. Anyway, let’s get back into the spec! If you’ve done any Go coding at all, you’ve seen at least one package, the main package.


Bootstrapping

A quick note to say that I’m taking next week off, for a move. I expect to return October 4 with more Boldy Go: Daily emails. Until then! We’re down to the final two built-in functions in Go. And these are probably functions you should not be using, except possibly in throw-away test code or during debugging. Bootstrapping Current implementations provide several built-in functions useful during bootstrapping. These functions are documented for completeness but are not guaranteed to stay in the language.


Recover values

Handling panics … The return value of recover is nil when the goroutine is not panicking or recover was not called directly by a deferred function. Conversely, if a goroutine is panicking and recover was called directly by a deferred function, the return value of recover is guaranteed not to be nil. To ensure this, calling panic with a nil interface value (or an untyped nil) causes a run-time panic.


Order of recovery

Yesterday we saw how panic plays with deferred functions, in terms of order of execution. Today we’ll take things up one level, and throw recover in there… there’s more to recover than just execution order. We’ll get to that next. Handling panics … The recover function allows a program to manage behavior of a panicking goroutine. Suppose a function G defers a function D that calls recover and a panic occurs in a function on the same goroutine in which G is executing.


Panicking and deferred functions

Handling panics … While executing a function F, an explicit call to panic or a run-time panic terminates the execution of F. Any functions deferred by F are then executed as usual. Next, any deferred functions run by F’s caller are run, and so on up to any deferred by the top-level function in the executing goroutine. At that point, the program is terminated and the error condition is reported, including the value of the argument to panic.


Don't panic!

We’re ready for the section of the Go spec that talks about panic and recover, Go’s rough analogs to throw and catch. Handling panics Two built-in functions, panic and recover, assist in reporting and handling run-time panics and program-defined error conditions. func panic(interface{}) func recover() interface{} But before we dive into a discussion of how these things work, and how to use them, I want to offer some caution, in the form of one of the famous Go Proverbs: