212

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

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

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

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

4

4 回答 4

330

根据Go 规范

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

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

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

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

str, ok := data.(string)

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

if str, ok := data.(string); ok {
    /* act on str */
} else {
    /* not string */
}
于 2013-01-12T02:25:44.003 回答
35

类型断言

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

这是go 之旅的解释:

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

t := i.(T)

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

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

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

t, ok := i.(T)

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

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

注意:i应该是接口类型

陷阱

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

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

表现

至于性能,它可能比直接访问实际值要慢,如this stackoverflow answer所示。

于 2016-12-03T10:58:00.173 回答
25
//an easy way:
str := fmt.Sprint(data)
于 2016-06-24T08:28:15.527 回答
6

正如@ρяσѕρєя 所要求的,可以在https://golang.org/pkg/fmt/#Sprint找到解释。相关解释可以在https://stackoverflow.com/a/44027953/12817546https://stackoverflow.com/a/42302709/12817546找到。这是@Yuanbo的完整答案。

package main

import "fmt"

func main() {
    var data interface{} = 2
    str := fmt.Sprint(data)
    fmt.Println(str)
}
于 2020-05-21T08:52:47.643 回答