Ce face container/list.New
container/list oferă o listă dublu înlănțuită: fiecare element (*list.Element) știe care este elementul dinainte și cel de după. Poți adăuga sau scoate elemente oriunde în listă în timp constant, fără să muți celelalte elemente, cum se întâmplă la un slice.
list.New() returnează un *list.List gol. Și valoarea zero a tipului este gata de folosit: var l list.List merge la fel. Valorile se pun în câmpul Value al fiecărui element, de tip any, așa că la citire faci conversia: e.Value.(string).
În practică, un slice este aproape mereu mai rapid și mai simplu. Lista este utilă când ții pointeri la elemente și le muți des, de exemplu într-un cache LRU (cel mai recent folosit în față, cel mai vechi scos de la coadă).
Ce returnează
New returnează un *list.List gol.
Exemple
Exemplul 1: Creare, adăugare și parcurgere
package main
import (
"container/list"
"fmt"
)
func main() {
l := list.New()
l.PushBack("Iași")
l.PushBack("Vaslui")
l.PushFront("Suceava")
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
var goala list.List // valoarea zero e gata de folosit
goala.PushBack(1)
fmt.Println(goala.Len())
}
Rezultat
Suceava
Iași
Vaslui
1
Exemplul 2: Cache LRU cu listă și map
Map-ul găsește rapid elementul, lista ține ordinea folosirii. La depășirea capacității se scoate elementul de la coadă (cel mai vechi).
package main
import (
"container/list"
"fmt"
)
type Cache struct {
cap int
lista *list.List
dupa map[string]*list.Element
}
func (c *Cache) Acceseaza(cheie string) {
if e, ok := c.dupa[cheie]; ok {
c.lista.MoveToFront(e)
return
}
c.dupa[cheie] = c.lista.PushFront(cheie)
if c.lista.Len() > c.cap {
vechi := c.lista.Back()
c.lista.Remove(vechi)
delete(c.dupa, vechi.Value.(string))
}
}
func main() {
c := &Cache{cap: 3, lista: list.New(), dupa: map[string]*list.Element{}}
for _, pagina := range []string{"acasa", "php", "go", "php", "rust"} {
c.Acceseaza(pagina)
}
for e := c.lista.Front(); e != nil; e = e.Next() {
fmt.Print(e.Value, " ")
}
fmt.Println()
}
Rezultat
rust php go
Greșeli frecvente
- Folosești o listă înlănțuită unde un slice ar ajunge: parcurgerea unei liste este mult mai lentă (elementele sunt împrăștiate în memorie).
- Uiți conversia la citire:
e.Value + 1nu compilează, pentru căValueesteany. Scriee.Value.(int) + 1.
Comenzi înrudite
container/list.List.PushBack: PushBack adaugă o valoare la sfârșitul listei, PushFront la început; ambele returnează elementul nou creat.container/list.List.Front: Front returnează primul element al listei (sau nil dacă e goală), iar Len numărul de elemente; cu Next parcurgi lista.container/list.List.Remove: Scoate elementul e din listă și returnează valoarea lui.container/heap.Init: Funcțiile de bază ale unui heap (coadă de priorități): Init îl organizează, Push adaugă, Pop scoate elementul cel mai mic.