【问题标题】:cannot convert data (type interface {}) to type string: need type assertion无法将数据(类型接口 {})转换为类型字符串:需要类型断言
【发布时间】:2012-12-26 16:33:33
【问题描述】:

我还是个新手,我正在玩这个 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)
}

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

【问题讨论】:

    标签: go type-mismatch


    【解决方案1】:

    根据@ρяσѕρєя 的要求,可以在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)
    }
    

    【讨论】:

    • 我想你可以通过简单地编辑@Yuanbo's 来组合这两个答案——你们俩都会被记入并加起来各自的“有用性”分数?
    【解决方案2】:

    类型断言

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

    这里是a tour of go的解释:

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

    t := i.(T)
    

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

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

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

    t, ok := i.(T)
    

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

    如果不是,ok 为 false,t 为 T 类型的零值,不会发生 panic。

    注意:i 应该是接口类型

    陷阱

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

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

    性能

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

    【讨论】:

      【解决方案3】:
      //an easy way:
      str := fmt.Sprint(data)
      

      【讨论】:

      • 添加一些解释,说明此答案如何帮助 OP 解决当前问题
      • 只需将 interface{} 转换为字符串即可。谢谢。
      【解决方案4】:

      根据Go specification

      对于接口类型的表达式 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 */
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-03-15
        • 2016-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多