如何在Go中为不同类型实现容器?

Mai*_*tor 2 generics types interface go

以下代码在Go中实现了一个int列表:

package main

import "fmt"

type List struct {
    Head int
    Tail *List
}

func tail(list List) *List {
    return list.Tail
}

func main() {
    list := List{Head: 1, Tail: 
         &List{Head: 2, Tail:
         &List{Head: 3, Tail:
         nil}}}
    fmt.Println(tail(list).Head)
}
Run Code Online (Sandbox Code Playgroud)

问题是这只适用于int.如果我想要一个列表strings,我需要再次重新实现每个列表方法(例如tail)!这显然不实用,所以,这可以通过使用空接口来解决:

type List struct {
  Head interface{} // Now works for any type!
  Tail *List
}
Run Code Online (Sandbox Code Playgroud)

问题是,1.由于类型转换,这似乎要慢得多,2.它抛弃了类型安全,允许人们键入任何东西:

// This type-checks!
func main() {
    list := List{Head: 123456789 , Tail:
         &List{Head: "covfefe" , Tail:
         &List{Head: nil       , Tail:
         &List{Head: []int{1,2}, Tail:
         nil}}}}
    fmt.Println(tail(list).Head)
Run Code Online (Sandbox Code Playgroud)

显然,该方案应该键入检查的静态类型语言.

如何实现一个List类型,它不需要我为每个包含的类型重新实现所有List方法,但是它保持了预期的类型安全性和性能?

icz*_*cza 7

Go没有泛型类型,所以你坚持使用你列出的选项.抱歉.

同时,Go的内置映射和切片,以及使用空接口构造容器(具有显式拆箱)的能力意味着在许多情况下可以编写执行泛型将启用的代码,如果不太顺利的话.

如果您对要在容器中存储的元素有更多了解,可以使用更专业的接口类型(而不是空接口interface{}),

  • 可以帮助您避免使用类型断言(保持良好的性能)
  • 保持类型安全
  • 它可以用于(隐式)实现你的接口的所有类型(代码"可重用性",不需要复制多种类型).

但那是关于它的.在这里查看此示例:为什么Golang需要接口?

另外,如果你错过了它,标准库已经在container/list包中有一个双向链表实现(它也使用interface{}值的类型).