Different syntax type assertion

I’m sure this is a very newbie question and I’m a little hesitant to ask but here it goes…

You often see: x := y.(someType) as the usual form of a type assertion.

Recently, I saw: x := (someType)(nil) .

I can only assume this is a different syntax for a type assertion but I thought I would ask and perhaps this syntax has a special use. When I look at it it seems to be a way of getting a type when you don’t have variable on-hand to cast but perhaps there’s more to it?

I wonder if the code you saw even compiled. Try this:

package main

import "fmt"

type t struct{}

func main() {
	s, ok := (t)(nil)
	fmt.Println(s, ok)
}

Output

./prog.go:8:14: cannot convert nil to type t

https://play.golang.org/p/wr5VFw9AYcl

I should have used a playground like you did, t is not a struct but an interface so the code would look more like this:

https://play.golang.org/p/ZorbnX8CO1a

package main

import "fmt"

type t interface{}

func main() {
	s := (t)(nil)
	fmt.Println(s)
}

Output:

<nil>

How do I get the cool syntax highlighting here like you did?

One is a type assertion (extracting a value out of an interface box), the other is a conversion (converting a value to another type it’s assignable to).

1 Like

A distinction worth noting. Thanks.

1 Like

See also https://golang.org/ref/spec#Conversions vs https://golang.org/ref/spec#Type_assertions.

1 Like

There’s one thing left of which I am still unsure, if I change the print statement to fmt.Printf("%T", s) I thought it would show a type of t but it shows nil. I get the value is nil but I thought the type would now be t.

So here’s the thing, Go interfaces are sort of like boxes with a value and a type in them. (I’m using loose non-spec terminology here, because that is less confusing to me.) That value and type is always a “concrete” type - that is, a non-interface type like “int” or some struct. You can never put an interface into an interface - you can just take the concrete value out of one interface and put it into another. There are no layers of boxing, just an interface with a concrete value inside it.

What happens in your example is you create a box of type t and it’s empty (the concrete type and value are both nil). When you pass this to Printf, it wants an interface{} (that’s its parameter type). You can’t put an interface into an interface, so your t-typed box is opened and the type and value inside it are put into a new interface{}-typed box. Printf opens this and sees nil type and value, and prints that.

Adding to Jakob’s response: https://play.golang.org/p/ZKk72lze7VF

1 Like

Thanks Jakob, that was a very clear explanation.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.