40
Introduction à Go Novembre 2016 Sylvain Wallez Software Engineer, Elastic Cloud Elastic.co

Introduction au langage Go

Embed Size (px)

Citation preview

Page 1: Introduction au langage Go

Introduction à GoNovembre 2016

Sylvain WallezSoftware Engineer, Elastic CloudElastic.co

Page 2: Introduction au langage Go

Au menu

A propos...

Origines de Go, qui l'utilise ?

Comparaison de Go et Java

Exemples

Programmation concurrente

La boîte à outils de Go

Adapté de "Go for Java Programmers (http://talks.golang.org/2015/go-for-java-programmers.slide) " de Sameer Ajmani

Page 3: Introduction au langage Go

About me...

Page 4: Introduction au langage Go

Origines de Go

"Go is an open source programming language that makes it easy to build simple, reliable,and efficient software." -- golang.org (http://golang.org)

Créé par Google à partir de 2007 pour des besoins internes :

logiciels serveurs, architectures massivement distribuées (10⁶⁺ machines)

adapté à des grands projets (5000+ développeurs)

Open source depuis 2009 avec une communauté très active

Langage stable depuis la version 1 début 2012

Actuellement : Go 1.7.3

Page 5: Introduction au langage Go

Les créateurs

Robert Griesemer : V8, Java HotSpot

Rob Pike : Unix team, créateur de UTF-8

Ken Thompson : inventeur du langage B, ancètre du C

Page 6: Introduction au langage Go

Utilisations de Go chez Google

Des milliers de développeurs, des millions de lignes de code.

Exemples publics :

Proxy SPDY pour Chrome sur les mobiles

Serveur de téléchargement pour Chrome, ChromeOS, Android SDK, Earth, etc.

Load balancer Vitess pour MySQL (YouTube)

Kubernetes, orchestrateur de cluster Docker

La cible initiale est les services réseaux, mais c'est un langage généraliste.

Page 7: Introduction au langage Go

Qui utilise Go ?

golang.org/wiki/GoUsers (http://golang.org/wiki/GoUsers)

Apcera, Bitbucket, bitly, Canonical, CloudFlare, Core OS, Digital Ocean, Docker, Dropbox,Facebook, Getty Images, GitHub, Hashicorp, Heroku, InfluxDB, Iron.io, Kubernetes, Medium,MongoDB services, Mozilla services, New York Times, pool.ntp.org, SmugMug, SoundCloud,Stripe, Square, Thomson Reuters, Tumblr...

Page 8: Introduction au langage Go

Qui utilise Go ?

OVH (job précédent): - nouvelle génération de services internes - outils de déploiement (Docker & co) - Kafka as a Service, Time Series as a Service

Elastic (job actuel): - les Beats, agents de collectes de métrique

Page 9: Introduction au langage Go

Comparaison de Go et Java

Page 10: Introduction au langage Go

Beaucoup de points communs

Descendance de C (langage impératif, accolades)

Typage statique

Garbage collected

Memory safe (références nulles, contrôle des bornes à l'exécution)

Les variables sont toujours initialisées (zero/nil/false)

Méthodes

Interfaces

Assertions sur les types (instanceof)

Reflection et introspection

Page 11: Introduction au langage Go

Go est (évidemment) différent

Compilation en exécutable natif. Pas de VM

Link statique, exécutable autosuffisant

Contrôle sur l'organisation mémoire

Les fonctions sont des valeurs

String est un type primitif, représenté en UTF-8

Maps et array/slices : types primitifs

Goroutines et channels : concurrence définie dans le langage

Page 12: Introduction au langage Go

Beaucoup d'omissions volontaires

Pas de classes (mais des interfaces)

Pas de constructeurs

Pas d'héritage (mais composition)

Pas de final

Pas d'exceptions

Pas de types génériques

Page 13: Introduction au langage Go

Pourquoi Go fait ces omissions ?

Volonté des créateurs du langage :

La clarté du code est primordiale.

En lisant du code, comprendre ce qu'il fait doit être clair immédiatement.

En écrivant du code, savoir comment l'écrire doit être clair immédiatement.

Un peu de redondance vaut parfois mieux qu'une factorisation obscure.

Pour plus d'infos :

Less is exponentially more (Pike, 2012) (http://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html)

Go at Google: Language Design in the Service of Software Engineering (Pike, 2012)(http://talks.golang.org/2012/splash.article)

Page 14: Introduction au langage Go

Exemples

Page 15: Introduction au langage Go

Go, une syntaxe familière quand on vient de C ou Java

Main.java

public class Main { public static void main(String[] args) { System.out.println("Hello, world!"); } }

hello.go

package main import "fmt" func main() { fmt.Println("Hello, world!") } Run

Page 16: Introduction au langage Go

Hello, web server

Les types viennent après les noms. Les noms Capitalisés sont publics. Les autres noms sont privés (package). Il y a des types pointeurs.

package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/hello", handleHello) fmt.Println("serving on http://localhost:7777/hello") log.Fatal(http.ListenAndServe("localhost:7777", nil)) } func handleHello(w http.ResponseWriter, req *http.Request) { log.Println("serving", req.URL) fmt.Fprintln(w, "Hello, world!") } Run

Page 17: Introduction au langage Go

Exemple : recherche sur Google

func main() { http.HandleFunc("/search", handleSearch) fmt.Println("serving on http://localhost:8080/search") log.Fatal(http.ListenAndServe("localhost:8080", nil)) } // handleSearch handles URLs like "/search?q=golang" by running a // Google search for "golang" and writing the results as HTML to w. func handleSearch(w http.ResponseWriter, req *http.Request) { Run

Page 18: Introduction au langage Go

Valider la requête

func handleSearch(w http.ResponseWriter, req *http.Request) { log.Println("serving", req.URL) // Check the search query. query := req.FormValue("q") if query == "" { http.Error(w, `missing "q" URL parameter`, http.StatusBadRequest) return }

query := req.FormValue("q") initialise une nouvelle variable query du type de l'expression (string).

FormValue est une méthode sur le type *http.Request :

package http type Request struct {...} func (r *Request) FormValue(key string) string {...}

Page 19: Introduction au langage Go

Collecter les résultats

// Run the Google search. start := time.Now() results, err := Search(query) elapsed := time.Since(start) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return }

Search renvoie 2 valeurs : une "slice" de résultats, et une erreur.

func Search(query string) ([]Result, error) {...}

Les résultats sont valides uniquement si l'erreur est nil

type error interface { Error() string // a useful human-readable error message }

Les erreurs peuvent contenir des infos complémentaires, accessibles via des cast ("typeassertion").

Page 20: Introduction au langage Go

Afficher les résultats

// Render the results. type templateData struct { Results []Result Elapsed time.Duration } err = resultsTemplate.Execute(w, templateData{ Results: results, Elapsed: elapsed, }); if err != nil { log.Print(err) return }

resultsTemplate.Execute produit du HTML et l'écrit dans un io.Writer :

type Writer interface { Write(p []byte) (n int, err error) }

http.ResponseWriter implémente l'interface io.Writer.

Page 21: Introduction au langage Go

Les templates HTML

Dans librairie standard, similaire à Mustache

Paramètres : maps et objets Go

// A Result contains the title and URL of a search result. type Result struct { Title, URL string } var resultsTemplate = template.Must(template.New("results").Parse(` <html> <head/> <body> <ol> {{range .Results}} <li>{{.Title}} - <a href="{{.URL}}">{{.URL}}</a></li> {{end}} </ol> <p>{{len .Results}} results in {{.Elapsed}}</p> </body> </html> `)) Run

Page 22: Introduction au langage Go

Envoyer une requête à l'API Google Search

func Search(query string) ([]Result, error) { // Prepare the Google Search API request. u, err := url.Parse("https://ajax.googleapis.com/ajax/services/search/web?v=1.0") if err != nil { return nil, err } q := u.Query() q.Set("q", query) u.RawQuery = q.Encode() // Issue the HTTP request and handle the response. resp, err := http.Get(u.String()) if err != nil { return nil, err } defer resp.Body.Close()

L'instruction defer resp.Body.Close est équivalente au finally Java

Page 23: Introduction au langage Go

Parser la réponse JSON dans une structure Go

// https://developers.google.com/web-search/docs/#fonje var jsonResponse struct { // anonymous structure ResponseData struct { Results []struct { TitleNoFormatting, URL string } } } if err := json.NewDecoder(resp.Body).Decode(&jsonResponse); err != nil { return nil, err } // Extract the Results from jsonResponse and return them. var results []Result for _, r := range jsonResponse.ResponseData.Results { results = append(results, Result{Title: r.TitleNoFormatting, URL: r.URL}) } return results, nil }

Page 24: Introduction au langage Go

Terminé pour le front-end !

Nous n'avons utilisé que la librairie standard :

import ( "encoding/json" "fmt" "html/template" "log" "net/http" "net/url" "time" )

Les serveurs Go tiennent la charge : chaque requête tourne dans une goroutine séparée.

Goroutine ?

Page 25: Introduction au langage Go

L'exécution concurrente en Go

Page 26: Introduction au langage Go

Communicating Sequential Processes (Tony Hoare, 1978)

Les programmes concurrents sont structurés en :

processus indépendants

qui s'exécutent séquentiellement

et communiquent en échangeant des messages.

L'exécution séquentielle est facile à comprendre. Pas les callbacks !

Les primitives Go : goroutines, channels, et l'instruction select.

Page 27: Introduction au langage Go

Goroutines

Les goroutines sont comme des threads légers.

Elles démarrent avec des petites piles (stack) qui sont retaillées selon les besoins.

Un programme Go peut avoir des milliers de goroutines actives.

On démarre une goroutine avec l'instruction go :

doSomething() go doSomethingElse(arg1, arg2) // Forked in a separate goroutine doAnotherThing()

Le runtime Go ordonnance les goroutines sur des threads de l'OS

Une goroutine bloquée ne bloque pas un thread !

Page 28: Introduction au langage Go

Channels

Le canal de communication entre les goroutines.

c := make(chan string) // goroutine 1 go func() { c <- "hello!" }() // goroutine 2 go func() { s := <-c fmt.Println(s) // "hello!" }()

Page 29: Introduction au langage Go

Select

Un select bloque jusqu'à ce que envoi ou réception soient possibles.

select { case n := <-in: fmt.Println("received", n) case out <- v: fmt.Println("sent", v) }

Le default permet de ne pas bloquer.

select { case out <- v: fmt.Println("sent", v) default: fmt.Println("No message, moving on") }

Page 30: Introduction au langage Go

Exemple : Recherche Google (côté serveur)

A partir de mots-clés, renvoyer une page de résultats :

faire une recherche sur le Web

faire une recherche sur Youtube

faire une recherche sur Google Maps

faire une recherche dans les News, etc

sélectionner des pubs (faut bien vivre !)

assembler les résultats (et les pubs)

Page 31: Introduction au langage Go

Un Google fake en 6 lignes

On simule une recherche par un délai aléatoire de 100 ms maximum.

var ( Web = fakeSearch("web") Image = fakeSearch("image") Video = fakeSearch("video") // ... other sources ) type Result string type Search func(query string) Result func fakeSearch(kind string) Search { return func(query string) Result { time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) return Result(fmt.Sprintf("%s result for %q\n", kind, query)) } }

fakeSearch est une fonction qui retourne une fonction

Page 32: Introduction au langage Go

Google Search : le main()

func main() { start := time.Now() results := GoogleSearch("golang") elapsed := time.Since(start) fmt.Println(results) fmt.Println(elapsed) } Run

Page 33: Introduction au langage Go

Google Search (séquentiel)

La fonction GoogleSearch prend une chaîne de recherche, et renvoie une slice de Results(des string).

Lance sequentiellement les recherches Web, Image, et Video, et ajoute leurs résultats à laslice de résultats.

Temps total = somme des temps individuels

func GoogleSearch(query string) (results []Result) { results = append(results, Web(query)) results = append(results, Image(query)) results = append(results, Video(query)) return } Run

Page 34: Introduction au langage Go

Google Search (parallèle)

On lance les recherches en parallèle, et on attend tous les résultats.

Les func anonymes sont des closures sur query and c.

Temps total = temps de la requête la plus longue

func Google(query string) (results []Result) { c := make(chan Result) go func() { c <- Web(query) }() go func() { c <- Image(query) }() go func() { c <- Video(query) }() for i := 0; i < 3; i++ { result := <-c results = append(results, result) } return } Run

Page 35: Introduction au langage Go

Google Search (parallèle + timeout)

On n'attend pas les serveurs qui traînent.

Pas de lock, pas de synchronized, pas de callbacks !

c := make(chan Result, 3) go func() { c <- Web(query) }() go func() { c <- Image(query) }() go func() { c <- Video(query) }() timeout := time.After(80 * time.Millisecond) for i := 0; i < 3; i++ { select { case result := <-c: results = append(results, result) case <-timeout: fmt.Println("timed out") return } } return Run

Page 36: Introduction au langage Go

Les outils

Page 37: Introduction au langage Go

Go : l'outillage

La commande 'go' :

go fmt (http://play.golang.org/p/GPqra77cBK) : formatage selon les règles canoniques

go vet : "checkstyle" par les devs de Go

go doc : javadoc-like. Tout le Go open source sur godoc.org (http://godoc.org)

go get : téléchargement/installation de packages

IDE : plugins IntelliJ, Eclipse, Sublime, Vim...

Compilation cross-platform (Yay Raspberry Pi !)

Compilation pour mobiles (applis ou librairies Android et iOS)

Page 38: Introduction au langage Go

Quelques liens

Tutoriel interactif

tour.golang.org (http://tour.golang.org)

Effective Go : un must read pour aller plus loin

golang.org/doc/effective_go.html (https://golang.org/doc/effective_go.html)

Collection de liens, de trucs et astuces, etc.

golang.org/wiki/Learn (http://golang.org/wiki/Learn)

Cette présentation

github.com/swallez/golang-talks/ (https://github.com/swallez/golang-talks/)

Page 39: Introduction au langage Go

Thank you

Sylvain WallezSoftware Engineer, Elastic CloudElastic.co@bluxte (http://twitter.com/bluxte)

[email protected] (mailto:[email protected])

Page 40: Introduction au langage Go