无法将数据(type interface {})转换为字符串类型:need type assertion(cannot convert data (type interface {}) to type string: need type assertion)

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

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

func doit(w http.ResponseWriter, r *http.Request) { notify.Post("my_event", "Hello World!") fmt.Fprint(w, "+OK") }

我想在Hello World!添加换行符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)

经过一点点谷歌搜索之后,我发现了这个问题 。

然后我更新了我的代码:

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

这是我应该做的吗 我的编译器错误已经消失了,所以我猜这是非常好的 这是否有效? 你应该做的不同吗?

I am pretty new to go and I was playing with this notify package.

At first I had code that looked like this:

func doit(w http.ResponseWriter, r *http.Request) { notify.Post("my_event", "Hello World!") fmt.Fprint(w, "+OK") }

I wanted to append newline to Hello World! but not in the function doit above, because that would be pretty trivial, but in the handler afterwards like this below:

func handler(w http.ResponseWriter, r *http.Request) { myEventChan := make(chan interface{}) notify.Start("my_event", myEventChan) data := <-myEventChan fmt.Fprint(w, data + "\n") }

After go run:

$ go run lp.go # command-line-arguments ./lp.go:15: invalid operation: data + "\n" (mismatched types interface {} and string)

After a little bit of Googling I found this question on SO.

Then I updated my code to:

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

Is this what I was supposed to do? My compiler errors are gone so I guess that's pretty good? Is this efficient? Should you do it differently?

最满意答案

根据Go规范 :

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

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

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

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

str, ok := data.(string)

如果数据不是字符串,则ok将为false。 因此,将这样的语句包装成如下所示的if语句是常见的:

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

According to the Go specification:

For an expression x of interface type and a type T, the primary expression x.(T) asserts that x is not nil and that the value stored in x is of type T.

A "type assertion" allows you to declare an interface value contains a certain concrete type or that its concrete type satisfies another interface.

In your example, you were asserting data (type interface{}) has the concrete type string. If you are wrong, the program will panic at runtime. You do not need to worry about efficiency, checking just requires comparing two pointer values.

If you were unsure if it was a string or not, you could test using the two return syntax.

str, ok := data.(string)

If data is not a string, ok will be false. It is then common to wrap such a statement into an if statement like so:

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