Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for reasonable stack implementation in golang?

Tags:

go

So far my naive approach is

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 } 

it works - playground, but looks ugly and has too much dereferencing. Can I do better?

like image 748
Uvelichitel Avatar asked Feb 16 '15 12:02

Uvelichitel


People also ask

How do you implement a stack in Golang?

Stacks are most easily implemented in Golang using slices: An element is pushed to the stack with the built-in append function. The element is popped from the stack by slicing off the top element.

For which stack implementation we can use?

Instead of using array, we can also use linked list to implement stack. Linked list allocates the memory dynamically. However, time complexity in both the scenario is same for all the operations i.e. push, pop and peek.

Which data structure best implements stack?

You can perform the implementation of stacks in data structures using two data structures that are an array and a linked list. Array: In array implementation, the stack is formed using an array. All the operations are performed using arrays.


2 Answers

It's a matter of style and personal taste, your code is fine (apart from not being thread safe and panicking if you pop from an empty stack). To simplify it a bit you can work with value methods and return the stack itself, it's slightly more elegant to some tastes. i.e.

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)  } 

Another approach is to wrap it in a struct, so you can also easily add a mutex to avoid race conditions, etc. something like:

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()) } 
like image 190
Not_a_Golfer Avatar answered Sep 28 '22 10:09

Not_a_Golfer


Here is a LIFO implementation using linked data structure

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 } 
like image 23
guy_fawkes Avatar answered Sep 28 '22 08:09

guy_fawkes