Using Go

Go Fundamentals


Authors

Designed by Ken Thompson, Rob Pike and Robert Griesemer. Ken Thompson helped design C, Unix, UTF-8. Rob Pike also worked on Unix and UTF-8. Robert Greisemer created the Hotspot JVM.

Motivation

To address the following:

  • Efficient compilation
  • Efficient execution
  • Ease of programming

At Google the use of C++, Java and Python did not give all the three behaviors combined.

Python (Efficient compilation, ease of programming)
C++ (Efficient execution)
Java (Better compilation than C++)

The authors (while at google) therefore created Go which aims to provide efficient compilation, efficient (fast) execution, and be simple to program in.

More details:
https://app.pluralsight.com/library/courses/go-big-picture

Setup

Visual Studio Code


Add Go extensions

Ctrl + Shift + X

Go (Microsoft extensions)

Ctrl + Shift +  P

go install/update

select all tick box -> ok


Path Set up

You can also run VS Code from the terminal by typing 'code' after adding it to the path.

Launch VS Code. Open the Command Palette (Ctrl+Shift+P) and type 'shell command' to find the Shell Command: Install 'code' command in PATH command

Auto Save

Settings: Ctrl + ,

Files: Auto Save > onFocusChange

Terminal

Ctrl + Shift + '

Debug/Run

Ctrl + F5

Click on configure cog wheel.  Change  "program": "${fileDirname}" to  "program": "${file}"

Ctrl + Shift + F5 (Stop Debug)

Golang Installation

https://golang.org/dl/

Install to C:\go

Add Workspace

Eg %USERPROFILE%\code\go-ws

Create bin, pkg and src folder here

Set environment variable GOPATH to point to the go workspace

In gitbash:

setx GOPATH ~/code/go-ws

Run

go get github.com/golang/example/hello

$GOPATH/bin/hello

Hello, Go examples!

More details:
https://app.pluralsight.com/library/courses/getting-started-with-go

Modules

https://app.pluralsight.com/player?course=getting-started-with-go&author=mike-vansickle&name=c9efb374-e78a-4224-b854-bc89c3c0b5be&clip=4&mode=live

$ go mod init gitlab.com/lightphos/codeclub/server

If you get this
go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'

then
$ export GO111MODULE="on"

and try again

then

$ go build .


$ ls
go.mod  main.exe  main.go  server.exe

$./server.exe

On windows, the server will not run if there is another process with the same name already running.                                                                

Testing

To add unit tests right click on function select

generate unit tests

May be prompted to install extensions, go ahead and install.

This will create a corresponding <>_test.go file

$ go test *.go

Coverage

go test -cover

Performance (Benchmark)

Documentation

Simple Web Server

Create a file main.go in directory $GOPATH/src/gitlab.com/lightphos/codeclub

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", HelloServer)
    http.ListenAndServe(":8080", nil)
}

// HelloServer server
func HelloServer(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}

go run main.go

point your browser to http://localhost:8080/coders

Basic Constructs


https://devhints.io/go


Primitives

Declaration:

var i int
i = 1

or

var f float32 = 2.178

or

s := "String"

Note you must use a variable if declared otherwise the compiler will complain.

Some other types:

string, complex, byte, uint

Pointers

 *  - contents of an address (a reference)

 & - address of a value/variable

i := 7
p := &i // address of i
fmt.Println(*p) // print out the contents of the address at p
*p = 9  // change the contents of the address at P to 9
fmt.Println(i) // i is now 9

z := &p

fmt.Println(**z)
> 9

However unlike C/C++ no pointer arithmetic.


Constants

const Pi = 3.1415

const c int = 1

With Iota

const (
  a = iota // 0
  b = iota // 1
  c	   // 2 - no need to keep writing iota
)

// increments the const variables if they within a common const block

fmt.Println(a, b, c)
> 0 1 2

Collections

Arrays, Slices, Maps, Structs

	var arr [3]int
	arr[0] = 1
	arr[1] = 2
	arr[2] = 3

or
	arr := []int{1, 2, 3}
	fmt.Println(arr)
	$ [1 2 3]

Arrays are fixed length while slices can be extended

Slice from array
	slice := arr[:]  // from 0 to the end
Slice from scratch
	slice := []int{1,2,3}

Extend
	slice = append(slice, 4, 5)

Select parts
	s2 := slice[1:] from 1 to end
	s3 := slice[:2] // from 0 to < 2
	s4 := slice[2:5] // from 2 to 4
                                    
m := map[string]int{"a":11, "b":12}  // key is string value is int
fmt.Println(m["b"]) // 12

delete(m, "a") // remove entry

Struct a collection of possibly different types.

type User struct {
	id int
	name string
}
fred := User{1, "Fred Flintstone"}
fred.id = 2
wilma := User{name:"Wilma Flintstone"}
pebbles := &User{3, "Pebbles Flintstone"}
fmt.Println(pebbles)
> &{3 Pebbles Flintstone}
(*pebbles).id = 4 // or
pebbles.id = 4

Functions/Methods

func afunc() {
   fmt.Println("a func")
}


// func afunc(s string) // cannnot overload !!!

Method modifies a struct

func (u User) afunc() {
  fmt.Println(u)
}

func (u User) concat(s string) {
   fmt.Println(u.name, s)
}

pebbles.concat(s)

> Pebbles Flintstone was here
fmt.Println(pebbles)
> &{2 Pebbles Flintstone} # no change to original struct

To modify struct use a pointer

func (u *User) change(name string) {
   u.name = name
}

pebbles.change("new name")
fmt.Println(pebbles)
> &{2 new name}  # struct modified

To make a function/method/struct public the initial letter of the name needs to be in capitals, this includes any fields in a struct.

func (u User) Concat(s) ....

Control

if name == "name" {
  fmt.Println("name is name")
}

if u := User{1, "name"}; u.name == "name" {
  fmt.Println("username is name")
}

Packages

All go programs need a package. If main then an executable will be created. The main function being the entry point. If any other package than an archive (.a) file will be created in the pkg directory.

src -> domain -> user.go

package domain

import "strings"

type User struct {
	Id   int
	Name string
}

func (u User) Upper() User {
	u.Name = strings.ToUpper(u.Name)
	return u
}

package reflects directory in which the code lives, though not necessarily (as in main).

Note the method has init caps to be publicly accessible. Lowercase methods are accessible if in the same package.

The Upper method has no parameters but returns User.

Another way would be to modify the structure using a pointer *User.

func (u *User) ChangeToUpper() {
    u.Name = strings.ToUpper(u.Name)
}

Usage: Note the import. With the correct extensions VSC will auto import.

package main

import (
	"fmt"

	"gitlab.com/lightphos/codeclub/domain"
)

func main() {
	u := domain.User{1, "name"}
	fmt.Println(u.Upper())
	
	un := domain.User{2, "new name"}
	un.ChangeToUpper()
	fmt.Println(un)
}

> {1 NAME}
> {2 NEW NAME}

Packages can be committed to repositories such as Github,  and a copy is downloaded using go get '=<repo url>

Modules and Versioning

go mod init
go mod edit -require github.com/wilk/uuid@0.0.1

Interfaces

Collection of methods that an object can meet and therefore be a type of that interface.

package access

type OID string

type Info struct {
   Item string
}

type Access interface {
  Open()
  Close()
  Find(oid OID) (Info, error)
}

To 'implement' the interface Access, all you need to do is provide all the methods in the interface.

type Db struct {
   id int
}

func (db Db) Open() {
	fmt.Println("Open")
}

func (db Db) Close() {
	fmt.Println("Close")
}

func (db Db) Find(oid OID) (Info, error) {
	inf := Info{"item"}
	return inf, nil
}

func DbEngine() {
	var a Access = Db{1}  // Db can be assigned to Access type
	a.Open()
	f, _ := a.Find("s")
	fmt.Println(f)
	a.Close()
}

Defer, will run the a.Close at the end of the scope of the function:

func DbEngine() {
	var a Access = Db{1}  // Db can be assigned to Access type
	defer a.Close()
	a.Open()
	f, _ := a.Find("s")
	fmt.Println(f)
}

Common Libraries

https://golang.org/pkg/

https://golang.org/pkg/strings/#pkg-overview

https://golang.org/pkg/net/http/

Go with VueJS

VueJs

Install chocolatey <https://chocolatey.org/>

Then node

choco install nodejs-lts   (10.6.0)

Then

npm install vue -g

Wails (Desktop)

https://medium.com/js-dojo/building-a-desktop-app-in-go-using-wails-b7f5825f986a

Mongo

 

CockroachDb

Google App Engine Server

See appengine-hello in src/github/golang/example

https://cloud.google.com/appengine/docs/go/#Go_tools