Search code examples
modulecompilationpackageprojects-and-solutionsgo

How does modular code work in Go?


Not having come from a C/compiled languages background, I'm finding it hard to get to grips with using Go's packages mechanism to create modular code.

In Python, to import a module and get access to it's functions and whatnot, it's a simple case of

import foo

where foo.py is the name of the module you want to import in the same directory. Otherwise you can add an empty __init__.py into a subfolder and access the modules via

from subfolder import foo

You can then access functions by simply referencing them through the module name, e.g. y = foo.bar(y). This makes it easy to separate logical pieces of code from one another.


In Go however, you specify the package name in the source file itself, e.g.

package foo

at the top of the 'foo' module, which you can then supposedly import through

import (
        "foo"
              )

and then refer to it through that, i.e. y := foo.Bar(x) . But what I can't wrap my head around is how this works in practice. The relevant docs on golang.org seem terse, and directed to people with more (any) experience using makefiles and compilers.

Can someone please clearly explain how you are meant to modularise your code in Go, the right project structure to do so, and how the compilation process works?


Solution

  • Wiki answer, please feel free to add/edit.

    Modularization

    1. Multiple files in the same package

      • This is just what it sounds like. A bunch of files in the same directory that all start with the same package <name> directive means that they are treated as one big set of code by Go. You can transparently call functions in a.go from b.go. This is mostly for the benefit of code organization.
      • A fictional example would be a "blog" package might be laid out with blog.go (the main file), entry.go, and server.go. It's up to you. While you could write a blog package in one big file, that tends to affect readability.
    2. Multiple packages

      • The standard library is done this way. Basically you create modules and optionally install them into $GOROOT. Any program you write can import "<name>" and then call <name>.someFunction()
      • In practice any standalone or shared components should be compiled into packages. Back to the blog package above, If you wanted to add a news feed, you could refactor server.go into a package. Then both blog.go and news.go would both import "server".

    Compilation

    I currently use gomake with Makefiles. The Go installation comes with some great include files for make that simplify the creation of a package or a command. It's not hard and the best way to get up to speed with these is to just look at sample makefiles from open source projects and read "How to Write Go Code".