Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cast to a type alias in Go?

Tags:

types

casting

go

See this playground snippet.

Relevant code:

type somethingFuncy func(int) bool  func funcy(i int) bool {     return i%2 == 0 }  var a interface{} = funcy  func main() {      _ = a.(func(int) bool)  // Works      fmt.Println("Awesome -- apparently, literally specifying the func signature works.")      _ = a.(somethingFuncy)  // Panics      fmt.Println("Darn -- doesn't get here. But somethingFuncy is the same signature as func(int) bool.") } 

The first cast works, by explicitly declaring the type. But the second cast panics. Why? Is there a clean way to cast to a longer func signature?

like image 597
Matt Avatar asked Oct 24 '13 21:10

Matt


People also ask

What is type alias in Golang?

Type aliasing refers to the technique of providing an alternate name for an existing type. Type aliasing was introduced in Go version 1.9 and above. This helps to facilitate code refactor for large codebases.

How do I cast to string in Go?

You can convert numbers to strings by using the strconv. Itoa method from the strconv package in the Go standard libary. If you pass either a number or a variable into the parentheses of the method, that numeric value will be converted into a string value.

Can you cast in Golang?

As per Golang Specification, there is no typecasting word or terminology in Golang. If you will try to search Type Casting in Golang Specifications or Documentation, you will find nothing like this. There is only Type Conversion.

Does Go support type conversion?

Golang Implicit Type CastingGolang does not support implicit type conversion because of its robust type system. Some languages allow or even require compilers to provide coercion.


2 Answers

tl;dr

For type assertions (which you use) only the actual type matters. So somethingFuncy is only equal to somethingFuncy and not to func(int) bool.

Explanation

To start with, this has nothing to do with casting. There is no casting in go. There are type assertions and type conversions.

You're dealing with a type assertion and are assuming that the same conditions hold as for type conversions. I made the same mistake while reading your question but actually there is a huge difference in behaviour.

Suppose you have two types, say int and type MyInt int. These are convertible as they both share the same underlying type (one of the conversion rules), so this works (play):

var a int = 10 var b MyInt = MyInt(a) 

Now, suppose a is not of type int but of type interface{} (play):

var a interface{} = int(10) var b MyInt = MyInt(a) 

The compiler will tell you:

cannot convert a (type interface {}) to type MyInt: need type assertion

So now we're not doing conversions anymore but assertions. We need to do this (play):

var a interface{} = int(10) var b MyInt = a.(MyInt) 

Now we have the same problem as in your question. This assertion fails with this panic:

panic: interface conversion: interface is int, not main.MyInt

The reason for this is stated in the type assertions section of the spec:

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. The notation x.(T) is called a type assertion. More precisely, if T is not an interface type, x.(T) asserts that the dynamic type of x is identical to the type T.

So int must be identical to MyInt. The rules of type identity state that (amongst other rules):

Two named types are identical if their type names originate in the same TypeSpec.

As int and MyInt have different declarations (TypeSpecs) they're not equal and the assertion fails. When you assert a to int, the assertion works. So what you're doing is not possible.

Bonus:

The actual check happens in this code, which simply checks if both types are the same, as expected.

like image 173
nemo Avatar answered Sep 29 '22 17:09

nemo


Update 2017:

With type assertions in Go 1.9, you can simply add = where you define the type.

type somethingFuncy = func(int) bool 

This tells the compiler that somethingFuncy is an alternate name for func(int) bool.

like image 22
agarfield Avatar answered Sep 29 '22 16:09

agarfield