Why can't I use an empty interface that holds a concrete type of string as a return value in a function declared to return string?

huangapple go评论89阅读模式
英文:

Why can't I use an empty interface that holds a concrete type of string as a return value in a function declared to return string?

问题

我是Go的新手,最近我正在按照《Go之旅》的指导进行学习。
我正在阅读关于“接口”的章节,对这个概念感到非常困惑。

以下是代码:

package main

import "fmt"

func main() {
    testTypeAssertion()
}

func testTypeAssertion() string {
    var i interface{} = "hello"
    fmt.Printf("i的类型是 %T", i)
    return i
    // return "hello"
}

在这种情况下,会导致错误:

# 示例
./prog.go:12:2: 无法将类型为 interface {} 的 i 用作返回参数中的 string 类型:需要类型断言

但是,如果我注释掉 return i 并取消注释 return "hello",结果如下:

i的类型是 string

那么为什么我们在这里需要类型断言呢?
i 的确切类型是什么?

我相信这个问题与 cannot use type interface {} as type person in assignment: need type assertion 不同。因为在那个问题中,发帖者试图将一个空接口值分配给一个具有具体自定义类型 person 的变量。在我的问题中,我试图弄清楚为什么一个持有具体 string 值的接口不能成为返回值类型恰好为 string 的函数的返回值。

感谢 mkopriva 在评论区的回答以及 bugstop 的回答。我将接受这是由于静态类型动态类型的不同用法引起的。顺便说一句,Reality 的回答非常有趣,真的帮助我理解了整个概念!

英文:

I am a newcomer of go and recently I am following the instruction of A Tour of Go.
I am reading the chapter on Interface and I am really confused by the concept.

The code is as follows

package main

import "fmt"

func main() {
	testTypeAssertion()
}

func testTypeAssertion() string {
	var i interface{}="hello"
	fmt.Printf("type of i is %T",i)
	return i
//	return "hello"
}

In this case, it will cause error

# example
./prog.go:12:2: cannot use i (type interface {}) as type string in return argument: need type assertion

But if I comment return i and uncomment return "hello", it goes like this

type of i is string

So why exactly do we need a type assertion here?
What's the type of i exactly?

I believe this question is different from cannot use type interface {} as type person in assignment: need type assertion. Because in that question the poster is trying to assign an empty interface value to a variable that has a concrete self-defined type person. In my question, I am trying to figure out why an interface holding a concrete string value cannot be a return value of a function whose return value type is exactly string.

Thanks to mkopriva's answer in the comment section and bugstop's answer. I will accept that it's caused by the different usage of static type and dynamic type. By the way, Reality's answer is very interesting and really helped me to understand the whole concept!

答案1

得分: 4

将接口想象成一个小盒子,它包含一个类型和一个值。这个盒子有一些方法,这些方法与盒子中的值的方法相对应。

语句fmt.Printf("type of i is %T",i)打印的是盒子中的类型,而不是盒子本身的类型。要打印i的类型,需要使用反射包的技巧,但这超出了本问题的范围。

语句return i无法编译通过,因为interface{}不是一个string类型。盒子中包含一个字符串,但盒子本身不是一个string类型。

我们可以使用类型断言将值从盒子中取出:return i.(string)。如果i不包含一个字符串,这个语句会引发恐慌。

英文:

Think of an interface as a little box that holds a type and a value. The box has methods that map to methods on the value in the box.

The statement fmt.Printf("type of i is %T",i) prints the type in the box, not the type of the box itself. Reflect package trickery is required to print the type of i. but that's outside the scope of this question.

The statement return i does not compile because interface{} is not a string. The box contains a string, but the box is not a string.

We can get the value out of the box using a type assertion: return i.(string). This statement panics if i does not contain a string.

答案2

得分: 3

这是一个具有动态类型为string的接口值i

阅读以下内容可能会有帮助:

英文:

it's an interface value i with a dynamic type string.

It may be useful to read about:

答案3

得分: 2

变量i的类型是interface{},其值为字符串"hello"。接口只是一个方法集,由于interface{}没有指定任何方法,所有类型都满足它。因此,赋值i="hello"是有效的。

然而,在需要string类型的地方,你不能返回一个interface{},因为stringinterface{}不是相同的类型。你可以在需要interface{}的地方返回一个string,因为字符串实现了interface{}

英文:

The variable i is of type interface{}, and its value is the string "hello". An interface is simply a method-set, and since interface{} has no methods specified, all types satisfy it. Because of this, the assignment i="hello" works.

However, you cannot return an interface{} where a string is required, because string is not the same type as an interface{}. You could have returned a string where an interface{} is required, because a string implements interface{}.

huangapple
  • 本文由 发表于 2022年2月15日 11:23:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/71120781.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定