🎯 Contexte
Aujourd’hui, j’ai passé un entretien technique.
Cela faisait trois ans que je n’en avais pas passé, et encore moins en Go. Autant dire que j’étais un peu rouillé sur l’exercice en lui-même : coder devant quelqu’un, en étant observé, ce n’est jamais tout à fait comme coder seul.
Petit retour d’expérience, à chaud, sur ce qui s’est bien passé, ce qui s’est moins bien passé, et ce que j’en retiens.
Vue d’ensemble des 3 exercices :
| # | Sujet | Temps attendu | Temps réel | Verdict |
|---|---|---|---|---|
| 1 | Bug fix + TDD | 5–10 min | ~20 min | 🟡 trop long |
| 2 | Bug de mutation | ~2 min | 5–10 min | 🟠 trop lent |
| 3 | Concurrence | NC | ~25–30 min | 🔴 le plus laborieux |
🤝 Le déroulement
Premier point positif : l’ambiance.
L’entretien s’est déroulé dans la bienveillance, et je pense qu’ils ont vite senti que je n’étais pas totalement à l’aise avec l’exercice.
Je suis quelqu’un qui a besoin de prendre son temps pour bien comprendre un problème, et en particulier pour comprendre l’énoncé d’un exercice de programmation, que je ne trouve pas toujours très explicite.
Ça s’est d’ailleurs vu : même après avoir réussi à installer les projets (avec une petite frayeur sur leur projet Go qui ne voulait pas s’importer correctement dans GoLand), il m’a fallu un moment pour vraiment démarrer.
🐛 Exercice 1 — un bug fix, et un vrai rappel sur le TDD
Sur ce premier exercice, un des interlocuteurs m’a arrêté net quand il m’a vu modifier le test.
Et il avait totalement raison. Le but n’était pas de faire évoluer un comportement pour une nouvelle fonctionnalité, mais de corriger un bug : le test était volontairement rédigé pour faire échouer le programme. C’est donc le code de prod qu’il fallait corriger, pas le test.
En clair : l’étape « red » du TDD était déjà faite. Il ne restait que le reste du cycle :
Une évidence sur le papier, beaucoup moins évidente sous le stress d’un entretien, il m’a fallu une bonne dizaine de minutes pour vraiment comprendre le sujet.
Une fois le déclic fait, j’ai itéré assez vite, mais l’exercice m’a quand même pris une vingtaine de minutes au total, bien trop long pour ce qu’il demandait (je pense qu’il aurait dû me prendre 5 à 10 minutes).
En appliquant mes réflexes TDD, que j’ai beaucoup pratiqués par le passé, j’ai découvert au passage un petit bug dans l’ordonnancement de leurs tests. L’occasion d’échanger sur nos manières de tester : j’ai l’habitude du table testing, ou de tests avec une ou deux assertions pour la partie erreur en Go, alors que mes interlocuteurs avaient plutôt l’habitude de faire évoluer un même test avec plusieurs assertions pour couvrir davantage de cas. Intéressant de voir la différence d’habitudes selon les équipes.
🔀 Le piège du tri de slice
Le test suivant portait sur le tri d’un slice. Pas que je ne savais pas faire, avec l’autocomplétion actuelle, c’est même plutôt rapide, mais je me suis fait avoir sur quelque chose que je connais pourtant bien : un slice en Go pointe vers une structure sous-jacente, donc la modifier modifie l’état interne partagé.
Concrètement, l’autocomplétion IA m’a envoyé sur une mauvaise piste, et avec le stress, ça a cassé. Heureusement, un des interlocuteurs m’a redirigé vers la bonne approche sous mes yeux.
Morale : pensez à cloner vos slices quand vous voulez préserver leur état d’origine.
🧮 Range indexé vs range over, et une histoire d’allocation
Le dernier test de cet exercice, une recherche basique, s’est réglé rapidement. Il a surtout donné lieu à un échange intéressant : je n’ai pas utilisé de range classique mais un range indexé, ce qui a un peu surpris un des interlocuteurs.
La raison : chez mon client actuel, une règle de lint nous rappelle le fameux piège du « copy over range » en Go, et nous pousse à indexer nos slices pour limiter les allocations mémoire inutiles. Mon interlocuteur est resté perplexe sur ce point, une divergence de pratiques entre équipes, sans doute.
Sur ce même sujet, j’ai laissé passer une triple allocation en boucle qui aurait pu être faite une seule fois, alors que c’est justement le genre de chose à laquelle je suis normalement sensible (allocation mémoire, temps de réponse).
Là-dessus, ils avaient parfaitement raison de le relever.
⚡ Exercice 2 — rapide, mais pas assez
Le deuxième exercice portait sur une situation de mutation, que j’ai identifiée assez vite. Ça m’a pris 5 à 10 minutes, alors que ça aurait dû être quasi instantané (2 minutes grand maximum). Rien à redire sur le fond, seulement sur le temps que j’ai mis.
🔄 Exercice 3 — concurrence, et un énoncé perfectible
Le troisième exercice, sans doute le plus long mais pas le pire, portait sur la concurrence en Go : channels et goroutines. Le test était lui aussi buggé, tout comme le code de prod, avec pour objectif de vérifier la maîtrise de ces sujets. Je trouve honnêtement l’exercice mal posé.
J’ai vite repéré un premier problème (un WaitGroup mal géré), mais j’ai eu davantage de mal à trouver le bug principal, une dizaine, quinzaine de minutes de réflexion.
C’est en grande partie dû au fait que je trouvais le code déjà mal structuré au départ.
À un moment, j’ai fini par verbaliser mon ressenti à l’interlocuteur en lui expliquant un truc bizarre que je trouvais qu’il faisait dans leur code :
faire transiter un message via une structure de comportement plutôt qu’une structure de données.
👉C’était bel et bien le second problème.
Vu que jusqu’à maintenant le code était général correct avec de petites modifications à apporter, je ne me suis pas douté que je pouvais faire des gros changements.
Une fois qu’il m’a donné carte blanche pour tout défaire et refaire, j’ai corrigé assez rapidement, jusqu’à buter sur un tout dernier point de blocage.
Le problème était identifié, j’ai mis quelques minutes à le résoudre, là aussi j’aurais dû être bien plus rapide.
Je pense que cet exercice mériterait d’être revu, l’énoncé n’étant à mon sens pas assez clair sur ce qui est réellement attendu.
Au final, en décrivant précisément ce qui se produisait, j’ai réussi à le finaliser, mais ça a été laborieux.
🧠 Bilan
De mon point de vue, j’ai raté cet entretien technique.
Ce n’est pas grave, ça arrive, et ça m’a surtout permis de me rendre compte de plusieurs choses :
Ce que j'en retiens
- 🎯 Refaire des petits exercices type entretien (LeetCode ou équivalent), ne serait-ce que pour s'entraîner à déchiffrer des énoncés parfois ambigus.
- 🔋 Mon cerveau tourne au ralenti en ce moment. Je suis dans une période de fatigue mentale importante et ce n'était pas nécessairement le plus opportun de faire un entretien technique dans cette période.
💬 Feedback sur l’entretien
Dans l’ensemble, c’était un bon entretien, mais il a manqué certaines choses à mon goût, surtout pour une cible d’Engineering Manager.
J’ai aussi été surpris de ne pas avoir eu de questions sur le design d’API ou d’architecture :
- pagination (ne jamais retourner une liste brute d’éléments),
- versioning,
- gestion des migrations de schéma de base de données, etc.
Je m’attendais à être challengé sur ces sujets, et leur absence est pour moi un petit manque dans cet entretien technique.
Au final, l’un des seuls vrais points de débat portait sur le refus des valeurs nil au profit d’un fallback systématique, un cas rencontré dans leur exercice autour de la couleur “red” : renvoyer une valeur vide plutôt que red.
👉 elle est utilisée comme valeur par défaut quand elle n’existe pas.
Remarque : je n’ai rien dit sur le moment, mais en Go ce débat n’a pas vraiment lieu d’être, le langage gère déjà nativement les valeurs par défaut (zero values). La question était donc assez mal calibrée pour du Go.
👉 À mon sens, le vrai problème était surtout un problème de nommage : la constante aurait dû s’appeler quelque chose comme
noColoroucolorAbsent.
Par ailleurs, c’est un point que je leur ai remonté, car ce genre de pratique induit une erreur de conception assez classique : on stocke cette valeur vide par défaut, ce qui peut coûter cher lors d’une migration de données, là où une colonne nullable ne coûte rien et exprime clairement l’absence / l’optionalité de la donnée.
Remarque : c’est pourquoi en Go, même si aujourd’hui c’est possible d’avoir des monades (type Option comme en Rust), il n’est pas nécessaire de l’avoir.
Le nil peut largement exprimer l’optionalité d’une donnée, là où dans d’autres langages, cela peut révéler une erreur technique.
En Go, par convention, on est censé renvoyer une erreur en retour de fonction (result, error) sauf pour les constructeurs of course (et même là, il peut y avoir débat 😉).
Ce genre de fallback masque aussi souvent un vrai problème, comment différencier une valeur vide d’une valeur absente ? Il masque des erreurs techniques, ce qui est plutôt à éviter, d’autant qu’en Go on a la chance d’avoir la gestion d’erreurs native et, par convention, de la faire remonter 💪. C’est d’ailleurs une pratique dont on est revenu chez mon client, qui l’utilisait aussi au début du projet.
Après, je reste ouvert à toute remarque sur ce point et cela peut dépendre du contexte métier, certainement que de leur côté, ils en ont besoin 👉 pas de jugement là dessus.
👉 Bref, débat sympa, mais qui tient plus à un débat philosophique que technique. D’un point de vue technique il n’y a pas raison de faire cela. Cela étant dit, je préfère discuter des problèmes que l’on rencontre en prod :
- services qui redémarrent souvent (parfois à cause d’OOMKilled sur k8s),
- asynchronisme des tâches lourdes,
- bases de données surchargées,
- tradeoff sur la gestion des resources (mémoire, cpu),
Remarque importante : Dans une équipe, ce qui est important c’est toujours d’établir des règles et de s’assurer qu’elles soient respecter. Ces règles doivent être enregistrer dans un document, le mieux un ADR (Architecture Decision Record). On peut ne pas être d’accord, mais on se doit de les respecter pour le bien du projet. Pour quel raison ? Les gens passent mais le projet reste. Il est plus facile de se retrouver dans un projet homogène où les règles sont respectées que dans un projet où tout le monde fait ce qu’il veut, créant une anarchie.
🎛️ Verdict
Entretien raté, mais c’est cool d’être de nouveau sous le feu des projecteurs.
Me voilà motivé pour ne plus rater les prochains 🚀
Et retrouver le détail de chaque exercice, dans des articles dédiés qui arriveront prochainement.

