Go Język Programowania Cheat Sheet
Go (znany również jako Golang) to statycznie typowany, kompilowany język opracowany przez Roberta Griesemera, Roba Pike’a i Kena Thompsona w Google. Składnia Go jest zbliżona do C, ale oferuje bezpieczeństwo pamięci, GC (garbage collection), typowanie strukturalne oraz współbieżność w stylu CSP.
Hello world
package main
import "fmt"
func main() {
message := greetMe("world")
fmt.Println(message)
}
func greetMe(name string) (string) {
return "Hello, " + name + "!"
}
$ go buildZmienne
Deklaracja zmiennej
var msg string
msg = "Hello"Skrócona deklaracja
msg := "Hello"Stałe
const Phi = 1.618Stałe mogą być znakami, ciągami znaków, wartościami logicznymi lub liczbowymi.
Typy podstawowe
Ciągi znaków (Strings)
str := "Hello"
str := `Wieloliniowy
string`Typem dla ciągów znaków jest string.
Liczby
Typowe typy
num := 3 // int
num := 3. // float64
num := 3 + 4i // complex128
num := byte('a') // byte (alias dla uint8)Inne typy
var u uint = 7 // uint (bez znaku)
var p float32 = 22.7 // 32-bitowy floatWskaźniki
func main () {
b := *getPointer()
fmt.Println("Wartość to", b)
}
func getPointer () (myPointer *int) {
a := 234
return &a
}Wskaźniki wskazują na lokalizację w pamięci zmiennej. Go posiada pełne odśmiecanie pamięci (garbage collection).
Tablice (Arrays)
// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}Tablice mają stały rozmiar.
Wycinki (Slices)
slice := []int{2, 3, 4}
slice := []byte("Hello")W przeciwieństwie do tablic, wycinki mają dynamiczny rozmiar.
Sterowanie przepływem
Instrukcje warunkowe
if day == "sunday" || day == "saturday" {
rest()
} else if day == "monday" && isTired() {
groan()
} else {
work()
}Instrukcja wewnątrz if
if _, err := getResult(); err != nil {
fmt.Println("Uh oh")
}Instrukcja if może wykonać prostą instrukcję przed wyrażeniem warunkowym.
Switch
switch day {
case "sunday":
// przypadki domyślnie nie "przechodzą" (no fallthrough)!
fallthrough
case "saturday":
rest()
default:
work()
}Funkcje
Lambdy (funkcje anonimowe)
myfunc := func() bool {
return x > 10000
}Funkcje są obywatelami pierwszej kategorii (first-class objects).
Wiele typów zwracanych
a, b := getMessage()
func getMessage() (a string, b string) {
return "Hello", "World"
}Nazwane wartości zwracane
func split(sum int) (x, y int) {
x := sum * 4 / 9
y := sum - x
return
}Dzięki nazywaniu wartości zwracanych w deklaracji, return (bez argumentów) zwróci zmienne o tych nazwach.
Pakiety
Ładowanie
import "fmt"
import "math/rand"
import (
"fmt" // daje fmt.Println
"math/rand" // daje rand.Intn
)Obie formy są poprawne.
Aliasy
import r "math/rand"
r.Intn()Nazwy eksportowane
func Hello () {
···
}Nazwy eksportowane zaczynają się od wielkiej litery.
Pakiety
package helloKażdy plik pakietu musi zaczynać się od deklaracji package.
Współbieżność
Goroutines
func main() {
// "Kanał" (channel)
ch := make(chan string)
// Uruchomienie współbieżnych procedur
go push("Moe", ch)
go push("Larry", ch)
go push("Curly", ch)
// Odczyt 3 wyników
// (Ponieważ nasze goroutines są współbieżne,
// kolejność nie jest gwarantowana!)
fmt.Println(<-ch, <-ch, <-ch)
}
func push(name string, ch chan string) {
msg := "Hey, " + name
ch <- msg
}Kanały są bezpiecznymi dla współbieżności obiektami komunikacyjnymi używanymi w goroutines.
Kanały buforowane
ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- 3
// błąd krytyczny:
// all goroutines are asleep - deadlock!Kanały buforowane ograniczają liczbę komunikatov, które mogą pomieścić.
Zamykanie kanałów
Zamyka kanał
ch <- 1
ch <- 2
ch <- 3
close(ch)Iteracja po kanale aż do jego zamknięcia
for i := range ch {
···
}Zamknięty, jeśli ok == false
v, ok := <- chDefer & Panic
Defer
func main() {
defer fmt.Println("Gotowe")
fmt.Println("Pracuję...")
}Odracza wykonanie funkcji do momentu, gdy funkcja nadrzędna zakończy działanie. Argumenty są oceniane natychmiast, ale wywołanie funkcji następuje dopiero na końcu.
Defer z lambdami
func main() {
defer func() {
fmt.Println("Gotowe")
}()
fmt.Println("Pracuję...")
}Lambdy lepiej nadają się do bloków odroczonych.
Struktury (Structs)
Definicja
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
v.X = 4
fmt.Println(v.X, v.Y)
}Literały
v := Vertex{X: 1, Y: 2}
// Nazwy pól można pominąć
v := Vertex{1, 2}
// Y jest domniemane
v := Vertex{X: 1}Można również określić nazwy pól.
Wskaźniki do struktur
v := &Vertex{1, 2}
v.X = 2Gdy v jest wskaźnikiem, v.X i (*v).X to to samo.
Metody
Odbiorniki (Receivers)
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()W Go nie ma klas, ale można definiować funkcje dla typów za pomocą odbiorników.
Odbiorniki wskaźnikowe
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` zostaje zaktualizowany