我很新,我正在玩这个notify包。
起初我的代码看起来像这样:
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)
经过一段谷歌搜索后,我找到了this question on 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)
}
这是我应该做的吗?我的编译器错误消失了,所以我觉得这很好吗?这有效吗?你应该采用不同的方式吗?
答案 0 :(得分:265)
对于接口类型和类型T的表达式x,主表达式x。(T)声明x不是nil,并且存储在x中的值是T类型。
“类型断言”允许您声明接口值包含某个具体类型或其具体类型满足另一个接口。
在您的示例中,您声明的数据(类型interface {})具有具体的类型字符串。如果你错了,程序会在运行时发生恐慌。您无需担心效率,只需要比较两个指针值进行检查。
如果您不确定它是否是字符串,您可以使用两种返回语法进行测试。
str, ok := data.(string)
如果数据不是字符串,则ok将为false。然后通常将这样的语句包装到if语句中,如下所示:
if str, ok := data.(string); ok {
/* act on str */
} else {
/* not string */
}
答案 1 :(得分:15)
这在golang中称为type assertion
,这是一种常见做法。
以下是a tour of go的解释:
类型断言提供对接口值的基本具体值的访问。
t := i.(T)
该陈述断言接口值我持有具体类型 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)
}
就性能而言,它可能比直接访问this stackoverflow answer中显示的实际值慢。
答案 2 :(得分:7)
//an easy way:
str := fmt.Sprint(data)
答案 3 :(得分:6)
如@ρяσsρєя所要求的,可以在https://golang.org/pkg/fmt/#Sprint上找到说明。相关说明可以在https://stackoverflow.com/a/44027953/12817546和https://stackoverflow.com/a/42302709/12817546中找到。这是@Yuanbo的完整答案。
package main
import "fmt"
func main() {
var data interface{} = 2
str := fmt.Sprint(data)
fmt.Println(str)
}