我是很新的去,我玩这个通知包。
一开始我的代码是这样的:
func doit(w http.ResponseWriter, r *http.Request) {
notify.Post("my_event", "Hello World!")
fmt.Fprint(w, "+OK")
}
我想追加换行到Hello World!但不是在上面的doit函数中,因为那将是非常琐碎的,而是在之后的处理程序中,如下所示:
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)
}
这是我该做的吗?我的编译器错误消失了,所以我猜这很好?这样有效率吗?你是否应该另辟蹊径?
根据Go规范:
对于接口类型和类型T的表达式x,主表达式x.(T)断言x不是nil,并且存储在x中的值是类型T的。
“类型断言”允许您声明一个接口值包含某种具体类型,或者它的具体类型满足另一个接口。
在您的示例中,您断言data (type interface{})具有具体类型字符串。如果你错了,程序将在运行时恐慌。你不需要担心效率,检查只需要比较两个指针值。
如果您不确定它是否是一个字符串,您可以使用两个返回语法进行测试。
str, ok := data.(string)
如果data不是字符串,ok将为false。然后通常将这样的语句包装成if语句,如下所示:
if str, ok := data.(string); ok {
/* act on str */
} else {
/* not string */
}
除了其他答案,我觉得还可以看看“type switch”:
package main
import "fmt"
func printType(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("type of %v is %v\n", i, v)
// type of 21 is int
case string:
fmt.Printf("type of %v is %v\n", i, v)
// type of hello is string
default:
fmt.Printf("type of %v is %v\n", i, v)
// type of true is bool
}
}
func main() {
printType(21)
printType("hello")
printType(true)
}
我希望这能有所帮助。
更多信息:https://go.dev/tour/methods/16
根据Go规范:
对于接口类型和类型T的表达式x,主表达式x.(T)断言x不是nil,并且存储在x中的值是类型T的。
“类型断言”允许您声明一个接口值包含某种具体类型,或者它的具体类型满足另一个接口。
在您的示例中,您断言data (type interface{})具有具体类型字符串。如果你错了,程序将在运行时恐慌。你不需要担心效率,检查只需要比较两个指针值。
如果您不确定它是否是一个字符串,您可以使用两个返回语法进行测试。
str, ok := data.(string)
如果data不是字符串,ok将为false。然后通常将这样的语句包装成if语句,如下所示:
if str, ok := data.(string); ok {
/* act on str */
} else {
/* not string */
}
类型的断言
这在golang中称为类型断言,是一种常见的实践。
下面是一次围棋之旅的解释:
类型断言提供了对接口值的底层具体值的访问。
t := i.(T)
该语句断言接口值i保存具体类型T,并将底层T值赋给变量T。
如果i不持有T,该声明将引发恐慌。
要测试接口值是否包含特定类型,类型断言可以返回两个值:底层值和报告断言是否成功的布尔值。
t, ok := i.(T)
如果i包含T,那么T就是基础值ok就为真。
如果不是,ok将为假,t将是类型t的零值,并且不会发生恐慌。
备注:i取值为接口类型。
陷阱
即使i是接口类型,[]i也不是接口类型。因此,为了将[]i转换为它的值类型,我们必须单独执行:
// var items []i
for _, item := range items {
value, ok := item.(T)
dosomethingWith(value)
}
性能
至于性能,它可能比直接访问实际值慢,如stackoverflow回答所示。