Understanding Dependency Management and Package Management in GOLang

Written by hackernoon-archives | Published 2017/07/12
Tech Story Tags: programming-languages | language | golang | go | programming

TLDRvia the TL;DR App

Introduction

GO is a new language and thanks to GO community, it has grown rapidly since the release of GO 1.0. yet, keeping its most fundamental principle of simplicity intact.

Like other programming languages, GO has the approach for dependency management like npm in Node.js, the pip in Python.

GO user and developer have been using go get all the while. And there were many tools like godep, glide etc. available to compensate the little shortcomings of go get tool. One of the tool is glide and we will see how to use glide for package management.

But in future GO community might see a better dependency tool currently under development github.com/golang/dep.

Here I will walk through how we use different tools for managing packages in GO.

Workspace

When we set up Golang, we have a single directory where $GOPATH is referencing to. This directory is our workspace, where all the thing about go begins. And the workspace structure looks like

-Work
  |
  -- bin/
  |
  -- pkg/
  |
  -- src/
      |
	    -- project1/
	    |
	    -- project2/

bin — It contains executable commands.

pkg — It contains package objects.

src — It contains source files.

$GOPATH

It is an environment variable which specifies the location of our workspace. Inside the directory $GOPATH/src we create a new directory for each project we start to work on.

This $GOPATH exists because:

  • All the import declaration in GO code references to a package through import path, and directories inside $GOPATH/src where go tool can compute all the imported packages.
  • To store the dependencies retrieved by go get.

Simplicity of GO GET

go get is the official GO tool to fetch GO code from a repository and store it in $GOPATH/src.

It provides isolation of packages with different import paths.

And in our source code, we just have to specify our compiler where it should go to get latest sources.

import
(
“fmt”
“github.com/gorilla/mux”
)

Before running the code we have to import the library using go get:

go get github.com/gorilla/mux

And it will install the latest commit from the master branch of GitHub repository, these packages are not limited to GitHub.

For example golang.org/x/mobile — libraries and build tools for GO on Android.

go get always fetches the latest code for any package which is not already on the disk.

GO GET Flags

go get also uses flag instruction such as [-u, -insecure, -d, -f, -t, -fix, -v.]

The -u flag instructs get to use the network to update the named packages and their dependencies.

go get -u github.com/gorilla/mux

The -insecure flag permits fetching from repositories and resolving custom domains using insecure schemes such as HTTP.

go get -insecure github.com/name/repo

The -d flag instructs get to stop after downloading the packages; that is, it instructs get not to install the packages.

The -f flag, valid only when -u is set, forces get -u not to verify that each package has been checked out from the source control repository implied by its import path. This can be useful if the source is a local fork of the original.

The -fix flag instructs the get to run the fix tool on the downloaded packages before resolving dependencies or building the codes.

The -t flag instructs get to also download the packages required to build the tests for the specified packages.

Shortcomings in GO GET

We see that the way GO saves all its dependencies, there are some problems in this approach of dependency management like:

  • We won’t be able to determine which version of package we need unless it is hosted in complete different repository as go get always fetches from the latest version of a package. This leads to problem when working as team we might end up fetching different version of a package.
  • And since go get installs package at $GOPATH/src directory so we will have to use the same version of a package for different projects as all our projects are under a single directory. So each of the projects will not have different versions of dependencies with them.

Package Management Using Glide

Now that we have seen how GO handles imports and manage packages and we also saw some of the difficulties a developer faces when handling dependencies. Let us tell you how to solve them.

There are many tools available to handle packages which have been used by GO developers like godep, glide etc. and we are going to explain the one we are using : GLIDE.

What is Glide?

Glide is a package management tool for GO language. It downloads dependencies from different sources and then locks the versions so that each team member gets an exact same version to download and updates the dependencies which do not break the project.

Installing Glide

It will get the latest release of glide and the script puts it in GO binaries ($GOPATH/bin or $GOBIN).

  • You can also install the latest release on Mac OS X using:

$ brew install glide

  • And on Ubuntu Precise (12.04), Trusty (14.04), Wily (15.10) or Xenial (16.04) you can install using PPA:

$ sudo add-apt-repository ppa:masterminds/glide && sudo apt-get update

$ sudo apt-get install glide

Using Glide

Initializing Dependency

Once we have installed Glide, we can go to our project folder and generate a glide.yaml file using:

package: nexdash-backend-go
import:
- package: github.com/gorilla/mux
  version: ^1.4.0
- package: github.com/jinzhu/gorm
  version: ^1.0.0
  subpackages:
- dialects/postgres

$ glide init

This scans the codebase in our project directory and creates a glide.yaml file containing the dependencies.

In each of the package, it reads the import in a GO file.

We can even edit glide.yaml and add information such as versions.

glide.yaml file contains two main things

  • It names the current package.
  • It declares external dependencies.

A glide.yaml file:

Here, it names the current package nexadash-backend-go and the imported libraries by it with their versions and the sub packages.

Updating Dependency

We can fetch dependency for our project and set them to specified versions in the glide.yaml file using:

$ glide up

This will install the latest dependency in the project directory matching the version information.

Glide will then create a lock file glide.lock, which contains all the dependency tree locked to specific commit ids.

Here, the dependency tree means all the dependency including sub-dependencies of dependencies.

A glide.lock file:

hash: e444b77a1ddd14f0737181e0f2dc1d4468f88db77b2e36cddde6c67547c39948
updated: 2017-06-14T13:56:26.916785921+5:30
imports:
- name: github.com/gorilla/context
  version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42
- name: github.com/gorilla/mux
  version: bcd8bc72b08df0f70df986b97f95590779502d31
- name: github.com/gorilla/gorm
  version: 5174cc5c242a728b435ea2be8a2f7f998e15429b
  subpackages:
   - dialects/postgres
- name: github.com/jinzhu/inflection
  version: 1c35d901db3da928c72a72d8458480cc9ade058f
- name: github.com/lib/pq
  version: 8837942c3e09574accbc5f150e2c5e057189cace
  subpackages:
  - hstore
  - oid
testImports: []

Installing Dependency

Now we have a glide.lock file with all the specified dependency and versions, we use $ glide install to install versions specified in the lock file.

Continue Reading The Full Article At — XenonStack.com/Blog


Published by HackerNoon on 2017/07/12