-2

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!

Zeke
  • 23
  • 4
  • maybe you should explictly cast at return for your purpose though I dont think that is the essence of interface - `return i.(string`) ref - https://www.geeksforgeeks.org/interfaces-in-golang/#:~:text=In%20Go%20language%2C%20the%20interface,an%20instance%20of%20the%20interface.&text=Or%20in%20other%20words%2C%20the,it%20is%20a%20custom%20type. – Nidhin David Feb 15 '22 at 03:38
  • 4
    The *static* type of `i` is `interface{}`, the *dynamic* type is `string`. The `Printf("%T...` will *always* print the dynamic type of the passed in argument. Why? Because the `Printf` parameter's *static* type is `interface{}`, so if it was implemented to print the static type then it would print `interface{}` for anything and everything. That would not be very helpful. If you want to know the *static* type of `i` you can pass a pointer to `i` to `Printf` which will then print `*static_type` as the type of the given argument. https://go.dev/play/p/caKewzFgAUQ – mkopriva Feb 15 '22 at 04:56
  • Does this answer your question? [cannot use type interface {} as type person in assignment: need type assertion](https://stackoverflow.com/questions/27437053/cannot-use-type-interface-as-type-person-in-assignment-need-type-assertion) – blackgreen Feb 15 '22 at 06:22

3 Answers3

4

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.

3

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

It may be useful to read about:

Muhan Li
  • 46
  • 4
2

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{}.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59