0Pricing
Go Academy · Leçon

Définir et implémenter des interfaces

Satisfaction implicite et interface vide

Définir et implémenter des interfaces est une leçon Go Academy gratuite sur CoddyKit. Ceci est la leçon 1 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.

Qu'est-ce qu'une interface ?

Une interface en Go est un ensemble de signatures de méthodes. Tout type qui implémente toutes ces méthodes satisfait implicitement l'interface : aucun mot-clé implements n'est nécessaire. On parle de typage structurel ou de typage par canard.

Déclarer une interface

Définissez une interface avec le mot-clé type :

package main
import "fmt"

type Shape interface {
    Area() float64
    Perimeter() float64
}

type Circle struct{ Radius float64 }
func (c Circle) Area() float64      { return 3.14159 * c.Radius * c.Radius }
func (c Circle) Perimeter() float64 { return 2 * 3.14159 * c.Radius }

func main() {
    var s Shape = Circle{5}
    fmt.Printf("Area: %.2f\n", s.Area())
}

Satisfaction implicite

Aucune déclaration d'intention n'est nécessaire. Si un type possède les bonnes méthodes, il satisfait automatiquement l'interface :

package main
import "fmt"

type Greeter interface{ Greet() string }

type English struct{}
func (e English) Greet() string { return "Hello" }

type Spanish struct{}
func (s Spanish) Greet() string { return "Hola" }

func say(g Greeter) { fmt.Println(g.Greet()) }

func main() {
    say(English{})
    say(Spanish{})
}

L'interface vide

interface{} (ou any depuis Go 1.18) est satisfaite par tous les types. Elle est utilisée lorsque le type est inconnu au moment de la compilation :

package main
import "fmt"

func printAny(v any) { fmt.Printf("%T: %v\n", v, v) }

func main() {
    printAny(42)
    printAny("hello")
    printAny([]int{1,2,3})
}

Valeurs d'interface

Une valeur d'interface contient deux éléments : un type concret et une valeur concrète. Une interface nil a ces deux éléments définis à nil :

package main
import "fmt"

type Animal interface{ Sound() string }
type Dog struct{}
func (d Dog) Sound() string { return "woof" }

func main() {
    var a Animal
    fmt.Println(a == nil) // true
    a = Dog{}
    fmt.Println(a == nil) // false
    fmt.Println(a.Sound())
}

Satisfaction de plusieurs interfaces

Un type peut satisfaire plusieurs interfaces simultanément :

package main
import "fmt"

type Reader interface{ Read() string }
type Writer interface{ Write(string) }
type ReadWriter interface{ Reader; Writer }

type File struct{ content string }
func (f *File) Read() string       { return f.content }
func (f *File) Write(s string)     { f.content = s }

func main() {
    var rw ReadWriter = &File{}
    rw.Write("hello")
    fmt.Println(rw.Read())
}

Affectation d'interfaces

Une interface plus large peut contenir une valeur concrète plus spécifique. L'affectation entre types d'interface exige que le type concret satisfasse les deux interfaces :

package main
import "fmt"

type Stringer interface{ String() string }

type Point struct{ X, Y int }
func (p Point) String() string { return fmt.Sprintf("(%d,%d)", p.X, p.Y) }

func main() {
    var s Stringer = Point{3, 4}
    fmt.Println(s.String())
}

Piège de l'interface nil

Une interface non nulle contenant une valeur concrète nulle n'est NOT égale à nil :

package main
import "fmt"

type MyErr struct{}
func (e *MyErr) Error() string { return "oops" }

func bad() error {
    var e *MyErr // nil pointer
    return e     // returns non-nil interface!
}

func main() {
    err := bad()
    fmt.Println(err == nil) // false — common gotcha
}

Les interfaces facilitent les tests

Définir les dépendances comme des interfaces permet de remplacer les implémentations réelles par des simulations dans les tests :

package main
import "fmt"

type EmailSender interface{ Send(to, body string) error }

type MockSender struct{ Sent []string }
func (m *MockSender) Send(to, body string) error {
    m.Sent = append(m.Sent, to)
    return nil
}

func notify(s EmailSender, addr string) { s.Send(addr, "hello") }

func main() {
    mock := &MockSender{}
    notify(mock, "a@b.com")
    fmt.Println(mock.Sent) // [a@b.com]
}

Accepter des interfaces, retourner des structures

Une bonne pratique en Go : les paramètres des fonctions devraient être des interfaces (pour plus de souplesse), tandis que les types retournés devraient être des types concrets (afin que les appelants sachent ce qu'ils obtiennent) :

package main

type Logger interface{ Log(string) }

type FileLogger struct{}
func (f *FileLogger) Log(s string) {}

func NewFileLogger() *FileLogger { // returns concrete
    return &FileLogger{}
}

func process(l Logger) {} // accepts interface

func main() { process(NewFileLogger()) }

Garder les interfaces petites

La bibliothèque standard de Go privilégie les interfaces minuscules : io.Reader possède une méthode, et io.Writer en possède une également. Les petites interfaces sont plus faciles à composer et à simuler.

Vérification rapide

Un type doit-il déclarer qu'il implémente une interface ?

Récapitulatif : interfaces

Points essentiels :

  • Les interfaces définissent un comportement, pas des données
  • La satisfaction est implicite : aucun mot-clé implements
  • L'interface vide (any) accepte tous les types
  • Méfiez-vous du piège de l'interface nil
  • Gardez les interfaces petites et ciblées

Exercice pratique

Définissez une interface Storage avec Save(key, value string) error et Load(key string) (string, error). Implémentez-la avec un MemStorage reposant sur une table associative, puis testez-la.

Questions Fréquemment Posées

La leçon « Définir et implémenter des interfaces » est-elle gratuite ?

Oui — le texte complet de « Définir et implémenter des interfaces » 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 « Définir et implémenter des interfaces » ?

Satisfaction implicite et interface vide 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 1 sur 4.

Combien de temps prend la leçon « Définir et implémenter des interfaces » ?

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

  1. Définir et implémenter des interfaces
  2. Interfaces essentielles de la bibliothèque standard
  3. Assertions de type et switch de type
  4. Composition d’interfaces et bonnes pratiques
← Retour à Go Academy