Reputation: 115
For basic types we can easily cast the types if their underlying types are same .But the fields inside struct with same memory layout cannot be easily cast from one to another type. There is a proposal for this problem unfortunately it got rejected .After an hour of googling with no luck I came here seeking the help from experts.
Look at example below :
package main
import (
"fmt"
)
type Int int
type A struct {
name string
age Int
}
type B struct {
name string
age int
}
func main() {
var a A= A{"Foo",21}
var b B= B{"Bar", 21}
fmt.Println(a,b,(A)(b)) //Error here as expected
}
Eventhough struct A and B has the same underlying type of struct { string,int}
why cannot I cast to each other as the underlying type of Int
is int
.
Whether it is possible to cast recursively unless the underlying type differs?
Upvotes: 0
Views: 2273
Reputation: 21
The reason why this conversion isn't allowed in your program:
type A B // this isn't a type alias
In this example A has the same binary structure as B. However A doesn't inherit any methods associated with B at all!
Let's assume this code:
func (b B) method()
The following would be valid
var b B
b.method()
This is INVALID
var a A
a.method() // for type A no method of name 'method' exists
The Spec assumes that A and B could be indeed very different. So no type conversion allowed.
You could use instead a type alias like that:
type Int = int
Here is a Playground link.
Upvotes: 1
Reputation: 417622
You can't do it simply because the language spec does not allow it. Regarding structs, you can only convert from one type to the other if Spec: Conversion:
A non-constant value
x
can be converted to typeT
in any of these cases:
- ...
- ignoring struct tags (see below),
x
's type andT
have identical underlying types.
If you're absolutely sure the structs' memory layout is identical, you may use an unsafe conversion (using package unsafe
) like this:
var a A = A{"Foo", 21}
var b B
b = *(*B)(unsafe.Pointer(&a))
fmt.Println(a, b)
This will output (try it on the Go Playground):
{Foo 21} {Foo 21}
But use this as the last resort. Using unsafe
you lose compile time type safety and portability guarantees. E.g. if later you only modify one of the structs, the above code will continue to compile even though it might not be correct anymore, and the compiler will not able to inform you about that.
Upvotes: 2