Go语言中的接口设计决策

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

Design decision in Go's interface{}

问题

为什么Go语言不会自动转换以下代码中的类型:

package main

import "fmt"

type Any interface{} // Any是一个空接口
type X func(x Any) // X是一个接收Any类型参数的函数

func Y(x X) { // Y是一个接收X类型参数的函数
  x(1)
}

func test(v interface{}) { // test与X类型不相等
  fmt.Println("called", v)
}

func main() {
  Y(test) // 错误:无法将test(类型为func(interface {}))作为参数转换为X类型传递给Y函数
}

还有这个代码:

package main
import "fmt"

type Any interface{}

func X2(a Any) {
  X(a)
} 
func Y2(a interface{}) {
  X2(a) // 这是可以的
}

func X(a ...Any) {
  fmt.Println(a)
}
func Y(a ...interface{}) { // 但这个不行
  X(a...) // 错误:无法将a(类型为[]interface {})作为参数转换为[]Any类型传递给X函数
}

func main() {
  v := []int{1,2,3}
  X(v)
  Y(v)
}

我曾经很希望interface{}可以在任何地方(切片、映射、函数)而不仅仅是简单类型上重命名为Any

第二个问题是:有没有办法使这成为可能?

英文:

Why Go doesn't automatically convert between:

package main

import "fmt"

type Any interface{} // Any is an empty interface
type X func(x Any) // X is a function that receives Any
    
func Y(x X) { // Y is a function that receives X
  x(1)
}

func test(v interface{}) { // test is not considered equal to X
  fmt.Println("called",v)
}

func main() {
  Y(test) // error: cannot use test (type func(interface {})) as type X in argument to Y
}

Also this one:

package main
import "fmt"

type Any interface{}

func X2(a Any) {
  X(a)
} 
func Y2(a interface{}) {
  X2(a) // this is OK
}

func X(a ...Any) {
  fmt.Println(a)
}
func Y(a ...interface{}) { // but this one not ok
  X(a...) // error: cannot use a (type []interface {}) as type []Any in argument to X
}
    
func main() {
  v := []int{1,2,3}
  X(v)
  Y(v)
}

I was really hopeful that interface{} could be renamed to Any on anything (slices, map, func) not just simple types

Second question would be: is there a way to make it possible?

答案1

得分: 5

第一个问题涉及到类型转换和类型标识,对此你有一套规则。

  • type Any interface{} 是一个命名类型
  • interface{} 是一个无名类型

它们的标识是不同的,你不能将 func(interface{}) 用于 func(Any) 的位置。

第二个问题在 golang faq 中有详细解答。

我可以将 []T 转换为 []interface{} 吗?

> 不能直接转换,因为它们在内存中的表示方式不同。
需要逐个元素地将它们复制到目标切片中。以下示例将一个 int 切片转换为一个 interface{} 切片:

t := []int{1, 2, 3, 4}
s := make([]interface{}, len(t))
for i, v := range t {
    s[i] = v
}

有关内存表示的更多信息,请参阅 "what is the meaning of interface{} in golang?":

Go语言中的接口设计决策

英文:

The first one is about type conversion and type identity, for which you have a set of rules.
See more at "Why can I type alias functions and use them without casting?"

  • type Any interface{} is a named type
  • interface{} is an unnamed type

Their identity is different, and you cannot use func(interface[}) in place of func(Any).


The second one is covered by the golang faq

Can I convert a []T to an []interface{}?

> Not directly, because they do not have the same representation in memory.
It is necessary to copy the elements individually to the destination slice. This example converts a slice of int to a slice of interface{}:

t := []int{1, 2, 3, 4}
s := make([]interface{}, len(t))
for i, v := range t {
    s[i] = v
}

See "what is the meaning of interface{} in golang?" for more on the memory representation:

Go语言中的接口设计决策

huangapple
  • 本文由 发表于 2014年12月5日 14:38:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/27310220.html
匿名

发表评论

匿名网友

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

确定