当前位置: 首页 > 知识库问答 >
问题:

用于切片的泛型remove()函数

归建安
2023-03-14

我有3片(fos,酒吧,巴兹),每个都填充了不同类型的结构。为了删除一些样板代码,我想创建一个通用的删除(切片,结构)切片函数。类似于标准中提供的append()的反义词。

没有一个结构是指针,因此没有必要将其置零。我曾经想过使用接口{}来获得想要的结果,但没有效果。当前实现使用一个类型开关,然后有一个近复制粘贴的remove()(下面链接中的示例)从切片中删除。随着我继续扩展这个项目,它将成为更多的样板。

正在尝试的示例:https://play.golang.org/p/9UPRIIp5M2

Function input: []slices, struct
Expected output: 
    Modified (removed struct) []slices if struct is found
    Or, Unmodified []slices if it isn't.

如果它简单且易于实现。我想象它已经存在于标准中了。然而,从经验丰富的专业人士那里得到建议,告诉他们我正在尝试做的事情是否有可能,这并没有什么坏处。

谢谢你的时间。

共有2个答案

赵英哲
2023-03-14

我看了你的示例代码及其错误。要了解更多关于接口切片的信息,请参考Go wiki和SliceTricks。

泛型实现有点复杂,您可以使用基于类型的实现。然而,基于类型的实现带来了更多样板/重复的代码。

您需要按照评论中提到的@stephen weinberg使用reflect软件包。

所以最好的出发点是;试试这个github库。com/anzhihun/generic并遍历库代码库,自行实现。这个库使用反射。

林魁
2023-03-14

试图使围棋通用化是新围棋开发者的一大陷阱。停止您正在保存五行代码:

for i := len(foos) - 1; i >= 0; i-- {
    if foos[i] == foo1 {
        foos = append(foos[:i], foos[i+1:]...)
    }
}

是的,在通用语言中,您可以将这五行代码打包成一个漂亮的stdlib方法,但Go不是通用语言。尝试用反射来实现这一点很慢,但这并不是避免它的原因。反射非常复杂。很难把它弄对。你将花费更多的时间来计算和追踪奇怪的角落案例,而不是12次重写这五行代码(包括修复意外剪切/粘贴错误的时间,以及一次搞乱i--)。写下来就行了。

编写代码可以让您决定平等的含义。它让你决定是在第一次匹配时停止搜索,还是继续浏览整个列表。它让你做这个程序需要的事情,而不是关注某个通用程序有一天可能需要的东西。

我喜欢泛型编程。没有什么比在哈斯克尔创造一个优雅的折叠更让我高兴的了。但这不是办法。在Go中,您通常只需编写代码,保持简单明了,然后继续前进。

Andy提出了一个很好的观点,如果您必须经常这样做,list可能是一个更好的数据结构。我经常发现,当我有三种似乎都有并行方法的类型时,它们都应该是单个结构的一部分(这里真的需要单独的列表吗?)但在任何情况下,都要远离反思,除非你有一个非常特殊的问题,你真正的意思是“任何事情”,而不是“这些事情中的一个”

(值得注意的是,您调用append()。我认为在Go中写append()是不可能的。这就是为什么它必须是语言的一部分,而不是stdlib函数。当我开始学习围棋时,我认为这是语言中的一个重大缺陷。我在围棋上工作的时间越长,就越发现它不那么重要。你只需编写代码,然后继续前进。)

 类似资料:
  • 同样的规则也可以适用于函数:在使用前给出 <T> 后,类型 T 就变成了泛型。 使用泛型函数有时需要显式地指明类型参量。这种可能的情况包括,调用返回类型是泛型的函数,或者编译器没有足够的信息来推导类型参量。 函数调用使用显式指定的类型参量,如下所示: fun::<A, B, ...>(). struct A; // 具体类型 `A`。 struct S(A); //

  • 问题内容: 我目前正在努力完成出色的“围棋之旅”。我使用以下解决方案完成了其中一项练习(#45): 我不明白为什么我必须使用两次该类型的语句(请参见摘要中的注释)。这似乎是多余的,但我不知道该怎么做。 问题答案: Go中没有其他方法可以做到这一点。 是的,我同意这很冗长,但有必要。第二个make()语句完全独立于第一个。可以争论的是,编译器应该能够从推断类型,但此时还不行。 另一点:如果在第二种情

  • 问题内容: 如果我有一个像这样的抽象类: 还有一些从Item派生的类是这样的: 我不明白为什么我不能使用泛型调用构造函数: 我知道可以有一个没有构造函数的类型,但是这种情况是不可能的,因为Pencil具有没有参数的构造函数,而Item是抽象的。但是我从eclipse中得到了这个错误: 无法实例化 我不明白为什么的 T类型 ,以及如何避免这种情况? 问题答案: 无法使用Java类型系统来强制类层次结

  • 问题内容: 我正在学习中,文档和交互式课程说,空可以容纳任何类型,因为它不需要其他实现的方法。 举个例子: …将打印出来… 因此,我想我的问题是这是实现通用函数的方法,还是还有另一种更合适的方法来实现它们。 问题答案: Go范式通常是通过在非空接口中实现行为来避免这种情况。例如,假设您要打印特定于类型的格式的内容: 或者,您可以为知道如何进行字符串自身设置的接口定义一个接口(该接口在库中以形式存在

  • 我不想为每个类型T编写这个方法只是为了调用getMessage()并将其传递给下一个方法。 有可能写出这样的方法吗?我只想访问ConstraintViolation接口的方法,这些方法不依赖于类型T(如字符串getMessage())。

  • 假设我们想获取一个 map 类型的切片,我们必须使用两次 make() 函数,第一次分配切片,第二次分配 切片中每个 map 元素(参见下面的例子 8.4)。 示例 8.4 maps_forrange2.go: package main import "fmt" func main() { // Version A: items := make([]map[int]int, 5)