我有很少的C函数声明像这样
CURLcode curl_wrapper_easy_setopt_long(CURL* curl, CURLoption option, long param);
CURLcode curl_wrapper_easy_setopt_str(CURL* curl, CURLoption option, char* param);
我想将这些作为一个Go函数公开,如下所示
func (e *Easy)SetOption(option Option, param interface{})
所以我需要能够在运行时检查 param 类型。我该怎么做,这是个好主意(如果不是这种情况下的好习惯)?
答案 0 :(得分:71)
Go似乎有特殊形式的开关专用于此(它被称为类型开关):
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)))
}
}
答案 1 :(得分:47)
@Darius的答案是最惯用的(可能更高性能)方法。一个限制是您要检查的类型必须是interface{}
类型。如果使用具体类型,它将失败。
在运行时确定某些内容类型的另一种方法(包括具体类型)是使用Go reflect
包。将TypeOf(x).Kind()
链接在一起,您可以获得reflect.Kind
类型的uint
值:http://golang.org/pkg/reflect/#Kind
然后,您可以检查交换机块之外的类型,如下所示:
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")
}
打印输出:
reflect.Kind: int
reflect.Kind: float32
reflect.Kind: string
>> x is int
>> y is float32
>> z is string
同样,这可能不是首选的方法,但知道其他选项很好。
答案 2 :(得分:13)
请参阅此处的类型断言:
http://golang.org/ref/spec#Type_assertions
我只断言一个合理的类型(字符串,uint64)等,并保持尽可能宽松,最后执行到本机类型的转换。
答案 3 :(得分:3)
quux00的回答只讲述了比较基本类型。
如果您需要比较您定义的类型,则不应使用reflect.TypeOf(xxx)
。相反,请使用reflect.TypeOf(xxx).Kind()
。
有两种类型:
以下是一个完整的例子:
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")
}
输出结果为:
main.Vertex
struct
main.MyFloat
float64
Not equal typeOf
Not equal kind
Equal typeOf
Equal kind
如您所见,reflect.TypeOf(xxx)
会返回您可能想要使用的直接类型,而reflect.TypeOf(xxx).Kind()
会返回基本类型。
以下是结论。如果您需要与基本类型进行比较,请使用reflect.TypeOf(xxx).Kind()
;如果您需要与自定义类型进行比较,请使用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")
}
答案 4 :(得分:0)
有什么问题
func (e *Easy)SetStringOption(option Option, param string)
func (e *Easy)SetLongOption(option Option, param long)
等等?