Saturday 22 December 2018

Setting up Go on Windows

Go (Golang) is installed on Windows via its msi installer available on Go's website. The latest version at the time of writing this article was 1.11.4 and the installer go1.11.4.windows-amd64.msi.



Installation is straightforward:







By default, installer creates or modifies the following environment variables:

In System space:

   Variable (created): GOROOT
   Value: C:\Go\
   Description: Go installation location.

   Variable (value appended): Path
   Value: C:\Go\bin
   Description: Go binaries location.


In User space:

   Variable (created): GOPATH
   Value: %USERPROFILE%\go
   Description: User's go workspace path.

   Variable (value appended): Path
   Value: %USERPROFILE%\go\bin
   Description: User's Go applications' binaries location.


Go workspace:
  • a directory with two subdirectories: bin and src
    • src typically contains all repositories with Go projects
    • bin contains built and then installed Go application binaries
  • can be set at arbitrary location; I set mine to C:\dev\go (and also set User space Path to C:\dev\go\bin)

Upon installation, C:\Go\bin contains three binaries:
  • go -  Tool for managing Go source code
  • godoc - Documentation tool; parses Go source code - including comments - and produces documentation as HTML or plain text
  • gofmt - Go source code formatter; uses tabs for indentation and blanks for alignment. 



Let's see what are the command line arguments of go tool:

>go
Go is a tool for managing Go source code.

Usage:

        go <command> [arguments]

The commands are:

        bug         start a bug report
        build       compile packages and dependencies
        clean       remove object files and cached files
        doc         show documentation for package or symbol
        env         print Go environment information
        fix         update packages to use new APIs
        fmt         gofmt (reformat) package sources
        generate    generate Go files by processing source
        get         download and install packages and dependencies
        install     compile and install packages and dependencies
        list        list packages or modules
        mod         module maintenance
        run         compile and run Go program
        test        test packages
        tool        run specified go tool
        version     print Go version
        vet         report likely mistakes in packages

Use "go help <command>" for more information about a command.

Additional help topics:

        buildmode   build modes
        c           calling between Go and C
        cache       build and test caching
        environment environment variables
        filetype    file types
        go.mod      the go.mod file
        gopath      GOPATH environment variable
        gopath-get  legacy GOPATH go get
        goproxy     module proxy protocol
        importpath  import path syntax
        modules     modules, module versions, and more
        module-get  module-aware go get
        packages    package lists and patterns
        testflag    testing flags
        testfunc    testing functions





If we already have some Go project in some Git repository (like GitHub), we can use get command to clone the given repository:

C:\dev\go\src>go get github.com/BojanKomazec/go-hello-world
package github.com/BojanKomazec/go-hello-world: no Go files in
C:\dev\go\src\github.com\BojanKomazec\go-hello-world

Repository is cloned to C:\dev\go\src\github.com\BojanKomazec\go-hello-world directory.

Repository shall be written without starting https:// as go get would report an error:

C:\dev\go\src>go get https://github.com/BojanKomazec/go-hello-world
package https:/github.com/BojanKomazec/go-hello-world: https:/github.com/BojanKomazec/go-hello-world: invalid import path: malformed import path "https:/github.com/BojanKomazec/go-hello-world": invalid char ':'

This my repository only has .gitignore and README.md files so let's add some code. First, let's create a directory named hello and in it a go file with the following content:

C:\dev\go\src\github.com\BojanKomazec\go-hello-world\hello\hello.go:

package main

import "fmt"

func main() {
   fmt.Printf("hello, world\n")
}


Building this file with:

C:\dev\go\src\github.com\BojanKomazec\go-hello-world\hello>go build

...creates a hello.exe file in the same directory and we can run it:

C:\dev\go\src\github.com\BojanKomazec\go-hello-world\hello>hello
hello, world

To install that build as a package, we have to run:

C:\dev\go\src\github.com\BojanKomazec\go-hello-world\hello>go install

This deploys application binary in C:\dev\go\bin directory.

go tool and Git

If we add, commit and then try to push hello.go file to remote repository, we'll be prompted by Git to enter our GitHub credentials as by default go get sets the https-based URL of the remote. We can verify that with:

C:\dev\go\src\github.com\BojanKomazec\go-hello-world>git remote show origin
* remote origin
  Fetch URL: https://github.com/BojanKomazec/go-hello-world
  Push  URL: https://github.com/BojanKomazec/go-hello-world
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

We can set SSH-based URL by executing:

>git remote set-url origin git@github.com:BojanKomazec/go-hello-world.git

Let's verify it:

C:\dev\go\src\github.com\BojanKomazec\go-hello-world>git remote show origin
Enter passphrase for key '/c/Users/komazec/.ssh/id_rsa':
* remote origin
  Fetch URL: git@github.com:BojanKomazec/go-hello-world.git
  Push  URL: git@github.com:BojanKomazec/go-hello-world.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

Let's now analyse code in the go source file above.

package main

func main() {
   ...
}


This line tells the Go compiler that the package should compile as an executable program. Its entry point will be function main(). If we were building a shared library, we would use package lib directive and there would not be main() function in the package.

import "fmt"
...
fmt.Printf("hello, world\n")

import statement imports a package into other package. Here, we wanted to use function which prints a string onto standard output. Such function, Printf, is available in the fmt package which comes from the Go standard library. Go compiler looks for standard library packages on paths specified in GOROOT and your and third-party packages on path specified in GOPATH environment variables.

Project on GutHub:

https://github.com/BojanKomazec/go-hello-world

References:

golang.org: Go installation on Windows
Understanding Golang Packages
Package “main” and func “main”

No comments: