英文:
Converting from []T1 to []T2 when T2 has the underlying type of T1
问题
两个相关的问题:
为什么Go规范不允许将[]T1
转换为[]T2
,即使T2
具有T1
的基础类型?
使用unsafe
包进行转换会有什么负面影响?
示例:
package main
import (
"fmt"
"unsafe"
)
type T1 struct {
Val int
}
// T2具有T1的基础类型
type T2 T1
func main() {
a := []T1{T1{12}}
// 无法将a(类型为[]T1)转换为类型[]T2
//b := ([]T2)(a)
// 但是通过使用一些unsafe操作,我们可以实现转换。
// 那么,为什么Go不允许这样做?可能会有什么意想不到的后果?
b := *(*[]T2)(unsafe.Pointer(&a))
b[0].Val = 42
fmt.Println(a[0].Val) // 42
}
Playground: http://play.golang.org/p/x2tBRKuRF1
用法示例:
如果T1实现了某个接口,比如json.Marshaler
,并且你想以不同的方式对该类型进行JSON编码,你可以创建一个新的type T2 T1
,并为其实现自己的json.Marshaler
。
当对单个值进行编组时,这样做是可以的,但是当你得到一个[]T1切片时,你要么需要将其复制到一个[]T2切片中,要么创建一个新的type ST1 []T1
并为其实现MarshalJSON()
方法。能够进行简单的转换而不是使用unsafe
会更好,因为使用unsafe
可能会导致运行时错误而不是编译时错误。
英文:
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.
答案1
得分: 1
《Go编程语言规范》
转换
如果非常量值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
// 将a(类型为ST1)转换为类型[]ST2
b := ST2(a)
fmt.Println(b) // 42
}
输出:
[{42}]
[{42}]
英文:
> 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}]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论