【问题标题】:Converting from []T1 to []T2 when T2 has the underlying type of T1当 T2 具有 T1 的基础类型时,从 []T1 转换为 []T2
【发布时间】:2014-04-29 01:01:34
【问题描述】:

两个密切相关的问题:

如果T2 具有T1 的基础类型,为什么Go Specification 不允许您将[]T1 转换为[]T2

使用unsafe 包进行转换有什么负面影响?

示例:

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
}

游乐场: http://play.golang.org/p/x2tBRKuRF1

使用示例:

如果 T1 实现了某个接口,例如 json.Marshaler,并且您想以不同的方式对类型进行 JSON 编码,您可以创建一个新的 type T2 T1,并使用它自己的 json.Marshaler 实现。

它在封送单个值时可以正常工作,但是当您获得 []T1 切片时,您必须将其复制到 []T2 切片或使用自己的 MarshalJSON() 方法创建一个新的 type ST1 []T1。做一个简单的转换而不是转向unsafe 会很好,因为它可能会导致运行时错误而不是编译时间。

【问题讨论】:

    标签: go type-conversion


    【解决方案1】:

    The Go Programming Language Specification

    Conversions

    如果 x 的类型和 T,则非常量值 x 可以转换为类型 T 具有相同的基础类型。

    例如,

    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
    }
    

    输出:

    [{42}]
    [{42}]
    

    【讨论】:

    • 抱歉不清楚。我更想知道为什么规范不允许这样做。如果内存表示是相同的(它们显然具有相同的底层类型),为什么他们会决定阻止这种转换?我更新了我的问题。
    • @Greg Go 规范允许您从 T1 转换为 T2(如果它们具有相同的基础类型)。但不是从 []T1 到 []T2;那么您将遇到编译器错误。
    • @ANisus gotcha,我误解了 :)
    猜你喜欢
    • 2019-12-07
    • 1970-01-01
    • 2015-11-11
    • 2018-11-02
    • 2015-11-06
    • 1970-01-01
    • 2011-09-22
    • 2018-10-25
    • 1970-01-01
    相关资源
    最近更新 更多