将 []T1 转换为 []T2,其中 T2 的底层类型为 T1。

huangapple go评论91阅读模式
英文:

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}]

huangapple
  • 本文由 发表于 2014年4月29日 09:01:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/23353757.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定