2

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

0

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

3

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.