开发者

Any type and implementing generic list in go programming language

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


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜