Schema del linguaggio Go
Go (noto anche come Golang) è un linguaggio compilato e tipizzato staticamente sviluppato da Robert Griesemer, Rob Pike e Ken Thompson presso Google. La sintassi di Go è simile al C, ma offre: sicurezza della memoria, GC (garbage collection), tipizzazione strutturale e calcolo concorrente in stile CSP.
Hello world
package main
import "fmt"
func main() {
message := greetMe("world")
fmt.Println(message)
}
func greetMe(name string) (string) {
return "Hello, " + name + "!"
}
$ go buildVariabili
Dichiarazione delle variabili
var msg string
msg = "Hello"Abbreviazione
msg := "Hello"Costanti
const Phi = 1.618Le costanti possono essere caratteri, stringhe, valori booleani o numerici.
Tipi di base
Stringhe
str := "Hello"
str := `Multiline
string`Il tipo delle stringhe è string.
Valori numerici
Tipi tipici
num := 3 // int
num := 3. // float64
num := 3 + 4i // complex128
num := byte('a') // byte (alias per uint8)Altri tipi
var u uint = 7 // uint (senza segno)
var p float32 = 22.7 // float a 32 bitPuntatori
func main () {
b := *getPointer()
fmt.Println("Value is", b)
}
func getPointer () (myPointer *int) {
a := 234
return &a
}I puntatori puntano alla posizione di memoria di una variabile. Go è completamente garbage collected.
Array
// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}La dimensione degli array è fissa.
Slice
slice := []int{2, 3, 4}
slice := []byte("Hello")A differenza degli array, le slice hanno una dimensione dinamica.
Controllo del flusso
Condizionale (If)
if day == "sunday" || day == "saturday" {
rest()
} else if day == "monday" && isTired() {
groan()
} else {
work()
}Statements in if
if _, err := getResult(); err != nil {
fmt.Println("Uh oh")
}Le istruzioni if possono eseguire una semplice istruzione prima dell’espressione condizionale.
Switch
switch day {
case "sunday":
// i casi non "cadono" (fall through) per impostazione predefinita!
fallthrough
case "saturday":
rest()
default:
work()
}Funzioni
Lambdas
myfunc := func() bool {
return x > 10000
}Le funzioni sono oggetti di prima classe.
Tipi di ritorno multipli
a, b := getMessage()
func getMessage() (a string, b string) {
return "Hello", "World"
}Specificare i valori di ritorno
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}Dichiarando i nomi dei valori di ritorno, return (senza argomenti) restituirà le variabili con quei nomi.
Pacchetti (Packages)
Caricamento
import "fmt"
import "math/rand"
import (
"fmt" // fornisce fmt.Println
"math/rand" // fornisce rand.Intn
)Entrambi sono uguali.
Alias
import r "math/rand"
r.Intn()Nomi esportati
func Hello () {
···
}I nomi esportati iniziano con una lettera maiuscola.
Pacchetti
package helloOgni file di pacchetto deve iniziare con package.
Concorrenza
Goroutines
func main() {
// Un "channel"
ch := make(chan string)
// Avvia routine concorrenti
go push("Moe", ch)
go push("Larry", ch)
go push("Curly", ch)
// Leggi 3 risultati
// (Poiché le nostre goroutine sono concorrenti,
// l'ordine non è garantito!)
fmt.Println(<-ch, <-ch, <-ch)
}
func push(name string, ch chan string) {
msg := "Hey, " + name
ch <- msg
}I canali sono oggetti di comunicazione sicuri per la concorrenza, usati nelle goroutine.
Canali bufferizzati
ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- 3
// errore fatale:
// tutte le goroutine sono addormentate - deadlock!I canali bufferizzati limitano il numero di messaggi che possono contenere.
Chiusura del canale
Chiude un canale
ch <- 1
ch <- 2
ch <- 3
close(ch)Itera su un canale finché non viene chiuso
for i := range ch {
···
}Chiuso se ok == false
v, ok := <- chControllo degli errori
Defer
func main() {
defer fmt.Println("Done")
fmt.Println("Working...")
}Posticipa l’esecuzione di una funzione fino al ritorno della funzione circostante. I parametri vengono valutati immediatamente, ma la chiamata alla funzione non viene eseguita fino alla fine.
Funzioni differite
func main() {
defer func() {
fmt.Println("Done")
}()
fmt.Println("Working...")
}Le lambda sono più indicate per i blocchi defer.
Strutture (Structs)
Definizione
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
v.X = 4
fmt.Println(v.X, v.Y)
}Letterali
v := Vertex{X: 1, Y: 2}
// I nomi dei campi possono essere omessi
v := Vertex{1, 2}
// Y è implicita
v := Vertex{X: 1}È anche possibile inserire i nomi dei campi.
Puntatori a strutture
v := &Vertex{1, 2}
v.X = 2Quando v è un puntatore, eseguire v.X è lo stesso che fare (*v).X.
Metodi
Ricevitore (Receiver)
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
v := Vertex{1, 2}
v.Abs()Non ci sono classi, ma puoi usare un ricevitore per definire funzioni.
Modifiche
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
v := Vertex{6, 12}
v.Scale(0.5)
// `v` viene aggiornato