Go (langage)
Go est un langage de programmation compilé et concurrent inspiré de C et Pascal. Ce langage a été développé par Google[7] à partir d’un concept initial de Robert Griesemer (en), Rob Pike et Ken Thompson. Go possède deux implémentations : la première utilise gc, le compilateur Go ; la seconde utilise gccgo, « frontend » GCC écrit en C++. Go est écrit en C en utilisant yacc et GNU Bison pour l’analyse syntaxique[8] jusqu’à la version 1.4, et en Go lui-même pour les versions suivantes (1.5).
Pour les articles homonymes, voir GO.
Cet article concerne le langage de programmation open source créé par Google en 2009. Pour le langage de programmation créé en 2003, voir Go! (langage). Pour go dans d’autres contexte, voir GO.
Go | ||
Date de première version | ||
---|---|---|
Paradigme | Langage compilé, programmation concurrente, impérative et structurée | |
Auteur | Robert Griesemer (en) Rob Pike Ken Thompson |
|
Dernière version | 1.19 ()[1],[2] | |
Version en développement | 1.19rc2 ()[3] | |
Typage | Fort, statique, structurel | |
Influencé par | C Oberon-2 (en) Limbo Active Oberon (en) Communicating sequential processes Pascal Oberon Smalltalk Newsqueak (en) Modula-2 Alef APL BCPL Modula (en) Occam |
|
Système d'exploitation | Windows, GNU/Linux, Mac OS X, FreeBSD, OpenBSD, DragonflyBSD, Solaris, Plan 9[4] | |
Licence | Licence BSD[5], breveté[6] | |
Site web | go.dev | |
Extension de fichier | go | |
Un objectif de Go est donné par Rob Pike, l’un de ses trois créateurs, qui dit à propos des développeurs inexpérimentés[9] :
« Ils ne sont pas capables de comprendre un langage brillant, mais nous voulons les amener à réaliser de bons programmes. Ainsi, le langage que nous leur donnons doit être facile à comprendre et facile à adopter »
Go veut faciliter et accélérer la programmation à grande échelle : en raison de sa simplicité, il est donc concevable de l’utiliser aussi bien pour écrire des applications, des scripts ou de grands systèmes. Cette simplicité est nécessaire aussi pour assurer la maintenance et l’évolution des programmes sur plusieurs générations de développeurs.
S’il vise aussi la rapidité d’exécution, indispensable à la programmation système, il considère le multithreading comme le moyen le plus robuste d’assurer sur les processeurs actuels cette rapidité[10] tout en rendant la maintenance facile par séparation de tâches simples exécutées indépendamment afin d’éviter de créer des « usines à gaz ». Cette conception permet également le fonctionnement sans réécriture sur des architectures multi-cœurs en exploitant immédiatement l’augmentation de puissance correspondante.
« Hello, world »
Voici un exemple d'un programme Hello world typique écrit en Go :
package main
import "fmt"
func main() {
fmt.Printf("Hello, world\n")
}
Caractéristiques
Le langage Go a été créé pour la programmation système et a depuis été étendu aux applications, ce qui constitue la même cible que le C et surtout le C++. Il s'agit d'un langage impératif et concurrent. Sa vitesse de compilation (due à la simplicité de sa syntaxe) le fait parfois utiliser comme langage de script.
Concurrence
Go intègre directement, comme Java, les traitements de code en concurrence. Le mot clé go
permet à un appel de fonction de s'exécuter en concurrence avec la goroutine courante[11]. Une goroutine, ainsi nommée par analogie lointaine avec les coroutines, est un fil d'exécution supervisé par l'ordonnanceur inclus dans le runtime[12]. Le programme prendra alors avantage de la topologie de l'ordinateur pour exécuter au mieux les goroutines, pas forcément dans un nouveau thread, mais il est aussi possible qu'un groupe de goroutines soit multiplexé sur un groupe de threads[13].
Pour appeler une fonction f, on écrit f(). Pour l'appeler en tant que goroutine, on écrit simplement go f(), ce qui est très semblable au call f task; de PL/I, langage gérant également le multitâche depuis 1970.
Les goroutines communiquent entre elles par passage de messages, en envoyant ou en recevant des messages sur des canaux[14].
Ces messages synchronisent les goroutines entre elles conformément au modèle CSP, considéré par les auteurs comme plus intuitif que le modèle multi-threadé (avec synchronisation par sémaphores comportant des verrous, notion introduite elle aussi par Dijkstra).
Faux-amis
Dans l'état actuel du langage (2018)
Le langage contient des aspects de Pascal et de C, mais on s'expose à beaucoup d'erreurs si on oublie momentanément qu'on n'est ni en Pascal ni en C. Ainsi a:=b
alloue une variable a en lui affectant la valeur et le type de b, mais si la variable a déjà été allouée il faudra se contenter d'écrire a=b
. À ne pas confondre avec a==b
(égalité de valeurs). L'expression derrière un if
n'a pas besoin de parenthèses, mais l'expression à exécuter en cas de réussite du test devra être entre accolades. Dans son état actuel, le compilateur ne tolère pas qu'une variable déclarée ne soit pas utilisée, ce qui encourage certes de bonnes pratiques, mais rend fort pénibles les tâtonnements de mise au point des programmes.
Collections d'objets
Go connaît les types scalaires (entiers int
ou int64
, flottants float
, chaînes string
), les tableaux indexés par des entiers à partir de 0, les maps qui sont des collections d'objets indexés par des clés (nommés dictionnaires, hashes ou tableaux associatifs dans d'autres langages) et des slices qui sont une généralisation dynamique des tableaux.
Il accède aisément aux fichiers en lecture comme en écriture, que ce soit en mode ligne, ou caractère, ou bien en absorbant le fichier complet, par les packages os et io.
Système de types
Go a un système de type statique, fortement typé, structurel et sûr, fondé sur l'inférence de types avec la possibilité d'utiliser un typage explicite.
Pour donner un exemple, écrire s := "Camélia"
, qui déclare, alloue et initialise s
, est possible et n'oblige pas à écrire var s string = "Camélia"
, qui reste cependant accepté.
La compatibilité des types composés est fondée sur les propriétés plutôt que sur le nom. C'est-à-dire que deux types composés seront équivalents si leurs propriétés sont équivalentes : même nom pour la propriété et équivalence de type. C'est le typage structurel.
Cela a pour conséquence que le langage n'est pas objet au sens classique (soit avec classes, soit avec prototype), cependant les concepteurs du langage ont fait un choix plus original pour un langage statique. Il est possible de définir des interfaces portant des méthodes décrivant le comportement d'un objet (il est aussi facilement possible de mélanger plusieurs interfaces en une seule)[15]. Les fonctions Go peuvent déclarer accepter un argument de cette interface. Un objet déclarant toutes les méthodes de cette interface, avec la même signature, peut être passé en argument de cette méthode. La vérification du type est effectuée statiquement par le compilateur.
Le fait que Go ne soit pas objet au sens classique fait que Go n'a pas d'héritage de type et pas de sous-classage. Ceci permet de contourner les problèmes posés par ces systèmes tels l'héritage multiple dans les langages qui le permettent (en C++ par exemple), ou l'héritage simple (en Java par exemple). Grâce à l'équivalence de types fondée sur les propriétés, Go n'a pas besoin d'héritage de type. Le sous-classage est émulé par l'« embarquement de type ». Ceci permet de mélanger facilement deux bases de code conçues indépendamment, sans qu'elles aient besoin de partager des types communs.
La visibilité des structures, attributs, variables, constantes, méthodes, types de haut niveau et des fonctions hors de leur paquetage de déclaration est définie par la casse du premier caractère de leurs identificateurs.
Runes
Go travaille en Unicode aussi bien pour son code source que pour son traitement des chaînes. Sa littérature abandonne toutefois l'expression code points pour l'abréviation de runes. Des procédures permettent de transformer des représentations de caractère en runes (toute rune occupant une taille fixe[16]) et transformer par des procédures standards une suite de caractères Unicode en runes d'un tableau (une rune par élément), ainsi que l'inverse, sans avoir à jongler avec les représentations de longueur variables ni s'occuper de savoir si la machine est little-endian ou big-endian. La portabilité est donc assurée.
Parler de runes évite les ambiguités qui seraient présentes avec caractère ou octet[17]. Pour explorer une chaîne, soit on utilise directement des fonctions de chaîne, soit on la parcourt de rune en rune.
Les mises en capitales de caractères nationaux (par exemple "è"⇒ "È") se font simplement par unicode.ToUpper(r rune) rune
.
Les runes permettent de spécifier en tout caractère Unicode, thaï, chinois, grec, y compris du langage APL- et également toute émoticône s'y trouvant.
Divers
Dans Go, la gestion de la mémoire est assurée par un ramasse-miettes[15].
Il n'y a pas encore de programmation générique même si les concepteurs du langage y réfléchissent. Il n'y a pas de surcharge de méthodes ou d'arithmétique des pointeurs. Enfin, il n'y a pas d'assertions ou d'exceptions. Pour remplacer ces deux derniers, Go fournit les mots clés defer
, panic
et recover
[18] qui donnent des mécanismes similaires aux systèmes de gestion des exceptions de langages tels que C++ et Java (mots clés try
, catch
, finally
et throw
).
Go peut s'interfacer avec des bibliothèques en C/C++, des développeurs tiers ayant déjà développé des bindings pour SDL et MySQL.
Go définit un format de code standard (au niveau des indentations, et de la présentation des structures de contrôle) et fournit un outil pour l'appliquer (go fmt).
Go propose également un système de documentation à partir du code et un framework de test.
L'unité de compilation de go est le package qui est représenté dans l'implémentation standard par un répertoire et les fichiers directement contenus dans ce répertoire.
L'import d'un package se fait par son chemin d'importation et peut préciser soit une bibliothèque standard, soit également des packages tiers installés dans des dépôts de sources distants (actuellement supporté : dépôt sous svn, git, mercurial et bazaar).
Bibliothèques
Comme le C, Go exige d'indiquer quelles bibliothèques on utilisera. À la différence du C, il considère la compilation en erreur si cette bibliothèque n'est pas utilisée. Le compilateur Go ne contient en effet pas de messages d'avertissements par choix des concepteurs : « Il n'est pas indispensable de signaler ce qu'il ne serait pas indispensable de corriger ».
Principales bibliothèques :
- fmt fournit 19 fonctions de mise en forme des entrées-sorties dont Println, Print et Printf ;
- fyne fournit une pléthore de widgets d'interface graphique utilisateur[20], et est bien entendu multiplateforme : Windows, Mac, Linux, Android...
- io fournit des procédures d'entrées-sorties elles-mêmes, dont ReadFull, Seek, WriteString...
- math fournit un ensemble de fonctions mathématiques, telles que Min, Max, Sqrt, Log...
- os interface le système, par exemple pour ouvrir et fermer des fichiers, dont OpenFile, ReadAt...
- strings fournit une cinquantaine de fonctions traitant des chaînes de caractères ;
- time fournit des outils de mesure des temps d'exécution, dont time.Now et time.Since().
Les bibliothèques sont tantôt indépendantes, tantôt dépendantes. Il existe par ailleurs plusieurs façons de faire des choses similaires. Par exemple pour lire un fichier, on pourra utiliser ioutil.ReadAll, file.Read() ou bufio.NewScanner().
On obtient la liste des bibliothèques depuis la ligne de commande par go list all
.
Exemple de programme
Go admet l'appel récursif des programmes, ce qui peut parfois les rendre plus lisibles, sans perte de vitesse excessive :
package main
import "fmt"
import "time"
var s [61]int
func fib(n int) int {
if n < 3 {
return 1
}
if s[n] != 0 {
return s[n]
}
s[n] = fib(n-1) + fib(n-2)
return s[n]
}
func main() {
var i int
t0 := time.Now()
for i = 1; i <= 60; i++ {
fmt.Printf("fib(%d) = %-15d\t", i, fib(i))
}
println()
println("Durée :", time.Since(t0).Seconds())
}
Ce programme est formaté à la manière standard du go par l'utilitaire gofmt avec les options -s (simplifier le code si possible) et -w (écrire le code modifié in-situ). Cet utilitaire aligne les niveaux de profondeur du programme, facilitant la maintenance en particulier si plusieurs développeurs doivent maintenir le même code. On remarquera qu'il n'aligne pas verticalement les accolades ouvrantes et fermantes, la plupart des éditeurs actuels (2018) se chargeant de signaler visuellement les correspondances en mode édition.
Possibilités évoluées, syntaxe désuète, lisibilité par rapport à C
Les choix syntaxiques de Go ne font pas l'unanimité. Si le langage se réclame simpliste dans son écriture, certains lui reprochent des partis pris trop impactants et dogmatiques à cet égard[21] en qualifiant sa syntaxe de confuse[22],[23] et son compilateur d'une rigidité questionnable[24], citant entre autres :
- la portée des variables contrôlée par la présence ou non d'une majuscule ;
- l'absence d'opérateur ternaire ;
- le manque de sucre syntaxique ;
- le refus de compilation s'il existe des variables non utilisées ;
- la gestion des erreurs et notamment les conditions répétitives inhérentes à leur vérification[25] ;
- l’incohérence de certaines APIs du langage comme les channels[26].
Le langage s'est fait reprocher d'avoir « un moteur de Ferrari dans une carrosserie de Ford T »[27].
En revanche, Go propose de simplifier la syntaxe du C, intentionnellement conservée en C++ pour assurer la compatibilité ascendante, en supprimant par exemple les parenthèses syntaxiquement inutiles derrière le if
et le for
, en proposant un fall-through par défaut dans un switch
, etc. Ces modifications peuvent fournir des programmes plus lisibles[28].
Projets utilisant Go
Liste d’applications libres notables écrites en Go[29] :
- Docker - Création, déploiement et exécution d'application dans des conteneurs.
- Go Ethereum : Une des trois implémentations originales (avec C ++ et Python) du protocole Ethereum.
- Gogs - Forge multiplateforme fondée sur Git.
- Grafana - Outil de monitoring, d'analyse de métriques et de création de tableaux de bord.
- Kubernetes - Système de gestion d'applications conteneurisées.
- Hugo : générateur de sites web statiques.
- Caddy (en) : Serveur de pages Web.
- Syncthing : application de synchronisation de fichiers pair à pair open source disponible pour Windows, Mac, Linux, Android, Solaris, Darwin et BSD.
- Terraform : Environnement logiciel d'« infrastructure as code » publié en open-source par la société HashiCorp.
- Rclone : Utilitaire de synchronisation de fichiers dans le Cloud ou en montage de système de fichiers.
Notes et références
- « https://go.dev/doc/devel/release#go1.19 »
- « https://go.dev/doc/go1.19 »
- « https://twitter.com/golang/status/1546981570145288193 »
- (en) « Go on Plan9 ».
- (en) « Text file LICENSE » (consulté le ).
- (en) « Additional IP Rights Grant », sur golang (consulté le ).
- (en) https://techcrunch.com/2009/11/10/google-go-language/.
- (en) « FAQ - The Go Programming Language », golang.org, 6 octobre 2011.
- (en) « From Parallel to Concurrent ».
- (en) [vidéo] Rob Pike sur la programmation concurrente sur YouTube.
- Cette notion avait été introduite dans PL/I en 1970 en faisant suivre un appel de sous-programme du mot TASK.
- « Frequently Asked Questions (FAQ) - The Go Programming Language », sur golang.org (consulté le )
- « Frequently Asked Questions (FAQ) - The Go Programming Language », sur golang.org (consulté le )
- Voir Message Passing Interface.
- (en) Rob Pike, « Go at Google » (consulté le ).
- La version 6.3 d'Unicode comprenant 210 000 possibilités de caractères, plus de 21 bits sont nécessaires et on peut supposer qu'une rune occupera la même place qu'un
int32
. Le standard initial de Go était qu'une rune occupe autant de place qu'unint16
. Aucun code source n'a dû pour autant être modifié. - Chaînes en langage Go : les runes
- « Defer, Panic, and Recover », sur blog.golang.org, .
- (en) https://github.com/go-gl.
- Description de Fyne en français
- (en) « Ten Reasons Why I Don't Like Golang », sur www.teamten.com, (consulté le )
- (en) « My Thoughts on Go », sur blog.goodstuff.im, (consulté le )
- (en) Cliff Berg, « The "go" language is a mess », sur Value-Driven IT, (consulté le )
- (en) « Go is a poorly designed language », sur aletheia.icu, (consulté le )
- (en) Jesse Hallett, « Changes I would make to Go », sur sitr.us, (consulté le )
- (en) « Go channels are bad and you should feel bad », sur www.jtolio.com, (consulté le )
- Langage Go : une Ford T avec un moteur Ferrari
- « A C++ developer looks at Go (the programming language), Part 1: Simple Features », sur www.murrayc.com (consulté le )
- (en) « Go Projects »
Annexes
Liens externes
- (en) Site du logiciel
- (en) Go FAQ
- Portail de la programmation informatique
- Portail des logiciels libres
- Portail de Google
- Portail de l’informatique