Go – Un langage moderne – Généralités



Go – Un langage moderne – Généralités

0 1


introducing_go


On Github Soulou / introducing_go

Go

Un langage moderne

par Léo 'Soulou' Unbekandt

LOGo

Historique

Principal développeur : Rob Pike

  • 2007 — Google 80/20
  • 2009 — Licence BSD
  • Maintenant (hier) — Go 1.1
Travaille avec Kernighan sur UNIX Développé par la communauté

Go en production

Généralités

  • Langage compilé statiquement
  • Multiplateforme (GNU/Linux, BSD, OS X, Windows)
  • Multiarchitecture (x86, amd64, ARM)
  • Garbage Collector

Langage compilé statiquement

  • Pas de bibliothèque partagée
  • Binaire légèrement lourd
  • Exécutable portable

Multiplateforme

Multiarchitecture

  $ GOOS=windows GOARCH=386 go build main.go
  $ GOOS=darwin GOARCH=amd64 go build main.go
  $ GOOS=freebds GOARCH=arm GOARM=5 go build main.go
            

Garbage Collector

  • Pas de malloc ni de free
  • Mark & Sweep GC

La syntaxe

« Syntax is not important... - unless you are a programmer.»Rob Pike

La syntaxe...

est unique

  package main ; import "fmt" ; func main() { 
  fmt.Println("← Hello World ☺ →"); }
            
$ go fmt main.go
  package main

  import "fmt"

  func main() { 
    fmt.Println("← Hello World ☺ →")
  }
            
UTF-8 !

La syntaxe unique

  • Contraignant au début
  • Agréable par la suite
    • Lisibilité hautement accrue
    • Plus aisé à écrire
Car il n'y a pas N manière de faire, juste une

Le Langage

Variables

  i := 0
  b := true
            
==
  var i int = 0
  var b bool = true
            

Fonctions

  func hello(name string) string {
    return fmt.Sprintf("Hello %s !\n", name)
  }

  func split(str string) (string, string) {
    return str[:len(str)/2], str[len(str)/2:]
  }

  incr := func(n int) int {
    return n+1
  }
            
Les string sont IMMUTABLES !

Structures de contrôle

  if i == 0 {
    os.Exit(0)
  } else {
    fmt.Printf("NOT ZERO !\n")
  }
  for i := 0 ; i < N ; i++ { ..
  for i < N { ..
  for { .. 
            

Tableau / Slice

  var array [10]int 
  slice := array[:2]

  emptySlide := make([]int, 10)  

  strArray := []string{"Salut", "les", "Gophers"}
  for k,v := range strArray {
    fmt.Printf("Index : %d, Value : %s\n", k, v)
  }
            

Map

  data := map[string]string {
    "key1" : "value1",
    "key2" : "value2"
  }

  for k,v := range data { // ...
            

La gestion des dépendances

Une structure en packages

  // Fichier base.go
  package base

  func Inc(n int) int {
    return n + 1
  }
  func dec(n int) int {
    return n - 1
  }

            

La gestion des dépendances

Une structure en packages

  // Fichier main.go
  package main
  import (
    "base"
    "fmt"
  )
  func main() {
    fmt.Printf("Inc(1) = %d\n", base.Inc(1))
    // ERREUR
    fmt.Printf("dec(1) = %d\n", base.dec(1))
  }
            

Les dépendances externes

  import (
    "github.com/pmylund/go-cache"
    "launchpad.net/gnuflag"
    "bitbucket.org/taruti/ssh.go"
    "code.google.com/p/go-avltree"
  )
            
  $ go get [import]
            

Gestion des erreurs

  f, err := os.Open(name)
  if err != nil {
    // Traitement err
  }
            

Report d'instructions

  f, err := os.Open(name)
  if err != nil {
    // Traitement err
  }
  defer f.Close()
  // Utilisation du file handle
            

Fermetures (closures) !

  func AddN(n int) func(int) int {
    return func(m int) {
      return m + n
    }
  }

  add10 := AddN(10)
  fmt.Print(add10(1))
            

Type, Structure et Méthode

  type Point struct {
    x, y float64
  }
  func (this *Point) dist(that *Point) float64 {
    math.Sqrt(
      math.Pow(that.x - this.x, 2) + 
      math.Pow(that.y - this.y, 2))
  }
  p1 := &Point{1.0,2.0}
  p2 := &Point{2.0,3.0}
  fmt.Println("%f\n", p1.dist(p2))
            

Les interfaces

  type Animal interface {
    Bruit(uint16) error
  } 

  type Chien struct {
    Animal
  }

  type Poisson struct {
    Animal
  }
          

Les interfaces

  func (c Chien) Bruit(n uint16) error {
    for i := 0 ; uint16(i) < n ; i++ {
      fmt.Println("Waf")
    }
    return nil
  } 
  func (p Poisson) Bruit(n uint16) error {
    return fmt.Errorf("Je ne fais pas de bruit je suis un poisson\n")
  }
            

Concurrence

avec GO

Les goroutines

  func doSomething(n int) {
    time.Sleep(n * time.Millisecond)
    fmt.Printf("%d ms\n", n)
  }

  func main() {
    go doSomething(200)
    go doSomething(400)
    doSomething(600)
  }
            

Les Channels

  func waitRead(ch chan bool) {
    time.Sleep(2 * time.Second)
    ch <- true
  }
  func main() {
    ch := make(chan bool, 1)
    go waitReady(ch)
    <- ch
    fmt.Printf("We are ready\n")
  }
            
  func idGenerator() chan int {
    ids := make(chan int)
    go func() {
      id := 0
      for {
        ch <- id
        id++
      }
    }()
    return ids
  }
          
  func main() {
    ids := idGenerator()
    id1 := <-ids
    id2 := <-ids
  }
          

Select

  timeout := time.After(2 * time.Seconds)
  ch := make(chan Result)
  go func() {
    ch <- doSomething() 
  }()
  select {
    case r := <-ch:
      // On a un résultat en moins d'1 sec
    case <-timeout:
      // Timeout, on traite le cas
  }
            

Goroutines + Channels♥

  • Pas de mutex
  • Pas de semaphore
  • Très puissant

stdlibriche et moderne

  • CSV, JSON, XML
  • Mail, SMTP, HTTP, HTML (template)
  • Crypto : RSA, AES, DES, SHA, TLS, x509
  • Compression : bz2, gz, lzw, zip

Oubliez la libcurl

  resp, err := http.Get("http://example.com/")
  resp, err := http.Post("http://example.com/upload", 
    "image/jpeg", &buf)
  resp, err := http.PostForm("http://example.com/form",
    url.Values{"key": {"Value"}, "id": {"123"}})
            
  s := &http.Server{
    Addr:           ":8080",
    Handler:        myHandler,
    ReadTimeout:    10 * time.Second,
    WriteTimeout:   10 * time.Second,
    MaxHeaderBytes: 1 << 20,
  }
            
  func myHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %q", 
      html.EscapeString(r.URL.Path))
  }
            

Des frameworks

CGO

  package main

  import "fmt"

  // #include <stdio.h>
  import "C"

  func main() {
    n, err := C.getchar()
    fmt.Print(n, err)
  }
            

Des bindings C

  • GoSqlite3
  • GoMysql
  • GoCurses
  • GoGL
  • ...

L'outil CLI : GO

  • get
  • build
  • run
  • fmt
  • doc
  • test
  • fix

Setup ton PC

  $ wget 'http://goo.gl/qa4FT'
  $ tar xvf go1.1.linux-amd64.tar.gz
  $ echo "export GOOS=linux" > > ~/.zshrc
  $ echo "export GOARCH=amd64" > > ~/.zshrc
  $ echo "export GOROOT=`pwd`/go" > > ~/.zshrc
  $ echo "export GOPATH=~/Workspace/go" > > ~/.zshrc
  $ echo "export PATH=$PATH:$GOROOT/bin:$GOPATH/bin" > > ~/.zshrc
            
  $GOPATH/
    bin/
    pkg/
      linux_amd64/
        projet/
          package/
            *.a
    src/
      project/
        package/
          *.go
          

Setup Vim

  $ go get -u github.com/nsf/gocode
  $ $GOPATH/src/github.com/nsf/gocode/vim/update_pathogen.sh
            

Setup ZSH

http://tip.golang.org/misc/zsh/go

Références

Questions-Remarques ?

Merci

Léo UnbekandtÉtudiant à l'ENSIIE Strasbourg

http://go.l3o.eu