Definire e implementare le interfacce
Soddisfacimento implicito e interfaccia vuota
Definire e implementare le interfacce è una lezione Go Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Go Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Go Academy include 4 lezioni in totale.
Che cos'è un'interfaccia?
Un'interfaccia in Go è un insieme di firme di metodi. Qualsiasi tipo che implementa tutti questi metodi soddisfa implicitamente l'interfaccia: non è necessaria alcuna parola chiave implements. Questo meccanismo è chiamato tipizzazione strutturale o duck typing.
Dichiarare un'interfaccia
Definisca un'interfaccia con la parola chiave 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())
}Soddisfazione implicita
Non è necessaria alcuna dichiarazione di intenti. Se un tipo dispone dei metodi corretti, soddisfa automaticamente l'interfaccia:
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'interfaccia vuota
interface{} (o any in Go 1.18+) è soddisfatta da ogni tipo. Viene usata quando il tipo non è noto in fase di compilazione:
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})
}Valori di interfaccia
Un valore di interfaccia contiene due elementi: un tipo concreto e un valore concreto. Un'interfaccia nil ha entrambi impostati a 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())
}Soddisfare più interfacce
Un tipo può soddisfare contemporaneamente più interfacce:
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())
}Assegnazione tra interfacce
Un'interfaccia più ampia può contenere un valore concreto di tipo più specifico. Per assegnare un valore tra tipi di interfaccia, il tipo concreto deve soddisfare entrambe le interfacce:
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())
}Trappola dell'interfaccia nil
Un'interfaccia non nil che contiene un valore concreto nil NON è uguale a 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
}Le interfacce facilitano i test
Definire le dipendenze come interfacce consente di sostituire le implementazioni reali con mock nei test:
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]
}Accettare interfacce, restituire struct
Una best practice di Go: i parametri delle funzioni dovrebbero essere interfacce (per offrire flessibilità), mentre i tipi restituiti dovrebbero essere concreti (così i chiamanti sanno che cosa ricevono):
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()) }Mantenga le interfacce piccole
La libreria standard di Go privilegia interfacce ridotte: io.Reader ha un metodo, così come io.Writer. Le interfacce piccole sono più componibili e più facili da simulare nei test.
Verifica rapida
Un tipo deve dichiarare di implementare un'interfaccia?
Riepilogo: interfacce
Punti chiave:
- Le interfacce definiscono comportamenti, non dati
- La soddisfazione è implicita: non è necessaria la parola chiave
implements - L'interfaccia vuota (
any) accetta qualsiasi tipo - Presti attenzione alla trappola dell'interfaccia nil
- Mantenga le interfacce piccole e focalizzate
Esercizio
Definisca un'interfaccia Storage con Save(key, value string) error e Load(key string) (string, error). La implementi con una MemStorage basata su una map e la sottoponga a test.
Domande Frequenti
La lezione «Definire e implementare le interfacce» è gratuita?
Sì — il testo completo di «Definire e implementare le interfacce» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Go Academy, passa a CoddyKit PRO. Il corso Go Academy include 4 lezioni in totale.
Cosa imparerò in «Definire e implementare le interfacce»?
Soddisfacimento implicito e interfaccia vuota Eserciti Go Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Go Academy?
Non è richiesta alcuna esperienza precedente. Go Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «Definire e implementare le interfacce»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Go Academy?
Sì. Ogni lezione Go Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Definire e implementare le interfacce
- Interfacce fondamentali della libreria standard
- Asserzioni di tipo e switch sul tipo
- Composizione delle interfacce e buone pratiche