Introduction : Mythes et réalité du programmeur Go
\n\nDans la communauté IT, il existe deux opinions polaires sur le travail d'un développeur Go. Certains disent que c'est un paradis pour perfectionniste : typage strict, absence d'héritage de classes et compilation fulgurante. D'autres, que ce sont des if err != nil à l'infini et une lutte avec les generics (même s'ils ont déjà été ajoutés).
Où est la vérité ? Comment se déroule réellement une journée de travail d'un développeur Go dans une entreprise moyenne qui écrit des microservices à forte charge ? Aujourd'hui, j'ouvre la porte de ma réalité. Pas de blabla – seulement du code, des outils et des cas concrets.
\n\nJe travaille dans une entreprise produit où Golang est le langage principal du backend. Notre stack : gRPC, PostgreSQL, Kafka, Kubernetes. Une histoire typique pour le développement moderne en Go. C'est parti.
\n\n08:30 – Matin : Plan et revue de code
\n\nLa journée ne commence pas par un café, mais par la consultation des notifications dans GitLab et Slack. Pendant que le cerveau est frais, c'est le meilleur moment pour vérifier les Merge Requests des collègues.
\n\nRoutine matinale : Que regardé-je en premier ?
\n- \n
- Erreurs dans CI/CD – si la build a échoué pendant la nuit, c'est la première tâche. \n
- Commentaires sur mon code – en Go, il est d'usage de faire des revues détaillées. \n
- Graphiques de monitoring – la latence a-t-elle baissé après le déploiement d'hier ? \n
À propos de la revue de code. Dans la communauté Go, il existe une règle non écrite : le code doit être simple. Si vous écrivez une usine à gaz complexe, on vous la renverra en revue. Exemple de commentaire typique d'un senior :
\n\n// Mauvais : abstraction excessive\ntype Processor interface {\n Process(ctx context.Context, data []byte) ([]byte, error)\n}\n\n// Bien : simple fonction\nfunc Process(ctx context.Context, data []byte) ([]byte, error) {\n // logique\n}\n\n\nÀ 09:00 – le stand-up quotidien. Nous ne perdons pas de temps avec de longs récits. Format : ce que j'ai fait hier, ce que je vais faire aujourd'hui, y a-t-il des blocages. Pas de « comment s'est passée votre soirée ».
\n\n09:30 – Immersion dans le code : Écrire un microservice en Go
\n\nAujourd'hui au programme – amélioration du service de notifications. C'est un microservice classique en Go qui reçoit des événements de Kafka et envoie des emails/push. Tâche : ajouter le support des templates.
\n\nD'abord, j'ouvre la structure du projet. En Go, on adopte une arborescence de dossiers minimaliste :
\n\nnotifier/\n├── cmd/\n│ └── server/\n│ └── main.go\n├── internal/\n│ ├── handler/\n│ ├── service/\n│ └── repository/\n├── pkg/\n│ └── models/\n└── go.mod\n\n\nJe commence par le modèle de données. En Go, pour travailler avec la base de données, on utilise souvent un Go ORM (par exemple, GORM) ou des requêtes SQL pures via sqlx. Je préfère sqlx – moins de magie, plus de contrôle.
\n\ntype Template struct {\n ID int64 `db:"id"`\n Name string `db:"name"`\n Content string `db:"content"`\n CreatedAt time.Time `db:"created_at"`\n}\n\nfunc (r *Repository) GetTemplateByName(ctx context.Context, name string) (*Template, error) {\n var t Template\n err := r.db.GetContext(ctx, &t, "SELECT * FROM templates WHERE name = $1", name)\n if err != nil {\n return nil, fmt.Errorf("get template: %w", err)\n }\n return &t, nil\n}\n\n\nNotez la gestion des erreurs. En Golang, il n'y a pas de try-catch. Chaque appel de fonction est vérifié pour les erreurs. Ce n'est pas un bug, mais une fonctionnalité – le code devient prévisible. En 5 ans de travail, je n'ai jamais attrapé un null pointer inattendu en production.
\n\n11:00 – Intégration avec gRPC
\n\nL'étape suivante – ajouter un endpoint gRPC pour l'administration. Dans le développement moderne en Go, gRPC est devenu un standard pour les services internes. Il est plus rapide que REST et génère des clients automatiquement.
\n\nD'abord, je décris le fichier proto :
\n\nsyntax = "proto3";\n\npackage notifier;\n\nservice TemplateService {\n rpc CreateTemplate (CreateTemplateRequest) returns (TemplateResponse);\