Comment réussir un entretien Go : les questions avancées les plus fréquentes

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Entretien avancé Go : des goroutines aux generics

\n\n

Un entretien pour un poste de développeur Go de niveau intermédiaire ou senior ne se limite pas à une simple vérification de la syntaxe. Les employeurs attendent une compréhension approfondie du modèle de concurrence, du fonctionnement du runtime, de la gestion de la mémoire et des particularités du typage. Dans cet article, nous analysons les questions avancées les plus fréquentes sur Golang qui vous aideront à réussir votre entretien technique. Nous ne nous attarderons pas sur les bases comme « qu'est-ce qu'une slice » — nous passerons directement aux sujets complexes avec des exemples de code.

\n\n

1. Goroutines, canaux et modèles de synchronisation

\n\n

Les questions sur les goroutines et les canaux sont des classiques de tout entretien. Cependant, au niveau avancé, on ne vous demandera pas seulement « qu'est-ce qu'une goroutine », mais aussi les subtilités du fonctionnement de l'ordonnanceur (modèle GMP) et l'utilisation correcte des primitives de synchronisation.

\n\n

Question : Comment fonctionne l'ordonnanceur de goroutines en Go ? Que sont G, M, P ?

\n

L'ordonnanceur Go utilise le modèle GMP : G (goroutine) — thread léger, M (machine) — thread OS, P (processor) — contexte d'exécution. P est lié à un processeur logique et gère la file d'attente des goroutines. Lorsqu'une goroutine se bloque (par exemple, sur un appel système), P peut basculer M vers une autre goroutine, ce qui assure un multitâche efficace sans créer des milliers de threads OS.

\n\n

Question : Quelle est la différence entre un canal bufferisé et non bufferisé ? Donnez un exemple de deadlock.

\n\n
// Canal non bufferisé — bloque l'émetteur jusqu'à la réception\nch := make(chan int)\ngo func() {\n    ch <- 42 // bloqué jusqu'à ce que main lise\n}()\nfmt.Println(<-ch) // 42\n\n// Canal bufferisé — ne bloque pas tant que le buffer n'est pas plein\nchBuf := make(chan int, 2)\nchBuf <- 1\nchBuf <- 2 // ok, buffer pas plein\n// chBuf <- 3 // deadlock, s'il n'y a pas de lecteur\n\n// Deadlock typique : lecture d'un canal non bufferisé vide\nchDead := make(chan int)\n// <-chDead // fatal error: all goroutines are asleep — deadlock!\n
\n\n

Question : Comment fermer un canal en toute sécurité ? Qu'est-ce que « range over channel » ?

\n

Seul l'émetteur doit fermer le canal. Le récepteur peut utiliser le deuxième paramètre (v, ok := <-ch) pour vérifier. L'itération for v := range ch se termine lorsque le canal est fermé. Toute tentative d'écriture dans un canal fermé provoque une panique.

\n\n
ch := make(chan int)\ngo func() {\n    for i := 0; i < 3; i++ {\n        ch <- i\n    }\n    close(ch) // obligatoire de fermer\n}()\nfor v := range ch {\n    fmt.Println(v) // 0, 1, 2\n}\n
\n\n

2. Interfaces, interface vide et assertions de type

\n\n

Les interfaces en Go sont des contrats. Lors d'un entretien, il est important de comprendre comment elles sont structurées en interne (structures iface et eface) et en quoi le typage statique diffère du typage dynamique.

\n\n

Question : Qu'est-ce qu'une interface vide (interface{}) et quand l'utiliser ?

\n

L'interface vide ne contient aucune méthode, donc tout type l'implémente. Elle est utilisée pour travailler avec des données de type inconnu (par exemple, json.Unmarshal). Cependant, abuser de l'interface vide viole le typage strict de Go et peut entraîner des erreurs d'exécution.

\n\n

Question : Comment fonctionne l'assertion de type ? Quelle est la différence avec le type switch ?

\n\n
var val interface{} = "hello"\n\n// assertion de type\nstr, ok := val.(string)\nif ok {\n    fmt.Println("C'est une chaîne :", str)\n}\n\n// type switch\nswitch v := val.(type) {\ncase string:\n    fmt.Println("Chaîne :", v)\ncase int:\n    fmt.Println("Nombre :", v)\ndefault:\n    fmt.Println("Type inconnu")\n}\n
\n\n

Question : Comment les interfaces sont-elles stockées en mémoire ?

\n

Chaque interface est composée de deux pointeurs : un vers le type (itable), l'autre vers la valeur (data). Pour l'interface vide (interface{}), c

Blogs

Book Recommendations