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


175

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

最初,我有如下代码:

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)

经过一番谷歌搜索后,我在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)
}

这是我应该做的吗?我的编译器错误消失了,所以我想那很好吗?这样有效吗?您应该以其他方式做吗?

Answers:


290

根据Go规范

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

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

在您的示例中,您断言数据(类型interface {})具有具体的类型字符串。如果输入错误,则程序将在运行时崩溃。您无需担心效率,只需要比较两个指针值即可。

如果不确定是否为字符串,则可以使用两种返回语法进行测试。

str, ok := data.(string)

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

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

29

类型断言

type assertion在golang中是众所周知的,是一种常见的做法。

这是围棋之旅的解释:

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

t := i.(T)

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

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

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

t, ok := i.(T)

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

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

注意:i应为接口类型

陷阱

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

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

性能

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



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.