reference:

packages:

Install

installare con umake

umake go

channels+goroutines

Probably the single most important capability of the language is the concurrency via channels and goroutines. you can obtain millisecond latency with them. Channels are great because you quickly and easily share state between "threads" by communicating, rather than using a big, fat, overused performance killer: a lock (a capability I really liked from Erlang).

In addition to channels, there are lightweight "threads" known as goroutines. Goroutines are scheduled within a given CPU process. When a certain goroutine is "blocked" because of a subsystem call, the Go scheduler will switch to another goroutine until the subsystem call is complete. This prevents blocking additional work like other single-threaded languages (PHP, Ruby), but also enables the code from a given goroutine to be synchronous instead of callback spaghetti (JavaScript)

One other advantage of goroutines is the ability to spin off work in an asynchronous fashion. In essence, we could write a piece of code and then call go MyMethod to invoke MyMethod asynchronously. The .NET CLR has only just started to see a few of these features as of v4.5 using keywords await+async. With Go, these capabilities were baked in from the start.

GOPATH

GOROOT is the location where Go compiler is installed on your system.

export GOROOT=/usr/local/go

GOPATH is the location of your work directory

mkdir $HOME/gocode
mkdir -p gocode/{bin,pkg,src}
vi ~/.bashrc
export GOPATH=$HOME/gocode;
# For convenience, add the workspace's bin subdirectory to your PATH:
export PATH=$PATH:$GOPATH/bin

set the PATH variable to access go binary system wide

cat << ! >> ~/.bashrc
> export GOPATH=$HOME/go
> export PATH=$GOPATH:$GOPATH/bin:$PATH
> !

per installare le dipendenze:

go get github.com/user/project
# altro metodo
go install github.com/user/hello
go build 01.go -o progname

inoltre è possibile compilare una cartella, output sarà il nome della cartella, l'entry point il file main.go

go build ./cmd/drive
# -x --verbose output
go build -x ./cmd/drive

verifica:

go version
go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/taz/go"
GORACE=""
GOROOT="/usr/lib/go-1.6"
GOTOOLDIR="/usr/lib/go-1.6/pkg/tool/linux_amd64"
GO15VENDOREXPERIMENT="1"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"

GOMAXPROCS

The GOMAXPROCS setting controls how many operating systems threads attempt to execute code simultaneously. For example, if GOMAXPROCS is 4, then the program will only execute code on 4 operating system threads at once, even if there are 1000 goroutines. The limit does not count threads blocked in system calls such as I/O.

The default setting of GOMAXPROCS in all Go releases before 1.5 is 1, because programs with frequent goroutine switches ran much slower when using multiple threads. It is much cheaper to switch between two goroutines in the same thread than to switch between two goroutines in different threads.

Goroutine scheduling affinity and other improvements to the scheduler have largely addressed the problem, by keeping goroutines that are concurrent but not parallel in the same thread.

At the same time, as core count continues to increase, not using additional cores by default puts Go at a disadvantage compared to other languages, especially in programs without high-frequency goroutine switching.

C libs import

//libfoo.c
// $ gcc -shared libfoo.c -o libfoo.so
#include "libfoo.h"
int foo() {
    return 1;
}
//libfoo.h
int foo();

Make sure you copy over the binary to /usr/lib/ and copy the header to /usr/include/.

package main
/*
#cgo LDFLAGS: -lfoo
#include <libfoo/libfoo.h>
*/
import "C"
import "fmt"
func main() {
    fmt.Println("From libfoo: ", C.foo())
}
go build 01.go

C libs import

//libfoo.c
// $ gcc -shared libfoo.c -o libfoo.so
#include "libfoo.h"
int foo() {
    return 1;
}
//libfoo.h
int foo();

Make sure you copy over the binary to /usr/lib/ and copy the header to /usr/include/.

package main
/*
#cgo LDFLAGS: -lfoo
#include <libfoo/libfoo.h>
*/
import "C"
import "fmt"
func main() {
    fmt.Println("From libfoo: ", C.foo())
}

prevenire collisioni di identificatori:

import (
  
urllib "net/url"
)
// var url non potrebbe essere definita normalmente, collide con pack net/url
url := urllib.QueryEscape(var);

leggere un file CSV:

package main
import ("bufio";"fmt";"os";"strings";"strconv")
totalVal := 0
f, _ := os.Open("./file.csv")
scanner := bufio.NewScanner(f)
for true{
    line, err := r.ReadString('\n')
    if(err != nil){break}
    data := strings.Split(line, ",")
    sval := strings.Replace(strings.Replace(data[1], "+", "", -1), "\"", "", -1)
    fval, _ := strconv.ParseFloat(sval, 32)
    totalVal += fval
}

check if a value exists(isset($a['key'])) before you use it:

value, ok = m[key]
if(ok) { fmt.Println(value) }

in Go you already specified that the array (or "map") "m" was of a certain type ("int"). So Go can return the "zero" value for that type (a "0") while PHP has no idea what you might be storing in $_POST it so it requires you to check for a value.

In fact, building on the fact that Go makes you s-p-e-l-l-o-u-t what types you plan on storing it your variables you can do neat things like increment any zero'ed number value of any array, slice, or map even if the element doesn't exist yet. Take the following code that counts the number of times a word appears inside a string.

string_array := strings.Fields(s)
counts := make(map[string]int) // auto init to 0
 
for _, v := range string_array {
    counts[v]++ // No need to do "count[v] = 0" first
}

Formatting dates:

print date("d/m/Y H:ia");
fmt.Println(time.Now().Format("2/1/2006 at 3:04pm"))
fmt.Println(time.Now().Format("Mon, Jan 2, 2006 at 3:04pm"))
fmt.Println(time.Now().Format("Monday at 3:04pm"))

classes:

In Go, you create your class (called a struct) with all properties and then add in methods later (like you can do in Javascript).

// define Dog class
type Dog struct {
    Name  string
    Color string
}
 
// Method for the "Dog" object called "Call"
func (d Dog) Call() {
    fmt.Printf("Come here %s dog, %s", d.Color, d.Name)
}
 
Spot := Dog{Name: "Spot", Color: "brown"}
Spot.Call()

type casting

type Barrable interface {
  Bar()
}
barrable, ok := foo.(Barrable)
if ok {
  barrable.Bar()
}

Variant type / Union Types / Algebraic data types

package main
import "fmt"
func main() {
    a_test := []interface{}{"x", 124, true}
    for i, v := range a_test {
        fmt.Printf("%d: %v\n", i, v)
        switch v.(type) {
        case int:
            fmt.Printf("int: %d\n", v.(int))
        case string:
            fmt.Printf("string: %s\n", v.(string))
        case bool:
            fmt.Printf("bool: %t\n", v.(bool))
        }
    }
}

JSON

$input json_encode($a_in);
$output json_decode(`gobinary $input`);
package main
 
import "fmt"
import "encoding/json"
import "os"
 
type Message struct {
    Name string
    Body string
    Time int64
}
func usage() {
    fmt.Fprintf(os.Stderr, "usage: %s [inputfile]\n", os.Args[0])
    flag.PrintDefaults()
    os.Exit(2)
}
func main() {
    if len(os.Args) == 1 {
        fmt.Println("Input data missing.");
        os.Exit(1);
    }
    fmt.Printf("input data: %s\n", os.Args[1]);
    input_str := os.Args[1]
    input_str := `{"Name":"Bob","Food":"Pickle"}`
    b := []byte(input_str)
    var m Message
    err := json.Unmarshal(b, &m)
    if err != nil {
        log.Fatal("Unmarshal failed", err)
    }
    map_d := map[string]int{"a": 5, "b": 7}
    map_b, _ := json.Marshal(map_d)
    fmt.Println(string(map_b))
}

unmarshal senza tipo specifico:

package main
import "encoding/json"
import "fmt"
func main() {
    var data interface{}
    err := json.Unmarshal([]byte(`{"foo":1, "bar":[10, "apples"]}`), &data)
    if err == nil {
        fmt.Println(data)
    } else {
        fmt.Println(err)
    }
    sample := map[string]interface{}{
        "blue":  []interface{}{1, 2},
        "ocean": "water",
    }
    json_string, err := json.Marshal(sample)
    if err == nil {
        fmt.Println(string(json_string))
    } else {
        fmt.Println(err)
    }
}

composite data types

package main
import "encoding/json"
import "fmt"
type Person struct {
    Name string   `json:"name"`
    Age  int      `json:"age,omitempty"`
    Addr *Address `json:"address,omitempty"`
    Ph   []string `json:"phone,omitempty"`
}
type Address struct {
    Street string `json:"street"`
    City   string `json:"city"`
    State  string `json:"state"`
    Zip    string `json:"zip"`
}
func main() {
    // compare with output, note apt field ignored, missing fields have zero values.
    jData := []byte(`{
        "name": "Smith",
        "address": {
            "street": "21 2nd Street",
            "apt": "507",
            "city": "New York",
            "state": "NY",
            "zip": "10021"
        }
    }`)
    var p Person
    err := json.Unmarshal(jData, &p)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Printf("%+v\n  %+v\n\n", p, p.Addr)
    }
    // compare with output, note empty fields omitted.
    pList := []Person{
        {
            Name: "Jones",
            Age:  21,
        },
        {
            Name: "Smith",
            Addr: &Address{"21 2nd Street", "New York", "NY", "10021"},
            Ph:   []string{"212 555-1234", "646 555-4567"},
        },
    }
    jData, err = json.MarshalIndent(pList, "", "    ")
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(string(jData))
    }
}

Cross compile

dopo aver installato compiler e linker per win32

GOOS=windows GOARCH=386 go build -o hello.exe hello.go
# aggrega assets
rm -f bindata.go
go-bindata -ignore=\\.gitignore -ignore=\\ignoredir -ignore=\\.gitkeep static/...
 
gox -osarch="darwin/amd64 darwin/386 linux/amd64 linux/386 windows/amd64 windows/386" -output="./bin/pgname_{{.OS}}_{{.Arch}}"

è possibile compilare per mobile

Raspberry Pi Cross compile

there are several ARM versions supported by the Go compiler, but we’re looking for version 5.

env GOOS=linux GOARCH=arm GOARM=5 go build

Go with GVM(Go Version Manager)

While Ubuntu 12.04 has Go packages available to install in their default repositories, Martini requires Go version 1.1 or later to function correctly, Ubuntu often is outdated.

gvm install a recent version of go.

sudo apt-get update
sudo apt-get install curl git mercurial make binutils bison gcc
bash < <(curl -s https://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer)

To use gvm to install a Go version, we first need to source the script so that our current shell session has the scripts available:

.bashrc

source ~/.gvm/scripts/gvm
gvm install go1.2
gvm use go1.2 --default

GOB

serialization lib:

package main
import (
  "encoding/gob"
  "fmt"
  "os"
)
func main() {
  data := []int{101, 102, 103}
  // create a file
  dataFile, err := os.Create("integerdata.gob")
  if err != nil {
    fmt.Println(err)
    os.Exit(1)
  }
  dataEncoder := gob.NewEncoder(dataFile)
  dataEncoder.Encode(data)
  dataFile.Close()
}
package main
 import (
         "encoding/gob"
         "fmt"
         "os"
 )
 func main() {
         var data []int
         dataFile, err := os.Open("integerdata.gob")
         if err != nil {
                 fmt.Println(err)
                 os.Exit(1)
         }
         dataDecoder := gob.NewDecoder(dataFile)
         err = dataDecoder.Decode(&data)
         if err != nil {
                 fmt.Println(err)
                 os.Exit(1)
         }
         dataFile.Close()
         fmt.Println(data)
 }

Zlib Compression

 package main
 import (
         "bufio"
         "bytes"
         "compress/zlib"
         "flag"
         "fmt"
         "io/ioutil"
         "os"
 )
 func main() {
         flag.Parse() // get the arguments from command line
         filename := flag.Arg(0)
         if filename == "" {
                 fmt.Println("Usage : go-zlib sourcefile")
                 os.Exit(1)
         }
         rawfile, err := os.Open(filename)
         if err != nil {
                 fmt.Println(err)
                 os.Exit(1)
         }
         defer rawfile.Close()
         // calculate the buffer size for rawfile
         info, _ := rawfile.Stat()
         var size int64 = info.Size()
         rawbytes := make([]byte, size)
         // read rawfile content into buffer
         buffer := bufio.NewReader(rawfile)
         _, err = buffer.Read(rawbytes)
         if err != nil {
                 fmt.Println(err)
                 os.Exit(1)
         }
         var buf bytes.Buffer
         writer := zlib.NewWriter(&buf)
         writer.Write(rawbytes)
         writer.Close()
         err = ioutil.WriteFile(filename+".zlib", buf.Bytes(), info.Mode())
         // use 0666 to replace info.Mode() if you prefer
         if err != nil {
                 fmt.Println(err)
                 os.Exit(1)
         }
         fmt.Printf("%s compressed to %s\n", filename, filename+".zlib")
 
 }
package main
 import (
         "compress/zlib"
         "flag"
         "fmt"
         "io"
         "os"
         "strings"
 )
 func main() {
         flag.Parse() // get the arguments from command line
         filename := flag.Arg(0)
         if filename == "" {
                 fmt.Println("Usage : unzlib sourcefile.zlib")
                 os.Exit(1)
         }
         zlibfile, err := os.Open(filename)
         if err != nil {
                 fmt.Println(err)
                 os.Exit(1)
         }
         reader, err := zlib.NewReader(zlibfile)
         if err != nil {
                 fmt.Println(err)
                 os.Exit(1)
         }
         defer reader.Close()
         newfilename := strings.TrimSuffix(filename, ".zlib")
         writer, err := os.Create(newfilename)
         if err != nil {
                 fmt.Println(err)
                 os.Exit(1)
         }
         defer writer.Close()
         if _, err = io.Copy(writer, reader); err != nil {
                 fmt.Println(err)
                 os.Exit(1)
         }
         fmt.Println("Decompressed to ", newfilename)
 }

GDB

go build -gcflags "-N -l" -o test_pgm main.go
gdb test_pgm
....
(
gdbsource /usr/local/src/go/src/runtime/runtime-gdb.py
Loading Go Runtime support
.