当前位置: 首页 > 面试题库 >

您如何在Go中实现用于不同类型的容器?

孙正业
2023-03-14
问题内容

以下代码在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)
}

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

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

问题是: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)

显然,该计划应该 不会 在静态类型语言类型检查。

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


问题答案:

Go没有通用类型,因此您只能使用列出的选项。抱歉。

同时,Go的内置映射和切片,以及使用空接口构造容器的能力(带有显式拆箱),意味着在许多情况下,即使不那么顺利,也可以编写能够实现泛型的代码。

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

  • 可以帮助您避免使用类型断言( 保持良好的性能
  • 仍然 保持类型安全
  • 并且它可用于(隐式)实现您的接口的所有类型( 代码“可重用性” ,无需为多种类型重复)。

同样,以防万一您错过它,标准库在container/list包中已经有一个双链表实现(它也使用interface{}类型作为值)。



 类似资料:
  • 问题内容: 如何在Go中实现抽象类?由于Go不允许我们在接口中包含字段,因此这将是一个无状态的对象。因此,换句话说,Go中的方法是否可以具有某种默认实现? 考虑一个例子: 由于无法将接口用作接收器,因此无法编译。 实际上,我已经回答了我的问题(请参见下面的答案)。但是,这是实现这种逻辑的惯用方式吗?除了语言的简单性之外,还有什么理由不使用默认实现吗? 问题答案: 一个简单的解决方案是移至参数列表(

  • 问题内容: 我有一个简单的类型,可以在Go中实现子类型整数const到字符串的转换,反之亦然。我希望能够自动将JSON中的字符串解组为这种类型的值。我不能,因为UnmarshalJSON没有给我一种返回或修改标量值的方法。期望有一个结构,其成员由UnmarshalJSON设置。除内置标量类型外,“,string”方法不适用于其他类型。有没有一种方法可以为派生的标量类型正确实现UnmarshalJS

  • 问题内容: 说我有两个结构: 我希望他们都实现接口A: 像这样对First和Second结构都实现似乎是多余的: 有没有一种方法可以为实现接口A的所有结构提供一个实现?像这样的东西,但似乎不起作用: 谢谢! 问题答案: 不,您不能, 但是 您可以创建一个基本类型,然后将其嵌入到您的2结构中,因此只需要一个基本类型的实现即可: 用法: 操场上的完整例子 嵌入文件

  • 我想为实现,以提供对函数中的字段的访问,该字段对于数据提供程序来说应该是不可知的。字段的类型由trait关联的类型确定。请注意,特性确保这里的这些特性都不能被其他板条箱实现;这是我严格提供的功能。此外,类型受到空trait的限制,以防止用作该类型。 以下示例最能说明问题: 不幸的是,编译器抱怨道: 有没有办法实现我的目标?

  • 问题内容: 我在编写的程序中遇到接口问题。我想创建一个接口,该接口的方法之一可以接收/返回对自己对象类型的引用。就像这样: 我不能在“?”处使用“ I”,因为我不想返回对接口的引用,而是要返回对类的引用。我搜索后发现在Java中没有“自我引用”的方法,因此我不能仅用“?”代替。在示例中,“ self”关键字或类似的内容。实际上,我想出了一个解决方案 但这似乎确实是一种解决方法或类似方法。还有另一种

  • 问题内容: 我已经看到了一些类似的问题两种不同的类型如何使用接口在golang中实现相同的方法?,但就我而言,我的类型没有相同的基本类型。我的类型是不同大小的数组。 因此,可能不重复两种方法GetByte0()? 问题答案: 例如, 输出: