2013-08-19 9 views

risposta

4

Se stai cercando una soluzione pratica, la risposta è semplice e fastidiosa. reflect.TypeOf utilizza un tipo di interfaccia vuoto in cui inserire i dati che si desidera trasmettere. Il problema è che un tipo di interfaccia non può contenere un altro tipo di interfaccia, il che significa che non è possibile passare un'interfaccia a reflect.TypeOf in modo efficace. C'è una soluzione, ma è un po 'doloroso. Quello che devi fare è creare un tipo composito (come una struct o una slice o una mappa) in cui uno dei tipi di elementi è un tipo di interfaccia ed estrailo. Ad esempio:

var sliceOfEmptyInterface []interface{} 
var emptyInterfaceType = reflect.TypeOf(sliceOfEmptyInterface).Elem() 

Questo primo crea una rappresentazione di reflect.Type[]interface{} (una fetta di interface{} tipi) e quindi estrae il tipo di elemento, che è interface{}.

Per gentile concessione di this post.

5

Buona domanda. Ci ho lavorato per quasi un'ora per scoprire me stesso! inizio

Let con questo codice:

package main 

import (
     "fmt" 
     "reflect" 
) 

// define an interface 
type Doer interface { 
     Do() 
} 

// define a type that implements the interface 
type T struct{} 

func (T) Do() {} 

func main() { 
     var v Doer = T{} 
     fmt.Println(reflect.TypeOf(v).Kind()) 
} 

L'uscita è struct, non interface. (You can run it here.)

Ecco perché, anche se definiamo v come interfaccia variabile, il valore effettivo questa variabile contiene è di tipo T. Si chiama "tipo dinamico" della variabile. Uno dei punti principali del pacchetto reflect è quello di aiutare a determinare il tipo dinamico di variabili di interfaccia, quindi fornisce il tipo dinamico, non l'interfaccia. (E anche se lo volesse, pacchetto reflect potrebbe non ottenere l'interfaccia di variabili passate al TypeOf e ValueOf, perché le variabili sono passati come valori alle funzioni.)

Così, si può vedere che la tua domanda “, che il valore di tipo è Interface? ", può tecnicamente rispondere con" no valore ".

Ma a cosa serve questo Interface? Vedere questo codice:

// assuming the above code, just with this main function 
func main() { 
     a := make([]Doer, 0) 
     fmt.Println(reflect.TypeOf(a).Elem().Kind()) 
} 

Questa stampa interface. (This one is here.) Il punto è nella funzione Elem, che restituisce il tipo di elementi di una mappa, un tipo di interfaccia qui. Elem funziona anche su puntatori, matrici, sezioni e canali. Ci sono funzioni simili per ottenere il tipo di chiave di una mappa (Key), i campi di una struct (Field e amici), gli argomenti di una funzione e il parametro di ritorno (In e Out). Puoi aspettarti di ottenere un'interfaccia di tipo gentile da tutti questi.

Rob Pike ha scritto un articolo fantastico, The Laws of Reflection, che spiega molto bene le interfacce e il riflesso.

+2

Lunedì 19 agosto 2013: oggi ho imparato qualcosa. – thwd

+0

Alcune cose: _ "Uno dei punti principali del pacchetto riflette è quello di aiutare a determinare il tipo dinamico di variabili di interfaccia" _ - Questo è parte del meccanismo attraverso il quale funziona il pacchetto reflect. Il punto del pacchetto di riflessioni sta abilitando la programmazione che considera (riflette su) la struttura del codice. _ "quale tipo di valore è Interface? può essere tecnicamente risposto senza valore." _ - La risposta è semplicemente "valori dell'interfaccia"._ "Il punto è nella funzione Elem, che restituisce il tipo di elementi di una mappa" _ - Quello che hai non è una mappa, e la produzione di fette di lunghezza zero non è necessaria nella maggior parte dei casi. –

+0

Grazie per i punti Gustavo. – Mostafa

2

Penso che la tua domanda sia equivalente a: Può un'interfaccia contenere un'altra interfaccia?

In The Laws of Reflection troviamo questo (non-interfaccia) Valore

Una variabile interfaccia può memorizzare qualsiasi cemento o in modo più dettagliato

una variabile di tipo negozi di interfaccia una coppia: il valore concreto assegnato alla variabile e il descrittore di tipo di quel valore. Per essere più precisi, il valore è il dato concreto sottostante che implementa l'interfaccia e il tipo descrive il tipo completo di tale elemento .

Quindi un'interfaccia non può contenere un'altra interfaccia. Ciò significa che non esiste un valore il cui reflect.Kind è reflect.Interface. Immagino che potresti essere in grado di crearne uno con non sicuro, ma non credo che ne vedrai mai uno normalmente.

+0

_ "Ciò significa che non esiste un valore il cui reflect.Kind è reflect.Interface" _ - I valori dell'interfaccia hanno un'interfaccia gentile, se è possibile memorizzarli in un altro valore di interfaccia o meno. Questi sono concetti ortogonali. –

+0

Ho letto la domanda originale in questo modo: puoi dichiarare una v (non usando reflect o non sicuro) tale che 'reflect.TypeOf (v) .Kind()' è 'reflect.Interface'. In tal caso, penso che la mia affermazione sia vera. Anche se mi piacerebbe vedere un controesempio ;-) –

6

Le risposte finora sembrano sorprendentemente complicate, quando la domanda e la sua risposta sono in realtà dirette: reflect.Interface è il tipo di valori dell'interfaccia.

Si può facilmente vedere che, con:

var v interface{} 
var t = reflect.ValueOf(&v).Type().Elem() 
fmt.Println(t.Kind() == reflect.Interface) 

Nota che ValueOf(v) non avrebbe funzionato perché si desidera che il tipo di v per sé, non il suo contenuto.

2

Dipende da cosa intendi per "valore" e "tipo di valore".

In Vai, "tipo" può significare cose diverse: - Il statica tipo (tipo in fase di compilazione) di un'espressione. Ogni espressione nella lingua ha un tipo statico noto al momento della compilazione. - Il dinamico tipo (tipo runtime) di un valore di interfaccia. Una variabile o espressione di tipo di interfaccia è speciale in quanto può contenere valori di tipi diversi e il tipo di questo valore sottostante non è noto in fase di compilazione. Questo valore di runtime e il suo tipo possono essere controllati in fase di esecuzione.

Il riflesso si verifica in fase di esecuzione, quindi è solo interessante chiedere il tipo dinamico di un valore di interfaccia. Quindi, devi parlare del tipo del valore sottostante di un valore dell'interfaccia.

Un valore non nil interfaccia è fondamentalmente un "involucro" attorno ad un sottostante e tipo. Si noti che questo tipo sottostante non può essere un tipo di interfaccia. Ad esempio, il wrapper non può "avvolgere" un altro wrapper. Questa è la risposta di joshlf13. Questo perché quando si assegna da un tipo di interfaccia a un altro tipo di interfaccia, viene trasferito solo il valore sottostante. Il tipo di interfaccia da cui proviene non è ricordato. Pertanto, è impossibile creare un valore di interfaccia il cui tipo sottostante sia un tipo di interfaccia.

Le funzioni di riflessione come reflect.ValueOf() e reflect.TypeOf() consentono di passare un valore di interfaccia e ottenere una rappresentazione del valore sottostante. Il tipo di parametro è interface{} perché è il tipo che consente di passare qualsiasi cosa. Tuttavia, presumono che tu sia effettivamente interessante nel valore di fondo di quel valore di interfaccia, che hai trasformato in interface{} passandolo in primo luogo, o lo hai preso da qualche altra parte e vuoi esaminarlo. Quindi, le funzioni di riflessione sono fondamentalmente per esaminare il valore sottostante delle interfacce (che, come spiegato sopra, deve essere di tipo non-interfaccia), e non l'argomento del tipo di interfaccia reale.

Pertanto, se la tua domanda è: cosa v può fare valutare a Interface; la risposta è nulla. Questo perché, se v non è nil, quindi ValueOf() ottiene una rappresentazione del suo valore sottostante, che deve essere di tipo non-interfaccia. E se v è nil, quindi con la documentazione di reflect.ValueOf(), restituisce il valore zero del tipo Value e la documentazione per il tipo Value.Kind() dice che chiamando Kind() sul valore zero restituisce Invalid.

-1

farò una risposta chiara per questo.

Prima di tutto bisogna ora interfacce somthing possono contenere nulla, tranne un'altra interfaccia. quindi chiariamolo. dare un'occhiata a questo programma.

type i interface { 
    hello() 
} 
type s struct{ 
name string 
} 
func (a s)hello(){} 
func main(){ 
    var f i //here we create an empty interface i 
    f=s{} //now f hold a structure of type s 
    fmt.Print(reflect.ValueOf(f).Kind()) // here we got a structure type so what really happen now i will explained 
    } 

la firma di ValueOf Methode è:

reflect.ValueOf(i interface{}) 

in modo che il ValueOf ottenere sempre un'interfaccia ampty quello che avevo detto si interfaccia mai trattenere un'altra interfaccia così. valueOf non prenderà l'interfaccia f ma prenderà un'interfaccia vuota che mantiene la struttura. è come se noi taked il valore sottostante di f ed essere associato ad un'interfaccia vuota e passato al ValueOf Methode

0

Non è possibile ottenere direttamente il tipo di un valore interface{}, ma si può passare attraverso un puntatore indiretto:

reflect.TypeOf(new(interface{})).Elem() 

Esegui il on play.golang.org:

t := reflect.TypeOf(new(interface{})).Elem() 
fmt.Printf("Type: %s\n", t) 
fmt.Printf("Kind: %v\n", t.Kind()) 
fmt.Printf("IsInterface: %v\n", t.Kind() == reflect.Interface) 

uscita:

Type: interface {} 
Kind: interface 
IsInterface: true 
Problemi correlati