Skip to content

Go Programmeringsspråk - Snabbreferens

Go (även känt som Golang) är ett statiskt typsäkert, kompilerat språk utvecklat av Google av Robert Griesemer, Rob Pike και Ken Thompson. Go:s syntax liknar C, men har funktioner som: minnessäkerhet, GC (garbage collection), strukturell typsättning och CSP-stilad konkurrent beräkning.

Hello world

package main

import "fmt"

func main() {
  message := greetMe("world")
  fmt.Println(message)
}

func greetMe(name string) (string) {
  return "Hello, " + name + "!"
}
$ go build

Variabler (Variables)

Variabeldeklaration

var msg string
msg = "Hello"

Förkortning (Short declaration)

msg := "Hello"

Konstanter (Constants)

const Phi = 1.618

Konstanter kan vara tecken, strängar, booleska värden eller numeriska värden.

Grundläggande Typer

Strängar (Strings)

str := "Hello"
str := `Multiline
string`

Typen för strängar är string.

Numeriska Typer

Typiska typer

num := 3          // int
num := 3.         // float64
num := 3 + 4i     // complex128
num := byte('a')  // byte (alias för uint8)

Andra typer

var u uint = 7        // uint (teckenlös)
var p float32 = 22.7  // 32-bitars float

Pekare (Pointers)

func main () {
  b := *getPointer()
  fmt.Println("Värdet är", b)
}
 
func getPointer () (myPointer *int) {
  a := 234
  return &a
}

En pekare pekar på variabelns minnesplats. Go har fullständig skräpsamling (garbage collection).

Arrayer (Arrays)

// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}

Storleken på arrayer är fast.

Slices

slice := []int{2, 3, 4}
slice := []byte("Hello")

Till skillnad från arrayer har slices dynamisk storlek.

Flödeskontroll

Villkor (if/else)

if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}

Satser i if

if _, err := getResult(); err != nil {
  fmt.Println("Hoppsan")
}

En if-sats kan köra en enkel sats före villkorsuttrycket.

Switch

switch day {
  case "sunday":
    // cases faller inte igenom (fallthrough) som standard!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

Funktioner

Lambdas

myfunc := func() bool {
  return x > 10000
}

Funktioner är förstclass-objekt.

Flera returtyper

a, b := getMessage()
func getMessage() (a string, b string) {
  return "Hello", "World"
}

Namngivna returvärden

func split(sum int) (x, y int) {
  x := sum * 4 / 9
  y := sum - x
  return
}

Genom να deklarera namn för returvärden kommer return-satsen (utan parametrar) returnera variablerna med dessa namn.

Paket (Packages)

Laddning (Loading)

import "fmt"
import "math/rand"
import (
  "fmt"        // ger fmt.Println
  "math/rand"  // ger rand.Intn
)

Båda är likvärdiga.

Alias

import r "math/rand"
 
r.Intn()

Exporterade namn

func Hello () {
  ···
}

Anropade namn som exporteras börjar med stor bokstav.

Packages

package hello

Varje paketfil måste börja med package-deklarationen.

Konkurrens

Goroutines

func main() {
  // En "kanal" (channel)
  ch := make(chan string)

  // Starta konkurrerande rutiner
  go push("Moe", ch)
  go push("Larry", ch)
  go push("Curly", ch)

  // Läs 3 resultat
  // (Eftersom våra goroutines körs samtidigt,
  // är ordningen inte garanterad!)
  fmt.Println(<-ch, <-ch, <-ch)
}
 
func push(name string, ch chan string) {
  msg := "Hej, " + name
  ch <- msg
}

Kanaler är konkurrenssäkra kommunikationsobjekt som används mellan goroutines.

Buffrade kanaler (Buffered channels)

ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- 3
// fatal error:
// alla goroutines sover - deadlock!

Buffrade kanaler begränsar antalet meddelanden som kan sparas.

Stänga kanaler

ch <- 1
ch <- 2
ch <- 3
close(ch)

Iterera över en kanal tills den stängs:

for i := range ch {
  ···
}

Stängd om ok == false:

v, ok := <- ch

Felhantering

Defer

func main() {
  defer fmt.Println("Klar")
  fmt.Println("Jobbar...")
}

Fördröjer körningen av en funktion tills den omgivande funktionen returnerar. Argumenten utvärderas omedelbart, men funktionsanropet körs i slutet.

Fördröjda funktioner (Deferred functions)

func main() {
  defer func() {
    fmt.Println("Klar")
  }()
  fmt.Println("Jobbar...")
}

Lambdas är mer lämpliga för defer-block.

Strukter (Structs)

Definition

type Vertex struct {
  X int
  Y int
}

func main() {
  v := Vertex{1, 2}
  v.X = 4
  fmt.Println(v.X, v.Y)
}

Literaler

v := Vertex{X: 1, Y: 2}
// Fältnamn kan utelämnas
v := Vertex{1, 2}
// Y är implicit
v := Vertex{X: 1}

Du kan också ange fältnamn.

Pekare till strukter

v := &Vertex{1, 2}
v.X = 2

När v är en pekare är v.X och (*v).X samma sak.

Metoder

Mottagare (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()

Det finns inga klasser, men du kan använda mottagare för να definiera funktioner på typer.

Mutation (Ändringar)

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` uppdateras