[Golang nâng cao] Stack trong Golang

Post on: 2023-04-12 22:40:40 | in: Golang
Trong Go, Stack (ngăn xếp) có thể được triển khai bằng cách sử dụng một slice (mảng động) và sử dụng các phương thức của slice để thêm và xóa phần tử.

Tổng quan

Ngăn xếp (stack) là một kiểu dữ liệu trừu tượng mà chỉ cho phép thêm (push) và lấy ra (pop) các phần tử ở phía đầu ngăn xếp. Phần tử cuối cùng được thêm vào sẽ được lấy ra đầu tiên (Last-In-First-Out - LIFO). Ngăn xếp thường được sử dụng để lưu trữ các hành động (actions) hoặc các biến tạm thời (temporary variables) trong chương trình.

Một ngăn xếp đơn giản có thể được triển khai bằng GO sử dụng:

  1. container/list package
  2. slice

Một ngăn xếp sẽ có các hoạt động sau:

  1. Push
  2. Pop
  3. Front
  4. Size
  5. Empty

Triển khai bằng List

Trong Golang, ngăn xếp (stack) cũng có thể được triển khai bằng cách sử dụng package container/list có sẵn trong thư viện chuẩn của Golang. Package list cung cấp một cấu trúc dữ liệu danh sách liên kết kép (doubly linked list), và các phương thức của nó có thể được sử dụng để triển khai ngăn xếp.

Dưới đây là ví dụ về cách triển khai ngăn xếp bằng list package:

package main

import (
    "container/list"
    "fmt"
)

type customStack struct {
    stack *list.List
}

func (c *customStack) Push(value string) {
    c.stack.PushFront(value)
}

func (c *customStack) Pop() error {
    if c.stack.Len() > 0 {
        ele := c.stack.Front()
        c.stack.Remove(ele)
    }
    return fmt.Errorf("Pop Error: Stack is empty")
}

func (c *customStack) Front() (string, error) {
    if c.stack.Len() > 0 {
        if val, ok := c.stack.Front().Value.(string); ok {
            return val, nil
        }
        return "", fmt.Errorf("Peep Error: Stack Datatype is incorrect")
    }
    return "", fmt.Errorf("Peep Error: Stack is empty")
}

func (c *customStack) Size() int {
    return c.stack.Len()
}

func (c *customStack) Empty() bool {
    return c.stack.Len() == 0
}

func main() {
    customStack := &customStack{
        stack: list.New(),
    }
    fmt.Printf("Push: A\n")
    customStack.Push("A")
    fmt.Printf("Push: B\n")
    customStack.Push("B")
    fmt.Printf("Size: %d\n", customStack.Size())
    for customStack.Size() > 0 {
        frontVal, _ := customStack.Front()
        fmt.Printf("Front: %s\n", frontVal)
        fmt.Printf("Pop: %s\n", frontVal)
        customStack.Pop()
    }
    fmt.Printf("Size: %d\n", customStack.Size())
}

Output:

Push: A
Push: B
Size: 2
Front: B
Pop: B
Front: A
Pop: A
Size: 0

Triển khai bằng Slice

Trong Golang, bạn có thể triển khai một ngăn xếp (stack) bằng cách sử dụng một slice. Dưới đây là ví dụ về cách triển khai một ngăn xếp đơn giản sử dụng slice trong Golang:
package main

import (
    "fmt"
    "sync"
)

type customStack struct {
    stack []string
    lock  sync.RWMutex
}

func (c *customStack) Push(name string) {
    c.lock.Lock()
    defer c.lock.Unlock()
    c.stack = append(c.stack, name)
}

func (c *customStack) Pop() error {
    len := len(c.stack)
    if len > 0 {
        c.lock.Lock()
        defer c.lock.Unlock()
        c.stack = c.stack[:len-1]
        return nil
    }
    return fmt.Errorf("Pop Error: Stack is empty")
}

func (c *customStack) Front() (string, error) {
    len := len(c.stack)
    if len > 0 {
        c.lock.Lock()
        defer c.lock.Unlock()
        return c.stack[len-1], nil
    }
    return "", fmt.Errorf("Peep Error: Stack is empty")
}

func (c *customStack) Size() int {
    return len(c.stack)
}

func (c *customStack) Empty() bool {
    return len(c.stack) == 0
}
​​​​​​​
func main() {
    customStack := &customStack{
        stack: make([]string, 0),
    }
    fmt.Printf("Push: A\n")
    customStack.Push("A")
    fmt.Printf("Push: B\n")
    customStack.Push("B")
    fmt.Printf("Size: %d\n", customStack.Size())
    for customStack.Size() > 0 {
        frontVal, _ := customStack.Front()
        fmt.Printf("Front: %s\n", frontVal)
        fmt.Printf("Pop: %s\n", frontVal)
        customStack.Pop()
    }
    fmt.Printf("Size: %d\n", customStack.Size())
}

Output:

Push: A
Push: B
Size: 2
Front: B
Pop: B
Front: A
Pop: A
Size: 0

Tổng kết

Đây là tất cả những gì cần biết về stack trong Go. Mong rằng bạn đã thích bài viết này. Vui lòng chia sẻ phản hồi / cải tiến / sửa lỗi trong phần bình luận.