yoast variable snippet sitename sep recommendation page moz length descriptions description go

go - sitename - variable del snippet



Cómo verificar el tipo de variable en tiempo de ejecución en el idioma Go (5)

Tengo pocas funciones C declaradas así

CURLcode curl_wrapper_easy_setopt_long(CURL* curl, CURLoption option, long param); CURLcode curl_wrapper_easy_setopt_str(CURL* curl, CURLoption option, char* param);

Me gustaría exponer esos como una función Go como esta

func (e *Easy)SetOption(option Option, param interface{})

así que necesito poder verificar el tipo de param en tiempo de ejecución. ¿Cómo hago eso y esta es una buena idea (si no es lo que es una buena práctica en este caso)?


La respuesta de @Darius es el método más idiomático (y probablemente más eficiente). Una limitación es que el tipo que está comprobando debe ser del tipo interface{} . Si usa un tipo concreto, fallará.

Una forma alternativa de determinar el tipo de algo en tiempo de ejecución, incluidos los tipos concretos, es utilizar el paquete Go reflect . Encadenando TypeOf(x).Kind() juntos puede obtener un valor reflect.Kind que es un tipo uint : http://golang.org/pkg/reflect/#Kind

A continuación, puede hacer comprobaciones de los tipos fuera de un bloque de conmutadores, de esta manera:

import ( "fmt" "reflect" ) // .... x := 42 y := float32(43.3) z := "hello" xt := reflect.TypeOf(x).Kind() yt := reflect.TypeOf(y).Kind() zt := reflect.TypeOf(z).Kind() fmt.Printf("%T: %s/n", xt, xt) fmt.Printf("%T: %s/n", yt, yt) fmt.Printf("%T: %s/n", zt, zt) if xt == reflect.Int { println(">> x is int") } if yt == reflect.Float32 { println(">> y is float32") } if zt == reflect.String { println(">> z is string") }

Que imprime outs:

reflect.Kind: int reflect.Kind: float32 reflect.Kind: string >> x is int >> y is float32 >> z is string

De nuevo, esta no es probablemente la forma preferida de hacerlo, pero es bueno saber opciones alternativas.


La respuesta de quux00 solo dice acerca de la comparación de tipos básicos.

Si necesita comparar los tipos que definió, no debe usar reflect.TypeOf(xxx) . En su lugar, use reflect.TypeOf(xxx).Kind() .

Hay dos categorías de tipos:

  • tipos directos (los tipos que definió directamente)
  • tipos básicos (int, float64, struct, ...)

Aquí hay un ejemplo completo:

type MyFloat float64 type Vertex struct { X, Y float64 } type EmptyInterface interface {} type Abser interface { Abs() float64 } func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } func (f MyFloat) Abs() float64 { return math.Abs(float64(f)) } var ia, ib Abser ia = Vertex{1, 2} ib = MyFloat(1) fmt.Println(reflect.TypeOf(ia)) fmt.Println(reflect.TypeOf(ia).Kind()) fmt.Println(reflect.TypeOf(ib)) fmt.Println(reflect.TypeOf(ib).Kind()) if reflect.TypeOf(ia) != reflect.TypeOf(ib) { fmt.Println("Not equal typeOf") } if reflect.TypeOf(ia).Kind() != reflect.TypeOf(ib).Kind() { fmt.Println("Not equal kind") } ib = Vertex{3, 4} if reflect.TypeOf(ia) == reflect.TypeOf(ib) { fmt.Println("Equal typeOf") } if reflect.TypeOf(ia).Kind() == reflect.TypeOf(ib).Kind() { fmt.Println("Equal kind") }

La salida sería:

main.Vertex struct main.MyFloat float64 Not equal typeOf Not equal kind Equal typeOf Equal kind

Como puede ver, reflect.TypeOf(xxx) devuelve los tipos directos que puede desear utilizar, mientras que reflect.TypeOf(xxx).Kind() devuelve los tipos básicos.

Aquí está la conclusión. Si necesita comparar con tipos básicos, use reflect.TypeOf(xxx).Kind() ; y si necesita comparar con tipos autodefinidos, use reflect.TypeOf(xxx) .

if reflect.TypeOf(ia) == reflect.TypeOf(Vertex{}) { fmt.Println("self-defined") } else if reflect.TypeOf(ia).Kind() == reflect.Float64 { fmt.Println("basic types") }


Parece que Go tiene una forma especial de switch dedicada a esto (se llama type switch ):

func (e *Easy)SetOption(option Option, param interface{}) { switch v := param.(type) { default: fmt.Printf("unexpected type %T", v) case uint64: e.code = Code(C.curl_wrapper_easy_setopt_long(e.curl, C.CURLoption(option), C.long(v))) case string: e.code = Code(C.curl_wrapper_easy_setopt_str(e.curl, C.CURLoption(option), C.CString(v))) } }


Qué hay de malo en

func (e *Easy)SetStringOption(option Option, param string) func (e *Easy)SetLongOption(option Option, param long)

¿y así?


Vea las aserciones de tipo aquí:

http://golang.org/ref/spec#Type_assertions

Solo afirmaría un tipo razonable (cadena, uint64), etc. y lo mantendría lo más suelta posible, realizando una conversión al tipo nativo al final.