简体   繁体   中英

Embedded structs

please could someone explain how the Push function below works?

This is from https://gobyexample.com/generics .

The generics aspect makes sense to me, but I'm struggling with the embedded struct element in List.

It appears List has only two fields, which are pointers to the element struct.

Looking at the logic in Push, it seems the if statement is met once, the first time the method Push is called.

I don't understand how Push is adding multiple elements every time it gets called.

package main

import "fmt"

func MapKeys[K comparable, V any](m map[K]V) []K {
    r := make([]K, 0, len(m))
    for k := range m {
        r = append(r, k)
    }
    return r
}

type List[T any] struct {
    head, tail *element[T]
}

type element[T any] struct {
    next *element[T]
    val  T
}

func (lst *List[T]) Push(v T) {
    if lst.tail == nil {
        lst.head = &element[T]{val: v}
        lst.tail = lst.head
    } else {
        lst.tail.next = &element[T]{val: v}
        lst.tail = lst.tail.next
    }
}

func (lst *List[T]) GetAll() []T {
    var elems []T
    for e := lst.head; e != nil; e = e.next {
        elems = append(elems, e.val)
    }
    return elems
}

func main() {
    var m = map[int]string{1: "2", 2: "4", 4: "8"}

    fmt.Println("keys:", MapKeys(m))

    _ = MapKeys[int, string](m)

    lst := List[int]{}
    lst.Push(10)
    lst.Push(13)
    lst.Push(23)
    fmt.Println("list:", lst.GetAll())
}

The output is:

keys: [2 4 1]
list: [10 13 23]

The Push func works by initially setting head and tail as the same pointer to element.

Subsequent calls set the next field of the tail element to a new element pointer.

Push adds multiple elements here:

lst.tail.next = &element[T]{val: v}
lst.tail = lst.tail.next //the tail becomes a new element with next as nil

The key is that each time next is assigned a new element, the following line sets the tail to be tail.next. This means each 'next' leads to the next element.

This is the concept of a singly-linked list - it allows unidirectional traversal of the list, starting at the head, ending at the tail, which each element containing data (in this case an int), and a pointer to the next node (in this case, element pointer). In the final element, next will be nil, signifying the end of the list.

These lists are more memory efficient than a fixed size array, as the memory can be dynamically allocated as the list grows.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM