Puoi fare riferimento all'articolo " Come usare le interfacce in Go " (basato sulla " descrizione delle interfacce di Russ Cox "):
Che cosa è un'interfaccia?
Un'interfaccia è due cose:
- è un insieme di metodi,
- ma è anche un tipo
Il interface{}tipo, l' interfaccia vuota è l'interfaccia che non ha metodi.
Poiché non esiste una parola chiave implementa, tutti i tipi implementano almeno zero metodi e la soddisfazione di un'interfaccia viene eseguita automaticamente, tutti i tipi soddisfano l'interfaccia vuota .
Ciò significa che se si scrive una funzione che accetta un interface{}valore come parametro, è possibile fornire tale funzione con qualsiasi valore .
(Questo è ciò che Msgrappresenta nella tua domanda: qualsiasi valore)
func DoSomething(v interface{}) {
// ...
}
Ecco dove diventa confuso:
all'interno della DoSomethingfunzione, qual è vil tipo?
I gopher principianti sono portati a credere che " vè di qualsiasi tipo", ma è sbagliato.
vnon è di alcun tipo; è di interface{}tipo .
Quando si passa un valore nella DoSomethingfunzione, il runtime Go eseguirà una conversione del tipo (se necessario) e convertirà il valore in un interface{}valore .
Tutti i valori hanno esattamente un tipo in fase di esecuzione e vun solo tipo statico è interface{}.
Un valore di interfaccia è costituito da due parole di dati :
- una parola viene utilizzata per indicare una tabella dei metodi per il tipo sottostante del valore,
- e l'altra parola viene utilizzata per indicare i dati effettivi mantenuti da quel valore.
Addendum: questo è dove l'articolo di Russ è abbastanza completo per quanto riguarda una struttura di interfaccia:
type Stringer interface {
String() string
}
I valori dell'interfaccia sono rappresentati come una coppia di due parole che fornisce un puntatore alle informazioni sul tipo memorizzato nell'interfaccia e un puntatore ai dati associati.
L'assegnazione di b a un valore di interfaccia di tipo Stringer imposta entrambe le parole del valore di interfaccia.

La prima parola nel valore dell'interfaccia punta a ciò che chiamo una tabella di interfaccia o itable (i-table pronunciata; nelle fonti di runtime, il nome dell'implementazione C è Itab).
L'Itable inizia con alcuni metadati sui tipi coinvolti e quindi diventa un elenco di puntatori a funzioni.
Si noti che l'Itable corrisponde al tipo di interfaccia, non al tipo dinamico .
In termini del nostro esempio, l'itable per Stringercontenere il tipo Binary elenca i metodi usati per soddisfare Stringer, che è solo String: gli altri metodi di Binary ( Get) non appaiono in itable.
La seconda parola nel valore dell'interfaccia indica i dati effettivi , in questo caso una copia di b.
L'assegnazione var s Stringer = bcrea una copia banziché il punto bper lo stesso motivo che ne var c uint64 = bfa una copia: se bsuccessivamente cambia, se csi suppone che abbia il valore originale, non quello nuovo.
I valori memorizzati nelle interfacce potrebbero essere arbitrariamente grandi, ma solo una parola è dedicata a contenere il valore nella struttura dell'interfaccia, quindi l'assegnazione alloca un pezzo di memoria sull'heap e registra il puntatore nello slot di una parola.
interface{}è più o meno l'equivalente divoid *in C. Può indicare qualsiasi cosa ed è necessaria un'asserzione cast / tipo per usarla.