不能将数据(类型接口{})转换为类型字符串:需要类型断言。

时间:2022-03-18 16:33:59

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:

我想给Hello World添加新行!但不是在上面的函数中,因为这是很简单的,但是在之后的处理程序中,如下所示:

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?

这是我应该做的吗?我的编译器错误已经消失了所以我想这很好?这是有效的吗?你应该换一种方式吗?

3 个解决方案

#1


230  

According to the Go specification:

根据Go规范:

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.

对于接口类型和类型T的表达式x,主表达式x.(T)断言x不是nil,并且存储在x中的值为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:

如果数据不是字符串,ok将是错误的。然后将这样的语句封装到if语句中是很常见的:

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

#2


8  

Type Assertion

This is known as type assertion in golang, and it is a common practice.

这在golang中被称为类型断言,这是一种常见的做法。

Here is the explanation from a tour of go:

下面是对围棋的解释:

A type assertion provides access to an interface value's underlying concrete value.

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

t := i.(T)

This statement asserts that the interface value i holds the concrete type T and assigns the underlying T value to the variable t.

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

If i does not hold a T, the statement will trigger a panic.

如果我不持有T,该声明将引发恐慌。

To test whether an interface value holds a specific type, a type assertion can return two values: the underlying value and a boolean value that reports whether the assertion succeeded.

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

t, ok := i.(T)

If i holds a T, then t will be the underlying value and ok will be true.

如果我持有一个T,那么T就是它的基础值,好的就成立了。

If not, ok will be false and t will be the zero value of type T, and no panic occurs.

如果没有,ok将是false, t是t类型的零值,没有出现恐慌。

NOTE: value i should be interface type.

注意:值应该是接口类型。

Pitfalls

Even if i is an interface type, []i is not interface type. As a result, in order to convert []i to its value type, we have to do it individually:

即使我是一个接口类型,[]我也不是接口类型。因此,为了将i转换为其值类型,我们必须分别进行:

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

Performance

As for performance, it can be slower than direct access to the actual value as show in this * answer.

至于性能,它可能比直接访问实际值的速度要慢,正如在这个*的答案中显示的那样。

#3


-4  

//an easy way:
str := fmt.Sprint(data)

#1


230  

According to the Go specification:

根据Go规范:

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.

对于接口类型和类型T的表达式x,主表达式x.(T)断言x不是nil,并且存储在x中的值为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:

如果数据不是字符串,ok将是错误的。然后将这样的语句封装到if语句中是很常见的:

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

#2


8  

Type Assertion

This is known as type assertion in golang, and it is a common practice.

这在golang中被称为类型断言,这是一种常见的做法。

Here is the explanation from a tour of go:

下面是对围棋的解释:

A type assertion provides access to an interface value's underlying concrete value.

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

t := i.(T)

This statement asserts that the interface value i holds the concrete type T and assigns the underlying T value to the variable t.

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

If i does not hold a T, the statement will trigger a panic.

如果我不持有T,该声明将引发恐慌。

To test whether an interface value holds a specific type, a type assertion can return two values: the underlying value and a boolean value that reports whether the assertion succeeded.

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

t, ok := i.(T)

If i holds a T, then t will be the underlying value and ok will be true.

如果我持有一个T,那么T就是它的基础值,好的就成立了。

If not, ok will be false and t will be the zero value of type T, and no panic occurs.

如果没有,ok将是false, t是t类型的零值,没有出现恐慌。

NOTE: value i should be interface type.

注意:值应该是接口类型。

Pitfalls

Even if i is an interface type, []i is not interface type. As a result, in order to convert []i to its value type, we have to do it individually:

即使我是一个接口类型,[]我也不是接口类型。因此,为了将i转换为其值类型,我们必须分别进行:

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

Performance

As for performance, it can be slower than direct access to the actual value as show in this * answer.

至于性能,它可能比直接访问实际值的速度要慢,正如在这个*的答案中显示的那样。

#3


-4  

//an easy way:
str := fmt.Sprint(data)