Composition d’interfaces et bonnes pratiques
Petites interfaces et inversion des dépendances
Composition d’interfaces et bonnes pratiques est une leçon Go Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Go Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Go Academy comprend 4 leçons au total.
Composition d'interfaces
Les interfaces Go peuvent intégrer d'autres interfaces pour en composer de plus grandes :
package main
import "io"
// io.ReadWriter composes Reader and Writer
type ReadWriter interface {
io.Reader
io.Writer
}
// Your own composition:
type Processor interface {
io.Reader
Process() error
io.Closer
}
func main() { _ = (*Processor)(nil) }Principe des petites interfaces
Les interfaces Go les plus puissantes comportent une ou deux méthodes. Cela maximise le nombre de types qui peuvent les satisfaire :
io.Reader— 1 méthodeio.Writer— 1 méthodeerror— 1 méthodefmt.Stringer— 1 méthode
Les grandes interfaces sont plus difficiles à simuler et à tester.
Inversion des dépendances
Acceptez des interfaces dans les paramètres des fonctions plutôt que des types concrets. Cela découple votre code des implémentations spécifiques :
package main
import "fmt"
type Store interface {
Get(key string) (string, bool)
Set(key, val string)
}
func cache(s Store, key, value string) {
if _, ok := s.Get(key); !ok {
s.Set(key, value)
}
}
type MapStore struct{ m map[string]string }
func (ms *MapStore) Get(k string) (string, bool) { v, ok := ms.m[k]; return v, ok }
func (ms *MapStore) Set(k, v string) { ms.m[k] = v }
func main() {
s := &MapStore{m: map[string]string{}}
cache(s, "x", "hello")
v, _ := s.Get("x")
fmt.Println(v)
}Ségrégation des interfaces
Divisez les grandes interfaces en interfaces plus petites et ciblées. Les clients ne dépendent ainsi que des méthodes qu'ils utilisent :
package main
// Bad: large interface forces all methods
type BigStorage interface {
Read(key string) string
Write(key, val string)
Delete(key string)
List() []string
Backup() error
}
// Good: small, focused interfaces
type Reader interface{ Read(key string) string }
type Writer interface{ Write(key, val string) }
type Lister interface{ List() []string }
func readAll(r Reader) {} // only needs Read
func main() { _ = readAll }Retourner des types concrets
Les constructeurs doivent retourner des types concrets, et non des interfaces. Les appelants peuvent toujours affecter un type concret à une variable d'interface :
package main
type Logger interface{ Log(string) }
type ConsoleLogger struct{}
func (c *ConsoleLogger) Log(s string) {}
// Good: return concrete *ConsoleLogger
func NewConsoleLogger() *ConsoleLogger { return &ConsoleLogger{} }
// Avoid: return Logger (hides the concrete type)
// func NewConsoleLogger() Logger { return &ConsoleLogger{} }
func main() { _ = NewConsoleLogger() }Multiplication inutile des interfaces
Ne créez pas une interface pour chaque type « au cas où ». Créez des interfaces uniquement lorsque :
- Vous avez plusieurs implémentations maintenant ou prochainement
- Vous devez simuler la dépendance dans les tests
- Vous développez une bibliothèque et souhaitez découpler les appelants
Intégrer des interfaces pour étendre
Intégrez une interface pour ajouter des méthodes facultatives avec des valeurs par défaut :
package main
import "fmt"
type Handler interface{ Handle(msg string) }
type NamedHandler interface {
Handler
Name() string
}
func dispatch(h Handler) {
if nh, ok := h.(NamedHandler); ok {
fmt.Printf("[%s] ", nh.Name())
}
h.Handle("event")
}
type MyHandler struct{}
func (m MyHandler) Handle(msg string) { fmt.Println(msg) }
func (m MyHandler) Name() string { return "my" }
func main() { dispatch(MyHandler{}) }Simuler avec des interfaces
Définissez les dépendances sous forme d'interfaces ; injectez des simulations dans les tests :
package main
import "fmt"
type Clock interface{ Now() int64 }
type MockClock struct{ T int64 }
func (m MockClock) Now() int64 { return m.T }
func isExpired(c Clock, expiresAt int64) bool {
return c.Now() > expiresAt
}
func main() {
mc := MockClock{T: 1000}
fmt.Println(isExpired(mc, 500)) // true
fmt.Println(isExpired(mc, 1500)) // false
}Intégration d'interfaces ou de structures pour la réutilisation
Utilisez l'intégration d'interfaces pour composer l'API et l'intégration de structures pour réutiliser le code. Ces deux mécanismes ont des objectifs différents et ne doivent pas être confondus.
Détecter la conformité d'une interface à la compilation
Utilisez une vérification à la compilation avec un identifiant vide pour vérifier que votre type satisfait une interface :
package main
type Doer interface{ Do() }
type MyType struct{}
func (m *MyType) Do() {}
// Compile-time check — no runtime cost
var _ Doer = (*MyType)(nil)
func main() {}Vérification rapide
Quand devez-vous définir une nouvelle interface en Go ?
Récapitulatif : bonnes pratiques pour les interfaces
Points essentiels :
- Gardez les interfaces petites — une ou deux méthodes
- Composez les interfaces à partir d'interfaces plus petites
- Acceptez des interfaces et retournez des types concrets
- Créez des interfaces pour faciliter les tests et prendre en charge plusieurs implémentations
- Utilisez une vérification à la compilation par affectation à un identifiant vide
Exercice
Concevez une interface Notifier avec Notify(msg string) error. Implémentez-la pour EmailNotifier et SMSNotifier. Écrivez une fonction broadcast qui envoie des notifications à un []Notifier.
Questions Fréquemment Posées
La leçon « Composition d’interfaces et bonnes pratiques » est-elle gratuite ?
Oui — le texte complet de « Composition d’interfaces et bonnes pratiques » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Go Academy, passe à CoddyKit PRO. Le cours Go Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Composition d’interfaces et bonnes pratiques » ?
Petites interfaces et inversion des dépendances Tu pratiques Go Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Go Academy ?
Aucune expérience préalable n'est requise. Go Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Composition d’interfaces et bonnes pratiques » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Go Academy ?
Oui. Chaque leçon Go Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Définir et implémenter des interfaces
- Interfaces essentielles de la bibliothèque standard
- Assertions de type et switch de type
- Composition d’interfaces et bonnes pratiques