2015-02-16 10 views
14

Bisher meine naive Ansatz istAuf der Suche nach einer vernünftigen Stack-Implementierung in Golang?

type stack []int 

func (s *stack) Push(v int) { 
    *s = append(*s, v) 
} 

func (s *stack) Pop() int { 
    res:=(*s)[len(*s)-1] 
    *s=(*s)[:len(*s)-1] 
    return res 
} 

es funktioniert - playground, sieht aber hässlich und zu viel dereferenzierenden hat. Kann ich es besser machen?

+2

Besser in welchem ​​Aspekt? –

+0

@Michael Fouarakis Besser in der Bedeutung - nicht so hässlich, lesbarer und Vermeidung von Referenz auf Scheibe, die Referenztyp selbst ist. – Uvelichitel

+0

https://github.com/karalabe/cookiejar hat eine ziemlich performante Implementierung. – 0x434D53

Antwort

28

Es ist eine Frage von Stil und persönlichem Geschmack, Ihr Code ist in Ordnung (abgesehen davon, nicht thread sicher und in Panik, wenn Sie aus einem leeren Stapel Pop). Um es ein wenig zu vereinfachen, können Sie mit Wertmethoden arbeiten und den Stapel selbst zurückgeben, es ist etwas eleganter zu einigen Geschmäcken. dh

type stack []int 

func (s stack) Push(v int) stack { 
    return append(s, v) 
} 

func (s stack) Pop() (stack, int) { 
    // FIXME: What do we do if the stack is empty, though? 

    l := len(s) 
    return s[:l-1], s[l-1] 
} 


func main(){ 
    s := make(stack,0) 
    s = s.Push(1) 
    s = s.Push(2) 
    s = s.Push(3) 

    s, p := s.Pop() 
    fmt.Println(p) 

} 

Ein weiterer Ansatz ist es in einer Struktur wickeln, so können Sie auch einfach einen Mutex in den Rennbedingungen zu vermeiden, usw. so etwas wie:

type stack struct { 
    lock sync.Mutex // you don't have to do this if you don't want thread safety 
    s []int 
} 

func NewStack() *stack { 
    return &stack {sync.Mutex{}, make([]int,0), } 
} 

func (s *stack) Push(v int) { 
    s.lock.Lock() 
    defer s.lock.Unlock() 

    s.s = append(s.s, v) 
} 

func (s *stack) Pop() (int, error) { 
    s.lock.Lock() 
    defer s.lock.Unlock() 


    l := len(s.s) 
    if l == 0 { 
     return 0, errors.New("Empty Stack") 
    } 

    res := s.s[l-1] 
    s.s = s.s[:l-1] 
    return res, nil 
} 


func main(){ 
    s := NewStack() 
    s.Push(1) 
    s.Push(2) 
    s.Push(3) 
    fmt.Println(s.Pop()) 
    fmt.Println(s.Pop()) 
    fmt.Println(s.Pop()) 
} 
+0

nitpick, Sie müssen nicht wirklich eine neue 'sync.Mutex', & Stack {s: [] int {}} übergeben 'ist genug. – OneOfOne

+0

@ OneOfOne yeah, du hast Recht :) –

+0

Sie können versuchen, meine generische Implementierung. Es ist auch ziemlich schnell. https://github.com/alediaferia/stackgo – alediaferia

6

Hier ist eine LIFO-Implementierung mit verknüpften Datenstruktur

package stack 

import "sync" 

type element struct { 
    data interface{} 
    next *element 
} 

type stack struct { 
    lock *sync.Mutex 
    head *element 
    Size int 
} 

func (stk *stack) Push(data interface{}) { 
    stk.lock.Lock() 

    element := new(element) 
    element.data = data 
    temp := stk.head 
    element.next = temp 
    stk.head = element 
    stk.Size++ 

    stk.lock.Unlock() 
} 

func (stk *stack) Pop() interface{} { 
    if stk.head == nil { 
     return nil 
    } 
    stk.lock.Lock() 
    r := stk.head.data 
    stk.head = stk.head.next 
    stk.Size-- 

    stk.lock.Unlock() 

    return r 
} 

func New() *stack { 
    stk := new(stack) 
    stk.lock = &sync.Mutex{} 

    return stk 
} 
Verwandte Themen