Le pont entre Go et le système d'exploitation : appels système, pipes, sockets Unix, mémoire, profilage. Inégal, utile par morceaux.
Pourquoi ce livre
Vous écrivez un programme Go. Il écrit dans un fichier, parle à un autre programme, réserve de la mémoire. Le langage rend ces gestes simples, et cache ce qui se passe dessous. Le jour où la mémoire grimpe, il faut pourtant regarder sous le langage.
Le livre d'Alex Rios, ingénieur brésilien, fait ce tour sous le langage. Sa thèse, telle que je la lis : un programme Go ne fait rien seul, il demande tout au système d'exploitation. Comprendre ces demandes permet ensuite de mesurer au lieu de deviner.
Ce tour sous le langage, je le cherchais. Je code en Go en production depuis 2021, sur une plateforme crypto. Mon quotidien : l'Event Sourcing, Kubernetes, et des connecteurs qui reçoivent en temps réel les flux de plusieurs plateformes d'échange. Ma bibliothèque a déjà Learning Go de Jon Bodner (la fiche, 8,4/10), qui enseigne le langage. Ce qui se passe sous le langage, Learning Go le laisse de côté. D'où ce livre, lu sur ExpertEdge, l'abonnement de Packt.
Je l'ai lu en entier, en version cours : 106 leçons annoncées, 91 dans le texte, 6 h 48. Le cours compte un projet final : un cache réparti sur plusieurs machines.
J'en garde huit idées. Les sept premières forment trois familles. Les trois premières montrent comment un programme parle au système : au noyau, puis aux autres programmes. Les deux suivantes portent sur la mémoire. Les deux d'après apprennent à mesurer et à observer un programme. La dernière suit le projet final, qui sort de la machine unique.
Les idées qui restent
1Le programme Go demande, le noyau décide
Première famille : comment un programme parle au système, en commençant par le disque. Quand votre programme écrit un fichier, il ne touche pas le disque lui-même. Il le demande au noyau, le cœur du système d'exploitation, seul autorisé à parler au matériel. Cette demande s'appelle un appel système, ou syscall : write pour écrire, open pour ouvrir.
Rios en fait une image. Le noyau joue « le rôle d'un agent strict de contrôle aux frontières » (leçon 10). Chaque appel système est un passeport qu'il examine avant de laisser passer.
Ce passeport doit dire sur quoi il porte. L'appel système désigne sa cible par un numéro, le descripteur de fichier, que le système donne à chaque ressource ouverte. Un shell en donne trois à chaque programme : 0 pour l'entrée, 1 pour la sortie, 2 pour les erreurs. L'outil strace rend ces échanges visibles, car il affiche les appels système d'un programme :
strace -e write ./app
write(1, "Hello, World!", 13) = 13
Dans cette ligne, le 1 est le descripteur de la sortie. Le 13 est le nombre d'octets écrits.
open, le chemin est le même : seul le nom de l'appel change.Reste à savoir quel code Go émet ces appels système. Le livre présente trois paquets, du plus haut au plus bas :
os: il enveloppe les appels système de façon portable. Par exemple,os.Setenv(clé, valeur)marche sur tous les systèmes.syscall: un cran plus bas, ce paquet est gelé, sans plus aucun changement. La raison : les systèmes évoluent plus vite que Go ne peut suivre.golang.org/x/sys: le remplaçant desyscall. C'est un module à part, plus facile à maintenir. Il garde les appels propres à chaque système, Linux ou Windows.
La règle du livre en découle : passer par os, et n'appeler x/sys directement que « dans des cas exceptionnels » (leçon 10).
2Tout est fichier, même le pipe qui relie deux programmes
Après le disque, le programme parle aux autres programmes. Un programme en cours d'exécution s'appelle un processus. Le moyen le plus simple de relier deux processus est le pipe (tuyau) : un conduit en mémoire, à sens unique. Un processus écrit d'un côté, l'autre lit de l'autre côté.
Le | du shell en est un. Dans cat log.txt | grep ERROR, cat écrit les lignes du fichier dans le pipe. grep les lit et garde celles qui contiennent ERROR. Le livre distingue deux sortes de pipes.
Le schéma oppose ces deux sortes :
- Le pipe anonyme relie un processus parent aux processus qu'il a lancés, ses enfants. Il disparaît avec eux.
- Le pipe nommé, ou FIFO (premier entré, premier sorti), est un fichier spécial. Il vit dans le système de fichiers, donc deux processus quelconques peuvent l'ouvrir par son nom.
Le pipe nommé montre que tout est fichier : il relie deux programmes, et il a pourtant un nom dans le système de fichiers. Le livre l'explique avec une boîte aux tâches de bureau. Sa création prend une ligne :
syscall.Mkfifo("/tmp/boite", 0600) // 0600 : seul le propriétaire y accède
Cette ligne ramène à la règle de l'idée 1. Go n'a pas de os.Mkfifo : la création passe par syscall ou par golang.org/x/sys/unix. Créer un pipe nommé est donc un de ces cas exceptionnels. Or le livre change de paquet d'un exemple à l'autre. Il écrit unix.Mkfifo à la leçon 28, puis syscall.Mkfifo, le paquet gelé, à la leçon 29. Son outil de logs appelle même os.Mkfifo, qui n'existe pas : ce code ne compile pas tel quel.
Le livre ajoute deux conseils sur les pipes :
- Des noms aléatoires. Un intrus peut créer d'avance le pipe nommé que votre programme attend : c'est l'attaque de « name squatting ». Un nom imprévisible déjoue cette attaque (leçon 29).
- Pipe ou canal ? Une goroutine est une tâche légère qui tourne à l'intérieur d'un programme Go. Un canal relie deux goroutines, comme un pipe relie deux processus. La règle est nette : les pipes entre processus, les canaux entre goroutines.
3La socket Unix, le téléphone interne de la machine
Le pipe a une limite : il va dans un seul sens. La socket, une prise de communication, permet à deux processus de se répondre. La socket de domaine Unix relie deux processus de la même machine, comme un téléphone interne.
L'image se décode ainsi. Un appel réseau classique compose un numéro public : une adresse IP et un port. Le téléphone interne se contente d'un nom de poste, ici un chemin de fichier. Le livre en tire trois avantages :
- pas de surcoût de protocole réseau
- un chemin de fichier pour adresse
- des droits d'accès qui sont ceux du fichier : l'accès « peut être contrôlé par les permissions du système de fichiers » (leçon 31).
l, _ := net.Listen("unix", "/tmp/svc.sock") // serveur
c, _ := net.Dial("unix", "/tmp/svc.sock") // client
Le serveur écoute avec Listen, le client appelle avec Dial. Ce chemin de fichier a un revers. Listen crée d'abord la socket dans le noyau, puis la lie au chemin, qui devient un fichier. Ce fichier reste après l'arrêt du programme, « jusqu'à suppression explicite » (leçon 31). D'où le os.Remove du livre avant d'écouter : il efface le fichier laissé par une exécution précédente.
Le même fichier se supprime aussi à l'arrêt, grâce aux signaux. Un signal est un message bref que le système envoie à un processus. Sur SIGINT (Ctrl+C) ou SIGTERM (la demande d'arrêt du système), le serveur du livre ferme l'écoute et supprime le fichier (leçon 31).
4Le ballast : gonfler la mémoire pour la nettoyer moins souvent
Deuxième famille : la mémoire. En Go, on ne libère pas la mémoire à la main. Le GC (garbage collector, ramasse-miettes) s'en charge : il repère la mémoire que plus rien n'utilise et la libère. Il fait partie du runtime, le code livré dans chaque binaire Go, qui gère la mémoire et les goroutines.
Le GC se déclenche quand le tas a doublé depuis la dernière collecte. Le tas est la mémoire que le programme réserve pendant qu'il tourne. Sur un petit tas, ce doublement arrive vite, donc le GC tourne sans cesse. C'est une poubelle trop petite, qu'il faut vider sans arrêt.
Ce doublement n'est pas gravé dans le marbre. Il dépend de GOGC, une variable d'environnement : un réglage passé au programme au moment de le lancer. Sa valeur par défaut, 100, laisse le tas grandir de 100 % avant la collecte suivante. Le livre compare GOGC au thermostat d'une maison (leçon 37). À 50, le GC passe plus souvent, et le tas reste petit. À 200, il passe moins souvent, et la mémoire monte. La valeur off coupe le GC.
Le ballast agrandit la poubelle sans toucher à GOGC. C'est « une grande allocation de mémoire qui n'est jamais utilisée » (leçon 39), par exemple make([]byte, 10<<30), soit dix gibioctets. Le ballast gonfle le tas, donc le seuil du doublement recule. La poubelle est plus grande : on la vide moins souvent. Le livre conseille d'essayer GOGC avant le ballast, car c'est la voie la moins intrusive (leçon 39).
Dix gibioctets inutiles ne coûtent pourtant pas dix gibioctets de RAM. Le livre note que le ballast reste surtout en mémoire virtuelle (leçon 39). La mémoire virtuelle est une réservation : le système ne fournit la mémoire réelle que si le programme y touche. Or le ballast n'est jamais touché. Il relève donc le seuil du GC sans peser sur la mémoire réelle.
Le livre appuie la technique sur une histoire vraie, chez Twitch, le site de vidéo en direct. Un service de passerelle d'API, la porte d'entrée qui reçoit les requêtes, y subissait des « refresh storms ». Quand le direct d'un streamer tombe, ses spectateurs rechargent la page en rafale. Avec le ballast, le livre rapporte, en pic de charge (leçon 39) :
- environ 99 % de cycles de GC en moins
- 30 % de CPU en moins
- 45 % de latence en moins au 99e centile, la latence que 99 % des requêtes ne dépassent pas.
Le livre liste aussi six cas où éviter le ballast. Le plus important : le ballast peut masquer un défaut du code.
5GOMEMLIMIT : un plafond mémoire souple qui met le ballast à la retraite
Le ballast a une date de péremption, et le livre la donne aussitôt. La technique n'est pertinente « que jusqu'à Go 1.19 » (leçon 39). Son successeur est GOMEMLIMIT, une autre variable d'environnement, comme GOGC.
GOMEMLIMIT=512MiB ./app
Cette variable fixe un plafond souple pour la mémoire gérée par Go. Souple, parce que le GC devient plus agressif à l'approche de la limite, sans interdire de la dépasser. Le livre compare ce plafond à un panneau de vitesse « qui suggère une vitesse sûre mais ne peut pas freiner votre voiture » (leçon 40).
Faut-il garder le ballast en plus ? Le livre juge le cumul inutile : il « peut être redondant, comme porter deux montres pour donner la même heure » (leçon 40).
Le chapitre s'achève sur les arenas, des zones de mémoire libérées d'un coup, au lieu d'objet par objet. Le livre prévient qu'elles peuvent « ne pas exister dans les versions futures » (leçon 40). Il pose enfin trois questions de bon sens. L'une d'elles annonce la suite : sans mesure, « vous devinez » (leçon 40).
6Mesurer avant d'optimiser : quatre outils, du plus simple au plus fin
Troisième famille : mesurer pour ne plus deviner. Le livre donne quatre outils, que je range du plus simple au plus fin :
- regarder le GC travailler, sans écrire de code
- demander au compilateur où vivent les variables
- chronométrer une fonction, puis comparer deux versions
- chercher où part le temps, avec un profil.
Le premier outil reprend le GC de l'idée 4. Lancé avec GODEBUG=gctrace=1, le programme écrit une ligne à chaque collecte. Chaque ligne donne la durée de la collecte, la part du temps passée dans le GC, la taille du tas avant et après (leçon 38). Règle du livre : un tas qui grandit sans redescendre d'autant après les collectes « peut signaler une fuite de mémoire » (leçon 38).
Le deuxième outil interroge le compilateur. Une variable vit à l'un de deux endroits. La pile est la mémoire propre à un appel de fonction : elle se libère toute seule au retour de la fonction. Le tas, lui, attend le GC. L'image du livre : sur la pile, la variable est un ami qui dort une nuit sur le canapé. Sur le tas, elle signe un bail (leçon 44).
Le compilateur choisit l'endroit par l'analyse d'échappement. Une variable dont l'adresse sort de sa fonction « s'échappe » : elle doit survivre à l'appel, donc elle part sur le tas. L'exemple du livre est une fonction createPerson, qui crée une personne et renvoie son adresse. La commande go build -gcflags "-m -m" affiche alors moved to heap: p (leçon 44). Traduction : l'objet créé donnera du travail au GC.
Le troisième outil chronomètre. Un benchmark mesure le temps d'une fonction. En Go, il s'écrit func BenchmarkX(b *testing.B) et se lance avec go test -bench. Pour comparer deux versions du code, le livre enregistre deux séries de mesures, old.txt et new.txt. Il les donne ensuite à benchstat (leçon 46). Cet outil affiche l'écart en pourcentage, avec une valeur p. Sous 0,05, l'écart a peu de chances de venir du hasard.
Un benchmark peut aussi tromper. Le livre liste six pièges du benchmark (leçon 47). Le plus sournois vient du compilateur : il supprime un calcul dont personne n'utilise le résultat. Le benchmark chronomètre alors du vide. La parade du livre : ranger le résultat dans une variable du paquet, pour que le compilateur garde le calcul.
Le quatrième outil répond à la question que le benchmark laisse ouverte. Un benchmark dit combien de temps prend une fonction, pas où ce temps part. Le profil CPU le révèle, grâce à pprof, l'outil de profilage fourni avec Go :
f, _ := os.Create("cpu.out")
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
Ce code enregistre le profil dans cpu.out. go tool pprof lit ensuite ce fichier, en texte ou en graphe de flammes. Dans ce graphe, chaque fonction est une barre, et une barre plus large pèse plus de CPU. Le profil mémoire suit le même geste, avec pprof.WriteHeapProfile.
7Journaux, métriques, traces : trois façons de regarder un service tourner
Un profil se lance le temps d'un test. Un service, lui, tourne en continu, et il s'observe pendant qu'il tourne. Une partie du cours, environ un dixième du texte, donne trois outils pour cela :
- Les journaux structurés, avec
log/slog. Ils écrivent du JSON qu'on peut interroger. Le livre dit aussi quoi ne pas y écrire : mots de passe, données personnelles, gros binaires (leçon 60). - Les métriques, avec Prometheus, un serveur qui interroge votre service et stocke ses compteurs.
- Les traces, avec
runtime/trace, qu'on ouvre avecgo tool trace. Elles enregistrent ce que font les goroutines et le GC.
Les journaux viennent en premier, et le livre y fait deux comparaisons. La première oppose deux bibliothèques. Le livre refait le même exemple avec zap, une bibliothèque de journaux externe, puis tranche ainsi (leçon 59) :
- zap quand la vitesse prime et qu'on veut régler chaque détail.
- slog pour la simplicité, et pour son accord avec
context, le paquet qui transporte les délais et les valeurs d'une requête.
La seconde comparaison oppose deux usages des journaux :
- Les journaux de débogage sont très détaillés et temporaires. Ils servent aux développeurs, le temps de traquer un bug. Exemple : la liste des fonctions en cours au moment d'une erreur.
- Les journaux de supervision sont plus sobres et permanents. Des outils les agrègent, et l'équipe d'exploitation les lit aussi. Exemple : une ligne par requête HTTP, avec la méthode, l'URL et le code de réponse.
Pour le livre, la différence tient à « l'objectif, le niveau de détail, le public et la durée de vie » (leçon 59).
Le livre laisse le choix entre slog et zap. J'ai tranché plus net dans mon article sur les conventions Go 2025-2026. Depuis Go 1.21, slog est dans la bibliothèque standard, et j'y écris que zap est « en sursis ». Pour un projet neuf, slog suffit, sans dépendance à installer, sauf si la vitesse compte : mon article ne la mesure pas.
Après les journaux, les métriques. Elles se déclinent en quatre sortes :
- le compteur, qui monte seulement (par exemple, le nombre de requêtes reçues)
- la jauge, qui monte et descend (par exemple, la mémoire utilisée)
- l'histogramme, qui montre la distribution, par exemple le 95e centile des latences
- le résumé, qui calcule des quantiles à la volée (le centile en est un cas particulier).
OTel (OpenTelemetry) réunit les trois outils. C'est le standard ouvert d'instrumentation, la façon dont un programme émet ses journaux, ses métriques et ses traces. Un collecteur, un relais qui reçoit ces données et les redirige, se lance avec docker-compose. Dans OTel, un span est un segment de trace qui suit une requête.
Le livre reconnaît une limite : la partie journaux n'est « pas prête » (leçon 63) dans le SDK Go d'OTel, sa boîte à outils de développement. L'exemple du livre, lui, reste minimal. Il n'ouvre qu'un seul span, dans un seul handler, la fonction qui traite une requête HTTP :
_, span := otel.Tracer("example-tracer").Start(r.Context(), "handleRequest")
defer span.End() // ouvre un segment de trace, le ferme à la sortie de la fonction
8Le projet final : un cache distribué bien pesé, mais qui ne vérifie pas ses copies
Dernière idée : le projet final quitte la machine unique des sept premières. Le livre y construit un cache distribué. Un cache garde des réponses en mémoire pour les resservir vite, sans refaire le travail. L'image du livre : un mini-frigo près du bureau, pour ne pas aller à la cuisine à chaque soif (leçon 70). Distribué, ce cache tourne sur plusieurs machines à la fois, que le livre appelle des nœuds.
Le test du livre raconte le projet en deux requêtes. On lance deux nœuds, sur les ports 8080 et 8081. On écrit la clé foo, avec la valeur bar, sur le premier nœud. On la relit sur le second, qui répond bar : l'écriture a voyagé d'un nœud à l'autre (leçon 75).
Pour en arriver là, le livre ajoute trois mécanismes :
- L'éviction retire des entrées, car la mémoire a une fin. Deux règles se combinent (leçon 73). La règle LRU (least recently used, la moins récemment utilisée) retire l'entrée lue il y a le plus longtemps, quand le cache est plein. La règle TTL (time to live, durée de vie) retire une entrée trop vieille.
- La réplication copie chaque écriture sur les autres nœuds. Elle se fait de pair à pair : chaque nœud envoie lui-même ses écritures à tous les autres, sans nœud chef (leçon 75).
- Le partitionnement (sharding) donne à chaque clé un nœud propriétaire, choisi par hachage cohérent. Une fonction de hachage transforme un texte en nombre, et ce nombre place nœuds et clés sur un anneau. Une clé revient « au premier nœud qu'elle rencontre » en tournant dans le sens horaire (leçon 75). Un nœud qui reçoit la clé d'un autre la lui transmet (leçon 76).
Ce projet vaut surtout par ses compromis. Avant chaque mécanisme, le livre compare les options et dit pourquoi il choisit. Pour la réplication, il confronte quatre familles sur cinq critères, dont la tolérance aux pannes et l'accord entre les copies (leçon 74) :
- Primaire et copies : un seul nœud reçoit les écritures, et sa panne les bloque toutes.
- Pair à pair : aucun point unique de panne, mais les copies ne s'accordent souvent qu'avec retard. C'est la cohérence à terme (eventual consistency).
- Publication-abonnement : un relais diffuse les écritures, et devient le point fragile.
- Consensus (Raft, Paxos) : les copies restent d'accord, au prix de la latence et de la complexité.
Le livre retient le pair à pair, sans le vendre pour parfait : c'est « une approche raisonnable pour démarrer » (leçon 74).
Le code, lui, n'a pas la rigueur de ces comparaisons. Le nœud répond « OK » au client sans attendre l'envoi des copies. Chaque copie part ensuite seule, sans accusé de réception ni nouvel essai. Dans ce code, un nœud en panne perd donc pour de bon les écritures faites pendant son absence. Voici la fin d'un envoi, dans la fonction replicateSet (leçon 75) :
_, err = client.Do(req)
if err != nil {
log.Printf("Failed to replicate to peer %s: %v", peer, err)
}
log.Println("replication successful to", peer) // atteint même après l'échec
Ces cinq lignes cachent deux défauts. Après l'échec, aucun return n'arrête la fonction : le journal écrit « replication successful » juste après l'erreur. Le _ de la première ligne jette la réponse de l'autre nœud, donc le corps de cette réponse, son contenu, n'est jamais fermé. Or le chapitre du livre sur les bonnes pratiques l'enseigne : un corps non fermé « peut garder ouvertes les sockets sous-jacentes plus longtemps que nécessaire » (leçon 84).
Le partitionnement, lui, ne se juge pas sur pièces : le texte montre les signatures de l'anneau, pas leur code (leçon 76). Traduction : lisez ce projet pour sa façon de choisir, pas pour son code.
Mon avis, honnêtement
Mon verdict, 6,0 sur 10 : un bon guide de ce que Go demande au système, aux exemples inégaux. Je l'ai lu avec deux questions. Comment un programme Go parle-t-il au noyau, aux fichiers et aux autres processus ? Comment se comporte-t-il face à la mémoire ? Le livre répond bien aux deux, là où Learning Go s'arrête au langage.
Sa force : un fil qui relie tous les chapitres. Tout passe par des descripteurs de fichier, le noyau décide, et os vient d'abord. Le code tourne, strace compris. Le passage du ballast à GOMEMLIMIT montre même une technique devenir inutile en direct, chiffres de Twitch à l'appui. Le projet final ajoute une qualité plus rare : il compare les options avant de coder.
Ses faiblesses, avec leur coût pour vous :
- Des titres plus ambitieux que leur contenu. Le titre « Distributed Lock Manager » (leçon 24) promet de la distribution, et livre un verrou de fichier local. Ce verrou (
fcntl, de type « advisory ») ne vaut que si chaque processus le respecte de bonne volonté. Le seul exemple vraiment distribué est le projet final, une maquette de démonstration (idée 8). Coût : n'en attendez pas un vrai système distribué. - Des exemples faux, ou qui ne compilent pas. Deux exemples de code WebSocket, le protocole des échanges en temps réel, ne compilent pas tels quels (leçon 56). Le client appelle
contexto.Background()au lieu decontext.Background(). Le serveur ferme une parenthèse de trop. Dans le chapitre sur les bonnes pratiques, l'exemple de mmap copie tout le fichier avant de « synchroniser » une copie (leçon 82). Le « correctif » d'une fonction de connexion,connectToService, ne change rien (leçon 84). Coût : relisez le code avant de le copier, réplication du projet final comprise (idée 8). - Des chiffres qui ne se recoupent pas. La pause du GC est le moment où tout le programme s'arrête. Selon la leçon « Why Go? », elle dure en général « moins de 100 microsecondes », même dans le pire cas. La leçon 37 annonce « moins de 0,3 milliseconde » pour la première pause de la phase de marquage, soit trois fois plus. Le livre ne dit pas lequel retenir. Coût : mesurez votre propre pause avec gctrace (idée 6).
- Une voix qui s'étire. Dès la mi-parcours, les analogies s'enchaînent, avec des anecdotes génériques du genre « En repensant à mon parcours... je me souviens d'un projet ». Coût : il faut trier pour retrouver le propos.
Mon conseil : lisez-le pour la mémoire, les sockets et le profilage, et gardez-en le réflexe. Posez la limite mémoire, mesurez avec pprof et trace, ne devinez pas. Les écarts entre le livre et les sources officielles sont listés juste en dessous.
Odilon
Toujours valable en 2026 ?
Les bases, oui : descripteurs, signaux, pipes, sockets Unix, profilage. Le ballast et les arenas, eux, sont des curiosités historiques. Quelques exemples ont aussi vieilli : ioutil.ReadAll (leçon 84) est obsolète depuis Go 1.16 au profit de io.ReadAll, et x/exp/mmap (leçon 82) vient d'un module expérimental de Go.
Côté exactitude, j'ai comparé le livre aux notes de version de Go et à la norme de TCP. Ces vérifications sont de moi, pas du livre. Huit écarts :
- Le gel de
syscall. Le livre le date de Go 1.3 (leçon 10). Les notes de version de Go 1.4 l'annoncent une version plus tard. - L'arrivée de GOMEMLIMIT. Les notes de version de Go 1.19 l'annoncent dans cette version. Le livre écrit « depuis Go 1.20 » (leçon 40), alors qu'il borne lui-même le ballast à 1.19 (leçon 39).
- La retransmission sélective. TCP est le protocole qui garantit la livraison des données. Le livre décrit sa fiabilité « traditionnelle » par la retransmission « go-back-N » : tout renvoyer à partir du paquet perdu. Il présente ensuite la retransmission sélective, ou SACK, comme une technique pour UDP, le protocole sans connexion ni garantie de livraison (leçon 55). Or TCP la pratique aussi depuis la RFC 2018, le document de référence qui lui a ajouté l'acquittement sélectif.
rand.Seed. Cette fonction, présente dans ses listings, est obsolète depuis Go 1.20 : le générateur de nombres aléatoires s'amorce tout seul.slog. Le livre le dit « expérimental » en 1.21 (leçon 58). Ce paquet est pourtant dans la bibliothèque standard depuis cette version.- La fuite de
time.After. Le livre décrit un minuteur qui n'est pas ramassé tant qu'il n'a pas expiré (leçon 83). Depuis Go 1.23, un minuteur que le programme ne référence plus est ramassé tout de suite. Un appel àStopn'est plus nécessaire pour cela (notes de version de Go 1.23). singleflight. Ce paquet regroupe les appels identiques qui tournent en même temps, pour ne faire le travail qu'une fois. Le livre dit qu'il « permet de mettre en cache les résultats de la première exécution » (leçon 81). Il ne met rien en cache : un appel qui arrive après la fin du premier repart de zéro.OnceFunc. Le livre dit qu'elle « n'appellera f qu'une seule fois et renverra son résultat » (leçon 80). Sa signature prend une fonction sans résultat et renvoie une fonction sans résultat.
Pour qui ?
Lisez-le si
- vous connaissez Go (un à deux ans) et voulez comprendre ce qu'il demande au système sous le capot
- vous écrivez des services en conteneurs et devez régler la mémoire et le GC
- vous voulez un premier tour des sockets Unix, des pipes et de strace avec du code qui tourne
- vous avez lu Learning Go et cherchez la suite côté système
Passez si
- vous débutez en Go : lisez Learning Go d'abord (la fiche)
- vous attendez de vrais systèmes distribués : le verrou « distribué » est local et la réplication du projet final laisse ouverte la cohérence entre les copies
- vous voulez de l'observabilité complète : un seul span dans le code, et la propagation entre services n'est expliquée qu'en théorie (leçon 61)
Si vous ne lisez qu'un des deux, ce sera Bodner. Celui-ci vient ensuite, en lecture ciblée sur la mémoire et les sockets.
Ce livre fait partie d'ExpertEdge, l'abonnement aux livres techniques de Packt. Le code ODILON50 donne 50 % de remise sur l'abonnement annuel : le livre sur ExpertEdge. Lien affilié : je touche une commission si vous vous abonnez avec ce code, et mes notes n'en dépendent pas.
Pour aller plus loin
- La fiche Learning Go : le langage, avant le système.
- Le cours Concurrence avancée en Go : goroutines et canaux, le socle des chapitres de ce livre.
- Le cours HTTP et API en Go : serveur et client, côté TCP.
- Le cours Tests en Go : les benchmarks.
Fiche fondée sur la version cours ExpertEdge 2024, lue en entier. Source : leçons 1 à 91 lues en détail, sur les 106 annoncées, quiz exclus. Les citations, chiffres et exemples viennent du livre. Les passages « Ma lecture » sont de moi, pas du livre.
Commentaires (0)