Реализация списка с интерфейсами Go

Go предоставляет двусвязный список в container/list:

import "container/list"

l := list.New()

// Добавление
e1 := l.PushBack(10)
e2 := l.PushBack(20)
e3 := l.PushFront(5)

// Вставка относительно элемента
l.InsertAfter(15, e1)
l.InsertBefore(7, e1)

// Удаление
l.Remove(e2)

// Обход
for e := l.Front(); e != nil; e = e.Next() {
    fmt.Println(e.Value.(int))
}

list.Element.Value имеет тип any — нужно приведение типа при чтении.

type List[T any] struct {
    head *node[T]
    tail *node[T]
    len  int
}

type node[T any] struct {
    val  T
    prev *node[T]
    next *node[T]
}

func (l *List[T]) PushBack(v T) *node[T] {
    n := &node[T]{val: v, prev: l.tail}
    if l.tail != nil { l.tail.next = n }
    l.tail = n
    if l.head == nil { l.head = n }
    l.len++
    return n
}

func (l *List[T]) Len() int { return l.len }
func (l *List[T]) Filter(fn func(T) bool) *List[T] {
    result := &List[T]{}
    for n := l.head; n != nil; n = n.next {
        if fn(n.val) { result.PushBack(n.val) }
    }
    return result
}

func (l *List[T]) Map(fn func(T) T) *List[T] {
    result := &List[T]{}
    for n := l.head; n != nil; n = n.next {
        result.PushBack(fn(n.val))
    }
    return result
}

ЗаданиеСложность
1Упражнение 1easy
2Упражнение 2easy
3Упражнение 3medium