Go编程语言中的任意类型和实现泛型列表

发布于 2024-12-09 05:36:45 字数 687 浏览 0 评论 0原文

我正在尝试一些 go 编程语言

我对 Go 的简单性感到兴奋,但在使用它之后我遇到了一些麻烦。

1.我知道Go不支持泛型和继承。 有没有办法实现通用列表?

我正在考虑使用:

type Any interface { }

但是如何检查该值是否为NULL。
我正在寻找一些与 C 等效的实现

struct List {
  List* tail;
  void* head;
}

或者使用代数数据类型:

data List a = Nil | Cons a (List a)


2.更高级的要求是为具有特定类型字段的对象创建一些容器?
例如,在 Scala 编程语言中,我可以输入:

val List[Animal { type SuitableFood = Grass} ]

获取 AnimalsList,其成员类型 SuitableFoodGrass

I'm trying a little of go programming language.

I'm a excited about the simplicity of the Go, but after playing with it I met some troubles.

1 . I know that Go doesn't support generics and inheritance. Is there any way to implement generic list?

I thinking about using:

type Any interface { }

but how can I check if the value is NULL.
I'm looking for some equivalent implementation to C

struct List {
  List* tail;
  void* head;
}

Or using algebraic datatype:

data List a = Nil | Cons a (List a)

2 . More advanced requirement would be to make some container for objects with a field of a particular type?
For example in Scala programming language I can type:

val List[Animal { type SuitableFood = Grass} ]

to get a List of Animals, which have a member type SuitableFood which is Grass

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笑梦风尘 2024-12-16 05:36:45

您可以拥有 interface{} 类型的元素列表。你可以放入任何元素,当你取出它时,你必须转换回你想要的类型。这就像您在 C 示例中所做的 void * ;也像 Java 中没有泛型之前的列表,以及 Objective-C 中没有泛型的列表。 Go 库中的所有容器都执行此操作。

如果没有泛型,就无法对元素类型进行编译时检查。

如果您确实想要,可以通过使用反射来获取元素类型并根据预期类型检查它们来实现元素类型的运行时检查。然而,这可能有点矫枉过正了。

You can have a list of elements of type interface{}. You can put any elements in, and when you get it out, you have to cast back to the type you want. This is like what you're doing void * in your C example; and also like lists in Java before Generics, and in Objective-C, which doesn't have generics. All the containers in the Go library do this.

Without generics, there is no compile-time checking of the element types.

If you really wanted, you could implement run-time checks for element type, by using reflection to get the element types and checking them against the expected type. However, this is probably overkill.

落日海湾 2024-12-16 05:36:45

我知道 Go 不支持泛型 [...]

从 Go 1.18 开始支持泛型。我希望标准库最终能够沿着当前的 container/list< 添加通用容器/a> 包,这样你就不必重新发明轮子。

无论如何,作为思考练习,您可以复制标准 list.List 并自己添加类型参数:

type Element[T any] struct {
    next, prev  *Element[T]
    list        *List[T]
    Value       T
}

type List[T any] struct {
    root Element[T]
    len  int
}

// simplified constructor
func New[T any]() *List[T] { 
    l := new(List[T])
    l.root.next = &l.root
    l.root.prev = &l.root
    l.len = 0
    return l
}

如您所见,Element 结构可以具有类型为 Element< 的字段/code>,但类型参数必须相同且顺序相同(来源) 。

为具有特定类型字段的对象创建一些容器?

您可以通过将约束 any 替换为指定所需方法的接口约束来实现此目的,例如:

type Animal interface { 
    SuitableFood() string 
}

type Element[T Animal] struct {
    // ...
}

这会将类型参数限制为实现 Animal 接口的类型参数。


不能做的就是将类型参数限制为具有特定的字段1。如果您必须强制 T 具有特定值,则可以向接口约束添加更具体的方法,例如 SuitableFoodGrass() 但这是一个泄漏抽象 /em>.接口对行为进行建模,您应该遵守该原则。


1:从技术上讲,您可以使用结构的类型约束,但它不会很有用

I know that Go doesn't support generics [...]

It does as of Go 1.18. I expect the standard library to eventually add generic containers along the current container/list package so you don't have to reinvent the wheel.

Anyway as a thought exercise you could copy the standard list.List and add type parameters yourself:

type Element[T any] struct {
    next, prev  *Element[T]
    list        *List[T]
    Value       T
}

type List[T any] struct {
    root Element[T]
    len  int
}

// simplified constructor
func New[T any]() *List[T] { 
    l := new(List[T])
    l.root.next = &l.root
    l.root.prev = &l.root
    l.len = 0
    return l
}

As you can see Element struct can have a field of type Element, but the type params must be the same ones and in the same order (source).

make some container for objects with a field of a particular type?

You can do this by replacing the constraint any with an interface constraint that specified the method you want, for example:

type Animal interface { 
    SuitableFood() string 
}

type Element[T Animal] struct {
    // ...
}

and this constrains the type parameter to those that implement the Animal interface.


What you can not do is constrain the type param to have a particular field1. If you must force T to have specific values, you could instead add a more specific method to the interface constraint, e.g. SuitableFoodGrass() but that's a leaky abstraction. Interfaces model behavior, and you should stick to that principle.


1: Technically you can, using a type constraint with a struct, but it wouldn't be very useful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文