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

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

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

问题

两个相关的问题:

为什么Go规范不允许将[]T1转换为[]T2,即使T2具有T1的基础类型?

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

示例:

  1. package main
  2. import (
  3. "fmt"
  4. "unsafe"
  5. )
  6. type T1 struct {
  7. Val int
  8. }
  9. // T2具有T1的基础类型
  10. type T2 T1
  11. func main() {
  12. a := []T1{T1{12}}
  13. // 无法将a(类型为[]T1)转换为类型[]T2
  14. //b := ([]T2)(a)
  15. // 但是通过使用一些unsafe操作,我们可以实现转换。
  16. // 那么,为什么Go不允许这样做?可能会有什么意想不到的后果?
  17. b := *(*[]T2)(unsafe.Pointer(&a))
  18. b[0].Val = 42
  19. fmt.Println(a[0].Val) // 42
  20. }

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:

  1. package main
  2. import (
  3. "fmt"
  4. "unsafe"
  5. )
  6. type T1 struct {
  7. Val int
  8. }
  9. // T2 has the underlying type of T1
  10. type T2 T1
  11. func main() {
  12. a := []T1{T1{12}}
  13. // cannot convert a (type []T1) to type []T2
  14. //b := ([]T2)(a)
  15. // But with some unsafe we can do it.
  16. // So, why doesn't Go allow it? And what unforeseen consequence might it have?
  17. b := *(*[]T2)(unsafe.Pointer(&a))
  18. b[0].Val = 42
  19. fmt.Println(a[0].Val) // 42
  20. }

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。

例如,

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type T1 struct {
  6. Val int
  7. }
  8. type T2 T1
  9. type ST1 []T1
  10. type ST2 ST1
  11. func main() {
  12. a := ST1{T1{42}}
  13. fmt.Println(a) // 42
  14. // 将a(类型为ST1)转换为类型[]ST2
  15. b := ST2(a)
  16. fmt.Println(b) // 42
  17. }

输出:

  1. [{42}]
  2. [{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,

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type T1 struct {
  6. Val int
  7. }
  8. type T2 T1
  9. type ST1 []T1
  10. type ST2 ST1
  11. func main() {
  12. a := ST1{T1{42}}
  13. fmt.Println(a) // 42
  14. // convert a (type ST1) to type []ST2
  15. b := ST2(a)
  16. fmt.Println(b) // 42
  17. }

Output:

  1. [{42}]
  2. [{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:

确定