2015-06-08 14 views
15

Come è possibile convertire il tipo personalizzato in interface{} e quindi nel tipo di base (ad esempio uint8)?Tipo di tipi personalizzati di trasmissione per tipi di base

non posso usare getto diretto come uint16(val.(Year)) perché io non conosca tutti i tipi personalizzati, ma posso determinare i tipi di base (uint8, uint32, ...) in fase di esecuzione


Ci sono molti personalizzato tipi (di solito usato come enumerazioni) basate su numerica:

es:

type Year uint16 
type Day uint8 
type Month uint8 

e così via ...

La questione è sul tipo di fusione da interface{} a tipi di base:

package main 

import "fmt" 

type Year uint16 

// .... 
//Many others custom types based on uint8 

func AsUint16(val interface{}) uint16 { 
    return val.(uint16) //FAIL: cannot convert val (type interface {}) to type uint16: need type assertion 
} 

func AsUint16_2(val interface{}) uint16 { 
    return uint16(val) //FAIL: cannot convert val (type interface {}) to type uint16: need type assertion 
} 

func main() { 
    fmt.Println(AsUint16_2(Year(2015))) 
} 

http://play.golang.org/p/cyAnzQ90At

+3

Si prega di notare che né 'val (unit16)' 'né uint16 (val)' è un "cast":. Il primo è un "tipo asserzione" e la seconda e la "conversione di tipo". – Volker

risposta

12

è possibile eseguire questa utilizzando il pacchetto reflect:

package main 

import "fmt" 
import "reflect" 

type Year uint16 

func AsUint16(val interface{}) uint16 { 
    ref := reflect.ValueOf(val) 
    if ref.Kind() != reflect.Uint16 { 
     return 0 
    } 
    return uint16(ref.Uint()) 
} 

func main() { 
    fmt.Println(AsUint16(Year(2015))) 
} 

A seconda della situazione, si potrebbe voler restituire (uint16, error), invece di restituire il valore vuoto.

https://play.golang.org/p/sYm1jTCMIf

4

Perché si include Year nella questione? Speri di convertire oggetti arbitrari in Anni o convertire Anni in uint16s?

Se presumo si intende quest'ultimo caso, allora sarebbe meglio usare un metodo

func (y Year) AsUint16() uint16 { 
    return uint16(y) 
} 

, che non ha bisogno di affermazioni del tipo o di riflessione.

https://play.golang.org/p/9wCQJe46PU

+0

Ho molti (N) tipi personalizzati basati su tipi semplici (uint8, 16, 32 ...). E non voglio creare metodi N invece di quello –

+0

Questo è giusto, ma vale la pena di valutare i pro e i contro di ciascun approccio. L'approccio esplicito che ho descritto sopra è semplice, veloce e sicuro per il tipo, ma probabilmente troppo dettagliato. L'approccio riflessivo sarà più lento e meno esplicito in ciò che fa alle persone che vengono e leggono il tuo codice. –

+0

FWIW, mi sono occupato di una situazione simile utilizzando [Gen] (https://github.com/clipperhouse/gen) per creare codice di codice da modelli, ma nel tuo caso non è una scelta convincente. –

Problemi correlati