不能将数据(键入接口{})转换为string:需要types断言
我很新的去,我正在玩这个通知包。
起初,我有这样的代码:
func doit(w http.ResponseWriter, r *http.Request) { notify.Post("my_event", "Hello World!") fmt.Fprint(w, "+OK") }
我想追加换行到Hello World!
但不是在函数doit
上面,因为这将是相当微不足道的,但在handler
之后如下所示:
func handler(w http.ResponseWriter, r *http.Request) { myEventChan := make(chan interface{}) notify.Start("my_event", myEventChan) data := <-myEventChan fmt.Fprint(w, data + "\n") }
go run
:
$ go run lp.go # command-line-arguments ./lp.go:15: invalid operation: data + "\n" (mismatched types interface {} and string)
经过一些Googlesearch后,我发现这个问题 。
然后我更新我的代码:
func handler(w http.ResponseWriter, r *http.Request) { myEventChan := make(chan interface{}) notify.Start("my_event", myEventChan) data := <-myEventChan s:= data.(string) + "\n" fmt.Fprint(w, s) }
这是我应该做的吗? 我的编译器错误消失了,所以我猜这是相当不错的? 这是否有效? 你应该做不同的事情吗?
根据Go规范 :
对于接口types和typesT的expression式x,主expression式x。(T)声明x不是零,并且存储在x中的值是typesT.
“types断言”允许你声明一个包含某个具体types的接口值,或者它的具体types满足另一个接口。
在你的例子中,你是断言数据(types接口{})具有具体的typesstring。 如果你错了,程序会在运行时恐慌。 你不需要担心效率,检查只需要比较两个指针值。
如果你不确定它是否是一个string,你可以使用两个返回语法来testing。
str, ok := data.(string)
如果数据不是string,ok将是错误的。 那么把这样的陈述包含在if语句中是很常见的,如下所示:
if str, ok := data.(string); ok { /* act on str */ } else { /* not string */ }
键入断言
这被称为golang中的type assertion
,这是一种常见的做法。
这里是去旅行的解释:
types断言提供对接口值的基础具体值的访问。
t := i.(T)
这个语句声明了接口值 i保存了具体的types T,并将基础的T值赋给了variablest。
如果我不持有T,则会引发恐慌。
为了testing一个接口值是否拥有一个特定的types,一个types断言可以返回两个值:基础值和一个报告断言是否成功的布尔值。
t, ok := i.(T)
如果我拥有一个T,那么t就是底层的价值,OK就是真的。
如果不是的话,ok将是false,t将是T型的零值,不会发生恐慌。
注意: 值i
应该是接口types 。
陷阱
即使i
是一个接口types, []i
不是接口types。 因此,为了将[]i
转换为它的值types,我们必须单独做:
// var items []i for _, item := range items { value, ok := item.(T) dosomethingWith(value) }
性能
至于性能,它可能比直接访问实际值要慢,如在这个计算器的答案中所示 。
//an easy way: str := fmt.Sprint(data)