无法将数据(类型接口 {})转换为类型字符串:需要类型断言

新手上路,请多包涵

我很新,我正在玩这个 通知 包。

起初我的代码看起来像这样:

 func doit(w http.ResponseWriter, r *http.Request) {
    notify.Post("my_event", "Hello World!")
    fmt.Fprint(w, "+OK")
}

我想将换行符附加到 Hello World! 但不是在上面的函数 doit 中,因为那将是非常微不足道的,但是在 handler :18-be85c 之后就像下面这样

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)

经过一些谷歌搜索后,我 在 SO 上发现了这个问题

然后我将代码更新为:

 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)
}

这是我应该做的吗?我的编译器错误消失了,所以我想这很好?这有效率吗?你应该做不同的事吗?

原文由 Alfred 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 651
2 个回答

根据 Go 规范

对于接口类型和类型 T 的表达式 x,主表达式 x.(T) 断言 x 不是 nil 并且存储在 x 中的值是类型 T。

“类型断言”允许您声明接口值包含特定具体类型或其具体类型满足另一个接口。

在您的示例中,您断言数据(类型接口{})具有具体类型字符串。如果你错了,程序会在运行时出现 panic。您无需担心效率,只需比较两个指针值即可进行检查。

如果您不确定它是否是一个字符串,您可以使用两个返回语法进行测试。

 str, ok := data.(string)

如果数据不是字符串,则 ok 将为 false。然后通常将这样的语句包装到 if 语句中,如下所示:

 if str, ok := data.(string); ok {
    /* act on str */
} else {
    /* not string */
}

原文由 Stephen Weinberg 发布,翻译遵循 CC BY-SA 3.0 许可协议

类型断言

这在 golang 中称为 type assertion ,这是一种常见的做法。

这是来自 go 之旅 的解释:

类型断言提供对接口值的底层具体值的访问。

 t := i.(T)

此语句断言 接口值 i 持有 具体类型 T 并将基础 T 值分配给变量 t。

如果 i 不持有 T,该语句将引发恐慌。

要测试接口值是否包含特定类型,类型断言可以返回两个值:基础值和报告断言是否成功的布尔值。

 t, ok := i.(T)

如果我持有 T,则 t 将是基础值,并且 ok 将为真。

如果不是,ok 将为假并且 t 将为类型 T 的零值,并且不会发生恐慌。

注意: i 应该是 interface type

陷阱

即使 i 是接口类型, []i 也不是接口类型。因此,为了将 []i 转换为其值类型,我们必须单独进行:

 // var items []i
for _, item := range items {
    value, ok := item.(T)
    dosomethingWith(value)
}

表现

至于性能,它可能比直接访问实际值慢,如 本 stackoverflow 答案 所示。

原文由 cizixs 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题