你如何在Go中实现不同类型的容器? [英] How do you implement a container for different types in Go?

查看:101
本文介绍了你如何在Go中实现不同类型的容器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 包主
$ b $导入 fmt

类型列表结构{
头元素
尾*列表
}

func尾(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)
}

问题是这只适用于 int 。如果我想要列表 strings 我需要重新实现每个列表方法(例如 tail $ b

  !显然不切实际,因此,可以通过使用空接口来解决:类型列表结构{
主界面{} //现在适用于任何类型!
尾巴*清单
}

问题是,1.这似乎是由于类型转换慢得多,2.它抛出类型安全性,允许一个类型检查任何东西:

  // // This TYPE-检查! 
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)

很显然,程序应该 类型检查静态类型的语言。 / p>

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

解决方案

Go没有泛型类型,所以你被困在你列出的选项中。抱歉。


与此同时,Go的内置地图和切片,以及使用空接口构建容器的能力(通过显式拆箱)意味着在很多情况下,编写代码可以实现泛型能够实现的功能,如果不那么流畅。


如果您更了解您可以使用更专门的接口类型(而不是空接口 interface {} ),其中


  • 可以帮助您避免使用类型断言保持良好效果

  • 且仍然保持类型安全

  • (隐式)实现您的界面的所有类型(代码可重用性,不需要为多种类型复制)。


但就是这样。在这里看到一个例子:为什么Golang需要接口?



另外,如果您错过了它,标准库在 container / list 包(它也使用 interface {} 键入值)。


The following code implements a List of ints in Go:

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

Problem is this only works for int. If I wanted a list of strings, I'd need to re-implement every list method (such as tail) again! That's obviously not practical, so, this can be solved by using an empty interface:

type List struct {
  Head interface{} // Now works for any type!
  Tail *List
}

Problem is, 1. this seems to be much slower because of type casts, 2. it throws aways type safety, allowing one to type-check anything:

// 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)

Obviously that program should not type-check in a statically typed language.

How can I implement a List type which doesn't require me to re-implement all List methods for each contained type, but which keeps the expected type safety and performance?

解决方案

Go doesn't have generic types, so you're stuck with the options you listed. Sorry.

Meanwhile, Go's built-in maps and slices, plus the ability to use the empty interface to construct containers (with explicit unboxing) mean in many cases it is possible to write code that does what generics would enable, if less smoothly.

If you know more about the elements you want to store in the container, you may use a more specialized interface type (instead of the empty interface interface{}), which

  • could help you avoid using type assertions (keep good performance)
  • and still keep type safety
  • and it can be used for all types that (implicitly) implement your interface (code "re-usability", no need to duplicate for multiple types).

But that's about it. See an example of this here: Why are interfaces needed in Golang?

Also just in case you missed it, the standard library already has a doubly linked list implementation in the container/list package (which also uses interface{} type for the values).

这篇关于你如何在Go中实现不同类型的容器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆