ANisus
ANisus

Reputation: 78065

Converting from []T1 to []T2 when T2 has the underlying type of T1

Two closely related question:

Why doesn't Go Specification allow you to convert []T1 to []T2 if T2 has the underlying type of T1?

What are the negative consequences of doing the conversion using the unsafe package?

Example:

package main

import (
    "fmt"
    "unsafe"
)

type T1 struct {
    Val int
}

// T2 has the underlying type of T1
type T2 T1

func main() {
    a := []T1{T1{12}}

    // cannot convert a (type []T1) to type []T2
    //b := ([]T2)(a)

    // But with some unsafe we can do it.
    // So, why doesn't Go allow it? And what unforeseen consequence might it have?
    b := *(*[]T2)(unsafe.Pointer(&a))
    b[0].Val = 42

    fmt.Println(a[0].Val) // 42
}

Playground: http://play.golang.org/p/x2tBRKuRF1

Example of usage:

If T1 implements a certain interface, say json.Marshaler, and you want to JSON encode the type in a different way, you create a new type T2 T1 with its own implementation of json.Marshaler.

It works fine when marshaling single values, but when you get a []T1 slice you would have to either copy it to a []T2 slice or create a new type ST1 []T1 with its own MarshalJSON() method. It would be nice to do a simple conversion instead instead of having to turn to unsafe as it might result in runtime errors instead of compile time.

Upvotes: 1

Views: 145

Answers (1)

peterSO
peterSO

Reputation: 166845

The Go Programming Language Specification

Conversions

A non-constant value x can be converted to type T if x's type and T have identical underlying types.

For example,

package main

import (
    "fmt"
)

type T1 struct {
    Val int
}

type T2 T1

type ST1 []T1

type ST2 ST1

func main() {
    a := ST1{T1{42}}
    fmt.Println(a) // 42
    // convert a (type ST1) to type []ST2
    b := ST2(a)
    fmt.Println(b) // 42
}

Output:

[{42}]
[{42}]

Upvotes: 1

Related Questions