Tracce
/
Go
Go
/
Programma
/
Interfacce
In

Interfacce in Go

2 esercizi

Informazioni su Interfacce

Un'interfaccia come insieme di metodi

Nella sua forma più semplice, un tipo interfaccia è un insieme di firme di metodi. Ecco un esempio di definizione di interfaccia che include due metodi Add e Value:

type Counter interface {
    Add(increment int)
    Value() int
}

I nomi dei parametri come increment possono essere omessi dalla definizione dell'interfaccia, ma spesso ne aumentano la leggibilità.

In Go, i nomi delle interfacce non contengono la parola Interface o I. Spesso terminano invece con er, ad esempio Reader, Stringer.

Implementare un'interfaccia

Qualsiasi tipo che definisce i metodi di un'interfaccia la «implementa» automaticamente, in modo implicito. In Go non esiste una parola chiave implements.

Il tipo seguente implementa l'interfaccia Counter che abbiamo visto sopra.

type Stats struct {
    value int
    // ...
}

func (s Stats) Add(v int) {
    s.value += v
}

func (s Stats) Value() int {
    return s.value
}

func (s Stats) SomeOtherMethod() {
    // The type can have additional methods not mentioned in the interface.
}

Per implementare l'interfaccia non importa se il metodo ha un receiver di valore o di puntatore. (Rivedi i concetti sui metodi se hai dei dubbi.)

Un valore di tipo interfaccia può contenere qualsiasi valore che implementi quei metodi. 1

Questo significa che ora Stats può essere usato in tutti i punti in cui ci si aspetta l'interfaccia Counter.

func SetUpAnalytics(counter Counter) {
    // ...
}

stats := Stats{}
SetUpAnalytics(stats)
// works because Stats implements Counter

Se tutti i parametri e i valori restituiti di una funzione dovessero usare tipi concreti (cioè non interfaccia), la loro riutilizzabilità sarebbe fortemente limitata. Usando tipi interfaccia per i parametri, si definisce solo il comportamento necessario alla funzione per fare il suo lavoro. Ora la funzione può essere usata con parametri di tipi concreti diversi, purché quei tipi concreti implementino l'interfaccia. La stessa logica vale quando si usano tipi interfaccia come valori restituiti.

Poiché le interfacce sono implementate in modo implicito, un tipo può facilmente implementare più interfacce. Deve solo avere definiti tutti i metodi necessari.

Combinare le interfacce

Le definizioni di interfaccia possono includere altre interfacce. Ecco un esempio dalla libreria standard.

type ReadCloser interface {
	Reader
	Closer
}

// Based on these interfaces:

type Reader interface {
	Read(p []byte) (n int, err error)
}

type Closer interface {
	Close() error
}

Invece di ripetere le firme dei metodi Read e Close per definire ReadCloser, la definizione dell'interfaccia sfrutta le definizioni esistenti di Reader e Closer.

Interfaccia vuota

In Go esiste un tipo interfaccia molto speciale, il tipo interfaccia vuota, che non contiene alcun metodo. L'interfaccia vuota si scrive così: interface{}. Da Go 1.18 in poi si può usare anche any. È stata definita come alias.

Dato che l'interfaccia vuota non ha metodi, ogni tipo la implementa implicitamente. Questo è utile per definire una funzione che possa accettare qualsiasi valore in modo generico. In quel caso, il parametro della funzione usa il tipo interfaccia vuota.

Per esempio:

func AnythingGoes(i interface{}) string {
    if i == 0 {
        return "zero"
    }
    if i == "" {
        return "empty string"
    }
    return "something else"
}
  1. Tour of Go: Interfaces ↩

Modifica tramite GitHub Il collegamento si apre in una nuova finestra o scheda

Impara Interfacce

La pratica è bloccata

Sblocca un altro esercizio per esercitarti su Interfacce