Go (Golang)

Introduction

Compiled - Go 1.5 and above enable native cross compilation on a system i.e.: on a mac declare env vars like GOOS=linux GOARCH=amd64go build will then build an executable for a Linux OS on the host machine running OS X.
On Windows add export GOOS= export GOARCH export
Object Oriented
Native support for Multiple cores
Network oriented/friendly
Manages memory / Garbage collecting
Clean syntax as scripting lang / low level language
Multi OS very portable
Procedural language where procedures equals functions, stitched together into a whole program
Can do what node.js does server side
Semicolons automatically included and placed by the compiler / 2 statements on the same line equals a semicolon to differentiate them
Package Declaration 1st line:
"package main" where main refers to the folder containing the go program(s), code, application(s) Can be organized by folder for program types and purposes, i.e.: crypto, system, network, webapp etc…
Import on second line:
"import" enables us to import pre-existent code into the program: we can import procedures (functions) and whole other GO programs, import packages from standard and third parties libraries
fmt.Println where package is fmt and the function is print line as in Println Print just sequentially prints the content Println adds a new line to the standard output render
Packages catalogue in standard library (and more for third parties at http://godoc.org ) https://golang.org/pkg/#stdlib
Every procedures (functions) are explained and documented for each package
Replace PKG in URL with src to access the source code of a package
No Polution in Code
Package declaration:
Import statement (s) i.e.:
import "fmt"
Or:
import ( fmt" "unicode/utf8" "strings" "strconv" ) Go will not allow code pollution use what you import or don't import it at all


Installation

Set variables:
GOROOT if go itself is installed somewhere else than default
GOPATH pointing to Go sources and workdirs WORKSPACE
GOBIN pointing to bin directory inside Go Workspace
go help + command = Documentation
Environment variables:
export PATH=$PATH:/sbin echo $PATH Set Go binary PATH system-wide in /etc/profile
export PATH=$PATH:/usr/local/go/bin User environment PATH declaration in ~/.profile
For our workspace to work with Go and the rest of the system programs whereas it remains private as our own workspace
export GOPATH=$HOME/workspaces/gocode export PATH=$HOME/workspaces/gocode/bin:$PATH The last $PATH is for go can know where are the other programs on the system
go help environment <== for a comprehensive help about environment variables in GO


Basic Commands

go run needs a file name, eg, go run main.go
go build for an executable: builds the file, reports errors, if any. If there are no errors, it puts an executable into the current folder.
for a package: builds the file, reports errors, if any. And throws away binary.
go install for an executable: compiles the program (builds it), names the executable the folder name holding the code, puts the executable in workspace / bin.
$GOPATH/bin for a package: compiles the package (builds it), puts the executable in workspace / pkg
$GOPATH/pkg makes it an archive file
go clean cleans folders (Add more information)

Go FMT Verbs and Escape characters

Format verbs examples:
Formatting in HEX CAPS with 0x prefix:
%#x
%#X
Formatting in DECIMALS:
%d
Formatting in BINARY:
%b
Formatting in text encapsulated in '…' with a safe return to a new line:
%q Escape characters:
Adds a tabulation:
\t
Adds a return to a new line afterwards:
\n


Installing over SSH

ssh root@debsrv05s 'cd /usr/local && wget \ https://storage.googleapis.com/golang/go1.8.1.linux-amd64.tar.gz && \ tar -xzvf go1.8.1.linux-amd64.tar.gz && go version && rm -f go1.8.1.linux-amd64.tar.gz' Then the environment variables can be applied remotely with the content of variables or of a file to happen to .profile Obviously the command above needs to be modified with the proper server name and the current Go-Lang version.


Basic Concepts

Base formating

Our very first package. Folders organization:
~/Workspaces/gocode/src/github/go-lang-training$ ls -lR first_package/ first_package/: main stringutil first_package/main: main.go first_package/stringutil: name.go reverse.go reverseTwo.go

But before a little formating with fmt

package main import "fmt" func main() { fmt.Printf("%d \t %b \t %#x \n", 2048, 2048, 2048) // Decimal d, Binary b, Hexadecimal x // Print some numbers base formated \t is new line }

stringutil/main.go

package main import ( "fmt" "github.com/t0m-a/golangex/firstPackage/stringutil" ) func main() { fmt.Println(stringutil.Reverse("!og, og, oG !olleH")) fmt.Println(stringutil.MyName, stringutil.MyPlace) } // Calling to functions we packaged in first_package/stringutil/name.go // reverse.go // function.Variable

name.go

package stringutil // MyName declared as a variable and assigning Tom as its value var MyName = "Tom" // MyPlace declared with assigned value of 127.0.0.1 var MyPlace = "@127.0.0.1"

reverse.go

// Package stringutil we are calling for a package of our own containing functions for working with strings. package stringutil // Reverse returns its argument declared with (s string) processed by // the function reverseTwo func Reverse(s string) string { return reverseTwo(s) }

reverseTwo.go

package stringutil func reverseTwo(s string) string { r := []rune(s) for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } return string(r) }
Remainder

remainder symbol is % in a variable value

package main import "fmt" //remainder symbol is % in a variable value func main() { // 4 divided by 2 makes 2 and remains 0 quotient := 4 / 2 fmt.Printf("%d \t", quotient) fmt.Println("ient) remainder := 4 % 2 fmt.Printf("%d \t", remainder) fmt.Println(&remainder) // 5 contains two times 2 and it remains 1 quotient2 := 5 / 2 fmt.Printf("%d \t", quotient2) fmt.Println("ient2) remainder2 := 5 % 2 fmt.Printf("%d \t", remainder2) fmt.Println(&remainder2) // How many times is there the number 3 in 4999 var quotient3 float32 quotient3 = 4999 / 3 fmt.Printf("%f \t", quotient3) // %f is format verb for floating numbers fmt.Println("ient3) // Answer is 1666 times // How many remains var remainder3 float32 remainder3 = 4999 % 3 fmt.Printf("%f \t", remainder3) fmt.Println(&remainder3) // and 1 time 3 remains that cannot be contained in the quotient // It's logical, mathematical would give 1666,333333 etc... // Remainder are usefull to check if a number is odd or even (impair ou pair) }


Loop and Print

package main import "fmt" func main() { for i := 0; i < 200; i++ { fmt.Printf("%d \t %b \t %x %q \n", i, i, i, i) } }


Variables and Constants

Declare and initialize variables

Variables

Mémo de cours et exercice

Dans le dossier Declare_and_Init se trouve un exercice commenté expliquant et mettant en pratique la déclaration, l'assignation et l'affichage de variables sur la sortie standard. La déclaration et l'assignation de variables peut être multiple. Une variable à zero ou nul est une variable déclarée mais non assignée. 2 façon de déclarer sont à préférer: - shorthand /!\ UTILISABLE QUE DANS UNE FUNC - var i.e.: // DECLARATION de variables selon la méthode shorthand qui N'EST UTILISABLE QUE A L'INTERIEUR D'UNE FUNC var a int // var déclarée soit nomée a, et qui a pour type int (nombre intègre) var b string // var déclarée (soit nomée) b, et qui a pour type string (chaîne de catactères) var c float64 // de type nombre décimal DOUBLE-PRECISION FLOATING-POINT FORMAT (FLOAT64) SÉPARÉ PAR UN POINT (et non pas par une virgule) var d bool // ... de type bolean true or false aKa yes or no ou plutôt 1 ou 0 ;) // DECLARATION et ASSIGNATION de variables MULTIPLES var e, f string = "je suis le contenu de la var e", "je suis le contenu de la var f" // /!\ ASSIGNATION /!\ de la valeur à une variable précédement déclarée (nomée) et typée a = 7 b = "couscous" c = 3.1415 d = true

declare_and_initialize/main.go

package main import "fmt" func main() { // DECLARATION de variables selon la méthode shorthand qui N'EST UTILISABLE QUE A L'INTERIEUR D'UNE FUNC var a int // var déclarée soit nomée a, et qui a pour type int (nombre intègre) var b string // var déclarée (soit nomée) b, et qui a pour type string (chaîne de catactères) var c float64 // ... de type nombre décimal DOUBLE-PRECISION FLOATING-POINT FORMAT (FLOAT64) SÉPARÉ PAR UN POINT (et non pas par une virgule) var d bool // ... de type bolean true or false aKa yes or no ou plutôt 1 ou 0 ;) // DECLARATION et ASSIGNATION de variables MULTIPLES var e, f string = "je suis le contenu de la var e", "je suis le contenu de la var f" // /!\ ASSIGNATION /!\ de la valeur à une variable précédement déclarée (nomée) et typée a = 7 b = "couscous" c = 3.1415 d = true // AFFICHE LE TYPE déclaré de la variables avec un retour chariot, virgule le nom de la variable // dont on affiche le type // %T permetant d'afficher ou représenter le Type T de la variable fmt.Println("Affichons le type T de nos variables :") fmt.Printf("%T \n", a) fmt.Printf("%T \n", b) fmt.Printf("%T \n", c) fmt.Printf("%T \n", d) fmt.Printf("%T \n", e) fmt.Printf("%T \n", f) // AFFICHE LA VALEUR assignée de la variables avec un retour chariot, virgule le nom de la variable // dont on affiche la valeur // %v permetant d'afficher ou représenter la Valeur V de la variable dans son format par défaut fmt.Println("Affichons la valeur V de nos variables :") fmt.Printf("%v \n", a) fmt.Printf("%v \n", b) fmt.Printf("%v \n", c) fmt.Printf("%v \n", d) fmt.Printf("%v \n", e) fmt.Printf("%v \n", f) // Une autre façon d'afficher type et valeur mais sur la même ligne de la STDOUT // avec deux ou trois \t tabulation pour l'alignement // et un \n pour le retour à la ligne fmt.Println("Affichons le type T et la valeur V de chacune de nos variables sur la même ligne pour chacune :") fmt.Printf("%T \t \t \t %v \n", a, a) fmt.Printf("%T \t \t \t %v \n", b, b) fmt.Printf("%T \t \t %v \n", c, c) fmt.Printf("%T \t \t \t %v \n", d, d) fmt.Printf("%T \t \t \t %v \n", e, e) fmt.Printf("%T \t \t \t %v \n", f, f) }

Constants

package main import "fmt" // Constants aKa CONST is a SIMPLE UNCHANGING (in the program) VALUE const p string = "granit" const r = 4096.556 // work as const r string = would work. As much as const r = "4096 or mémé or 4678,0" would work. // The comma expressed decimal number needs double quotes around it otherwise use a dot const r = "3,14" // VERSUS const r = 3.14 // It can be named or defined as: const conR = or const conDistanceTo = ... // etc... conXXX enabling to differenciate it for a variable // Declaring multiple constants at once ex: const ( // All these three above aligned with tabulation so the code is cleaner to read, // BTW PREFERE COMMENTING RIGHT ABOVE WHAT YOU ARE COMMENTING with NO EXTRA LINE pi = "3,1415" pi2 = 3.1415 language = "Go lang! GO !" // L : where we see how to style our code according to lint and elegant GO writting. // This comment MUST start with the name of the constant (work with anything you need to export) // It seems like a way to force good commenting habits for all exports outside the scope // so that the whole program can be easily maintainable and readable L = "see what Go says when using a Capital Letter as the first letter used when declaring a constant" // Now we are done with Export or non export let's have a look at /!\ iota /!\ whatsaniota = iota // 4 thisisaniota = iota // 5 incaseyoumissedit = iota // 6 because first const pi is 0, pi2 is 1 and so on ) const ( x = iota // 0 because IOTA RESETS when we use a new block of declared constants y = iota // 1 and so on ) const ( // Now we are using a BLANK IDENTIFIER to ommit the IOTA 0 _ = iota // which value is 0 which we ignore with the BLANK IDENTIFIER g = iota * 10 // 1*10 h = iota * 10 // 2*10 and so on i = g * h // AWESOME !!! We can multiply constants by themselves k = i * i ) func main() { const q = 42 const s = "3,1415" const t bool = false fmt.Println("p - ", p) fmt.Println("q - ", q) fmt.Println("r - ", r) fmt.Println("s - ", s) fmt.Println("t - ", t) // Aligned with tab so it's cleaner to read on STDOUT fmt.Println("Pi the \"european way\" \t - ", pi) fmt.Println("Pi the \"US\" way \t - ", pi2) fmt.Println("Language is - \t \t", language) fmt.Println("L - ", L) fmt.Println("whatsaniota - ", whatsaniota) fmt.Println("thisisaniota - ", thisisaniota) fmt.Println("incaseyoumissedit - ", incaseyoumissedit) fmt.Println("x - ", x) fmt.Println("y - ", y) fmt.Println("g - ", g) fmt.Println("h - ", h) fmt.Println("i - ", i) fmt.Println("k - ", k) }

Bitwise operations

package main import "fmt" const ( _ = iota // 0 ignored kb = 1 << (iota * 10) // 1 is shifted << by iota times ten (1 * 10) mb = 1 << (iota * 10) // 1 << (2 * 10) The bit 1 is shifted by 2 * 10 positions // on the 2 to the power of n table of calcul gb = 1 << (iota * 10) tb = 1 << (iota * 10) ) func main() { fmt.Println("binary\t\t\t\t\t\t\tdecimal") fmt.Printf("%b\t\t\t\t\t\t%d\n", kb, kb) fmt.Printf("%b\t\t\t\t\t%d\n", mb, mb) fmt.Printf("%b\t\t\t\t%d\n", gb, gb) fmt.Printf("%b\t\t%d\n", tb, tb) }


Scopes and Wrappers

package main import "fmt" /* wrapper will enable us to return a function "as a value", the second func is currently an anonymous func and will be assigned (named) later on. /!\ x= 0 is an OUTER SCOPE level assigned variable /!\ it will be remembered in the whole block scope contained in between the bracie { from line 8 to the closing } on line 14. We could have use this var x in many other func as long as these func would have been enclosed in the BLOCK starting on the end of LINE 10. /!\ From the opening bracie on LINE 13 we have our INNER SCOPE /!\ */ func wrapper() func() int { x := 0 return func() int { x++ return x } } func main() { increment := wrapper() // We are assigning the anonymous func its value or name // which is increment CALLED EXPRESSING A FUNCTION aKa func expression fmt.Println(increment()) // We are calling to the now assigned func increment. // As increment is a func it gets() right after it, // cause it has to execute stuff (what's on line 6 to 8) fmt.Println(increment()) }


Memory Addresses

README.md - Notes from courses

(also contained in coding exercises in the subdirs)

Referencing a memory pointer, dereferencing and reassigning variables

In go, & indicate memory address. &a means the memory address where the value of var a is stored.
/!\ VAR TYPE /!\ POINTER TO AN INT *int which means we point to the memaddress where the VALUE of b is stored.
a := 43 var bee *int = &a If we declare bee as = &a - bee will be automatically be inferred from context as of type *int (pointer to an int) *int -- the * is part of the type -- bee is of type *int Here, we are REFERENCING a VALUE (making a pointer to its memaddress) "*" Is always an operator * here means "pointer to" (an int) The above code makes bee a pointer to the memory address where an int is stored and bee is of type "int pointer" bee is of type "pointer to an int" which has for VALUE the memory address of where the value of var a is stored while *bee is DEREFERENCING the variable bee, meaning here we get the ACTUAL CONTENT of the value of bee stored in the memory Here the * means dereferencing which gives us the actual content in a pointer memory address.
In other words: to see the value in that memory address, add a * in front of b : this is known as dereferencing,
the * is an operator in this case.

REASSINGING the value of a variable:
*b = 42 // *b means: change the value of b to whatever you need, here it's 42 From now on as we have reassigned the value of *b (star b, it's important)
*b is equal to the reassigned value 42 AS MUCH AS TO THE VALUE OF VAR a.
as b is equal to the memaddress of a ==> &a, and dereferenced b or *b is equal to the value of a.
So from now on the VALUE of var a will be the reassigned value of our dereferenced b ==> *b
fmt.Println(a) // Will return 42 as THE NEWLY ASSIGNED VALUE of the var a

Courses input on reassigning a value to a memory address:

- this is useful - we can pass a memory address instead of a bunch of values, we can pass a reference - and then we can still change the value of whatever is stored at that memory address - this makes our programs more performant - we don't have to pass around large amounts of data - we only have to pass around addresses - everything is PASS BY VALUE in go, btw - when we pass a memory address, we are passing a value /* Referencing a memmory pointer, dereferencing and reassigning while having fun multiplying vars with each other, formating the results and making functions Overkill func and vars just for example and exercise NEVER CODE THIS UGLY WAY This is kind of a COURSES MEMO */ import "fmt" // Variables which need to be used file scope wide must be outside any function block, // preferably at the begining if already known at that point, to ease reading // If var was captial A it would have been exported: useable package wide var a = 3 // DECLARE+ASSIGN: declared var a of type int with assigned value of 300 var b = 4 var c *int = &a // /!\ REFERENCING a variable POINTER. &a equals *c (line 19,20) // THIS IS FOR EXAMPLE ONLY var d *int = &b // Go prefer var d = &b and will infer type is of POINTER TO AN INT // because it reads &something, it infers from right-hand side // Any secondary function used in main must be declared prior to it->file scope, must respect anorder: // First known (declared) and then useable func showofa() { fmt.Println(&a, "\t", a) fmt.Println(*c) // /!\ DEREFERENCING a pointer to an int, getting its ACTUAL VALUE for var a (3) } func showofb() { fmt.Println(&b, "\t", b) fmt.Println(*d) } func main() { var result int result = a * b showofa() showofb() fmt.Println(result, "\t \t", &result) *c = 2 // This means REASSIGNING a value of 2 to the DEREFERENCED var a // hence &a = c and *c = actual value of a var newresult int newresult = a * b fmt.Println(a) fmt.Println(newresult, "\t \t", &newresult) /* More explanation needed? See the courses notes in ../reference_dereference_reassign/main.go - tom */ }