Γρήγορη αναφορά

Go Γλώσσα Προγραμματισμού - Φύλλο Οδηγιών

Ένας πρακτικός οδηγός αναφοράς για τη γλώσσα Go, που περιλαμβάνει βασική σύνταξη, ταυτόχρονο προγραμματισμό, χρήση της πρότυπης βιβλιοθήκης και άλλα βασικά σημεία γνώσης, βοηθώντας τους προγραμματιστές να κατακτήσουν γρήγορα τις δεξιότητες ανάπτυξης στη γλώσσα Go.

Δημοσιεύτηκε

Η Go (γνωστή και ως Golang) είναι μια στατικά τυποποιημένη, μεταγλωττισμένη γλώσσα που αναπτύχθηκε από τους Robert Griesemer, Rob Pike και Ken Thompson της Google. Η σύνταξη της Go είναι παρόμοια με τη C, αλλά διαθέτει χαρακτηριστικά όπως: ασφάλεια μνήμης, GC (garbage collection), δομική τυποποίηση και ταυτόχρονο προγραμματισμό τύπου CSP.

Hello world

package main

import "fmt"

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

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

Μεταβλητές (Variables)

Δήλωση μεταβλητής

var msg string
msg = "Hello"

Σύντομη δήλωση

msg := "Hello"

Σταθερές (Constants)

const Phi = 1.618

Οι σταθερές μπορούν να είναι χαρακτήρες (characters), συμβολοσειρές (strings), λογικές τιμές (booleans) ή αριθμητικές τιμές.

Βασικοί Τύποι

Συμβολοσειρές (Strings)

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

Ο τύπος των συμβολοσειρών είναι string.

Αριθμητικοί Τύποι

Τυπικοί τύποι

num := 3          // int
num := 3.         // float64
num := 3 + 4i     // complex128
num := byte('a')  // byte (alias για uint8)

Άλλοι τύποι

var u uint = 7        // uint (unsigned)
var p float32 = 22.7  // 32-bit float

Δείκτες (Pointers)

func main () {
  b := *getPointer()
  fmt.Println("Value is", b)
}
 
func getPointer () (myPointer *int) {
  a := 234
  return &a
}

Ένας δείκτης δείχνει στη θέση μνήμης μιας μεταβλητής. Η Go διαθέτει πλήρη διαχείριση απορριμμάτων (garbage collection).

Πίνακες (Arrays)

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

Το μέγεθος των πινάκων είναι σταθερό.

Slices (Τμήματα)

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

Σε αντίθεση με τους πίνακες, τα slices έχουν δυναμικό μέγεθος.

Έλεγχος Ροής

Συνθήκες (Conditional logic)

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

Δηλώσεις μέσα στην if

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

Η δήλωση if μπορεί να εκτελέσει μια απλή δήλωση πριν από την έκφραση της συνθήκης.

Switch

switch day {
  case "sunday":
    // οι περιπτώσεις δεν "συνεχίζουν" (fall through) από προεπιλογή!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

Συναρτήσεις

Lambdas

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

Οι συναρτήσεις είναι αντικείμενα πρώτης τάξης (first-class objects).

Πολλαπλοί τύποι επιστροφής

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

Καθορισμένες τιμές επιστροφής

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

Δηλώνοντας ονόματα για τις τιμές επιστροφής, η εντολή return (χωρίς ορίσματα) θα επιστρέψει τις μεταβλητές με αυτά τα ονόματα.

Πακέτα (Packages)

Φόρτωση (Loading)

import "fmt"
import "math/rand"
import (
  "fmt"        // παρέχει fmt.Println
  "math/rand"  // παρέχει rand.Intn
)

Και οι δύο τρόποι είναι ίδιοι.

Ψευδώνυμα (Aliases)

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

Ονόματα κλήσης

func Hello () {
  ···
}

Τα ονόματα κλήσης που εξάγονται ξεκινούν με κεφαλαίο γράμμα.

Packages

package hello

Κάθε αρχείο πακέτου πρέπει να ξεκινά με τη δήλωση package.

Ταυτόχρονη Εκτέλεση (Concurrency)

Goroutines

func main() {
  // Ένα "κανάλι" (channel)
  ch := make(chan string)

  // Έναρξη ταυτόχρονων ρουτινών
  go push("Moe", ch)
  go push("Larry", ch)
  go push("Curly", ch)

  // Ανάγνωση 3 αποτελεσμάτων
  // (Εφόσον οι goroutines είναι ταυτόχρονες,
  // η σειρά δεν είναι εγγυημένη!)
  fmt.Println(<-ch, <-ch, <-ch)
}
 
func push(name string, ch chan string) {
  msg := "Hey, " + name
  ch <- msg
}

Τα κανάλια είναι αντικείμενα επικοινωνίας ασφαλή για ταυτόχρονη χρήση, που χρησιμοποιούνται μεταξύ των goroutines.

Κανάλια με Buffering

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

Τα κανάλια με buffer περιορίζουν τον αριθμό των μηνυμάτων που μπορούν να κρατήσουν.

Κλείσιμο καναλιού

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

Περίληψη καναλιού μέχρι να κλείσει:

for i := range ch {
  ···
}

Κλείσιμο αν ok == false:

v, ok := <- ch

Έλεγχος Σφαλμάτων

Defer

func main() {
  defer fmt.Println("Done")
  fmt.Println("Working...")
}

Καθυστερεί την εκτέλεση μιας συνάρτησης μέχρι να επιστρέψει η συνάρτηση που την περιβάλλει. Τα ορίσματα αξιολογούνται αμέσως, αλλά η κλήση της συνάρτησης εκτελείται στο τέλος.

Συναρτήσεις Defer

func main() {
  defer func() {
    fmt.Println("Done")
  }()
  fmt.Println("Working...")
}

Οι Lambdas είναι πιο κατάλληλες για μπλοκ καθυστέρησης (defer blocks).

Structure (Δομές)

Ορισμός

type Vertex struct {
  X int
  Y int
}

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

Literals (Κυριολεκτικά)

v := Vertex{X: 1, Y: 2}
// Τα ονόματα των πεδίων μπορούν να παραλειφθούν
v := Vertex{1, 2}
// Το Y είναι έμμεσο
v := Vertex{X: 1}

Μπορείτε επίσης να καθορίσετε τα ονόματα των πεδίων.

Δείκτες σε δομές

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

Όταν το v είναι δείκτης, το v.X και το (*v).X είναι το ίδιο.

Μέθοδοι (Methods)

Δέκτες (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()

Δεν υπάρχουν κλάσεις, αλλά μπορείτε να χρησιμοποιήσετε δέκτες για να ορίσετε συναρτήσεις σε τύπους.

Τροποποίηση

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` ενημερώνεται

Σχετικά θέματα