Google Go ou golang

Pourquoi et comment?



Jean-François Nadeau
20 mars, WAQ 2015

Qui suis-je?

  • Co-fondateur de MailSquad
  • A fait d'un peu de tout:
    Ruby 2003 - Lektora
    C++ 2005 - Microsoft / IE7
    Java 2007 - SSQ
    C# 2009 - SQI
    Golang / TypeScript 2014

Historique de Golang

  • Déjà plus de 5 ans (2009)
    • Ken Thompson (Unix)
    • Rob Pike (Plan 9)
    • Robert Griesemer
  • Problème: quantité de code C++ chez Google
  • Solution: inventer un langage à la "Google scale"

Cas d'utilisations typiques

  • "Daemon" réseau (ex: API REST HTTP)
  • Langage système (ex: docker)
  • Outil ligne de commande (ex: mongodb-tools)

Qui utilise?

Hello world!


package main

import "fmt"

func main() {
  msg := "Allo monde!"
  fmt.Println(msg)
}
					
  • package - similaire Java / namespace C++ / C#
  • import - déclaration d'utilisation d'un package externe
  • func - déclaration d'une fonction
  • opérateur := - déclaration et assignement
  • fmt.Println - utilisation librairie standard

Les particularités

Des pointeurs comme en C


type Structure struct {
  nombre int
}

func utilisation(s *Structure) { 
  copie := *s
}
					
  • Exactement pareil que en C
  • Assignement: copie par valeur
  • Sécuritaire (protection nil)

Interfaces


type Parleur interface {
  Parle() string
}

type Implementation struct {
  msg string
}

func (i *Implementation) Parle() string { 
  return i.msg
}

func FaitParler(p Parleur) {
  fmt.Println(p.Parle())
}
					
  • Déclaration et implémentation dissociée
  • Seule façon de faire du polymorphisme
  • Utile: plusieurs petites interfaces

Composition vs héritage


type Auto struct {
  nbRoues int
}

type Ferrari struct {
  Auto
  moteur *Moteur
}

func (i *Auto) NbRoues() int { 
  return i.nbRoues
}

func (i *Ferrari) Demarrer() { ...}

func exemple(f *Ferrari) {
  fmt.Println(f.NbRoues())
  f.Demarrer()
}
					
  • Pas d'héritage, composition seulement
  • Public / Privée: Lettre majuscule est exportée seulement
  • Pas de surcharge de méthodes / fonctions

Gestion des erreurs


func ManipulerFichier(nom string) (f *File, err error) {
	
 f, err = os.Open(nom)
 if err != nil {
     return
 }

 // Faire quelque chose avec f
}
						
  • Pas d'exception sauf fatale (panic sur pointeur nil)
  • On aime ou pas!
  • Le bon coté: forcer à considérer toutes les erreurs
  • Retour valeurs multiples est très utile

Goroutine et channel


func main() {

    messages := make(chan string)

    go func() { messages <- "allo" }()

    msg := <-messages
    fmt.Println(msg)
}

						
  • Goroutine: thread léger géré par Go (2kb stack!)
  • Pas besoin de async I/O (epoll à l'interne)
  • Principes CSP : éviter la mémoire partagée!
  • Plus d'infos: Concurrency is not parallelism de Rob Pike

Cas pratiques

Outils de développement

  • Meilleur combo: éditeur de texte avec plugin
  • Moi: Sublime + GoSublime
  • Débogage: retour du bon vieux printf
  • Autres: Atom, GoClipse, liteide, IntelliJ

Quelques packages

Go versus X,Y,Z?

Go vs Ruby/Python/Node.js

Plus
  • Typage statique
  • Performance et consommation de mémoire
  • Déploiement au plus simple
  • Vs Node.js: aync io sans callback hell

Go vs Ruby/Python/Node.js

Moins
  • Rien d'équivalent à RubyOnRails

Go vs .NET/Java

Plus
  • Aucune VM à gérer
  • Consommation mémoire: très efficace
  • Vs .NET: Linux, mais quoi réserve .NET Core?

Go vs .NET/Java

Moins
  • Vs C#: pas la même optique du tout (LINQ, génériques, etc.)
  • Vs JVM: vaste choix de langages pour une même VM

Go vs C/C++

Plus
  • Enfin une alternative viable
  • Support Android natif s'en vient
  • Chez Google: dl.google.com, C++ à Go

Go vs C/C++

Moins
  • GC obligatoire, mais 1.5, real time GC
  • Sera jamais aussi complet que C++
  • Mozilla Rust vs Golang: à voir

Retour d'expérience chez MailSquad

Critères de sélection

  • Backend: API REST seulement (frontend: AngularJS)
  • Rapport productivité/performance: $$$ infrastructure
  • Support Linux et MacOS X
  • Esprit TDD et outils environnant

Les choix

C#/.NET excellent langage, mais manque de confiance par rapport à Linux
Java/JVM très robuste mais JVM beaucoup trop gourmante en mémoire
Ruby/Python langage agréable mais VM déficiente
Node.js désolé, callbacks et promises n'est pas un cadeau
C/C++ gestion de mémoire et sécurité des pointeurs, jamais!
Rust < 1.0

Résultats

  • Encore très satisfait après 1 an, même devenu évangéliste!
  • Ce que j'aime:
    • Compilation instantanée pour 28k lignes de code
    • Coût d'exploitation ridicule
    • Librairie standard surprenamment complète
    • go fmt: génial!
    • Jamais de surprise
  • Ce que j'aime moins:
    • Les génériques seraient utiles, mais on s'y fait
    • Gestion des erreurs: neutre
    • Défis de recrutement: à voir?

Osez Golang!


Shameless plug!

Vous utilisez MailChimp ou CampaignMonitor?
Allez voir MailSquad!