LoginSignup
32
14

More than 1 year has passed since last update.

Go で Stack と FIFO

Last updated at Posted at 2022-08-15

はじめに

Go 強化月間 と聞いたので Go の記事を書きます。

Go で Stack や FIFO を実装する時には container/list を使います。この container/list は Stack と FIFO に必要となるベースのみ提供されます。なぜなら Stack も FIFO も仕組みは同じで、取り出す時に先頭か最後かの違いしかないからです。

Stack

container/list をフィールドに持ち、末端に追加、末端から取り出すのが Stack ですね。

package main

import (
	"container/list"
	"fmt"
)

type Stack struct {
	v *list.List
}

func NewStack() *Stack {
	return &Stack{v: list.New()}
}

func (s *Stack) Push(v interface{}) {
	s.v.PushBack(v)
}

func (s *Stack) Pop() interface{} {
	b := s.v.Back()
	if b == nil {
		return nil
	}
	return s.v.Remove(b)
}


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

FIFO

同じく container/list をフィールドに持ち、末端に追加、先頭から取り出すのが FIFO ですね。

package main

import (
	"container/list"
	"fmt"
)

type FIFO struct {
	v *list.List
}

func NewFIFO() *FIFO {
	return &FIFO{v: list.New()}
}

func (s *FIFO) Push(v interface{}) {
	s.v.PushBack(v)
}

func (s *FIFO) Pop() interface{} {
	b := s.v.Front()
	if b == nil {
		return nil
	}
	return s.v.Remove(b)
}

func main() {
	f := NewFIFO()
	f.Push(1)
	f.Push(2)
	f.Push(3)
	fmt.Println(f.Pop())
	fmt.Println(f.Pop())
	fmt.Println(f.Pop())
}

int に限定したい場合は こんな 感じ。

まとめ

Go には Stack や FIFO が無い様に見えて実はある、というお話でした。ちなみに FIFO は chan を使っても実現できます。chan は通常、goroutine でデータを通信する為に使われますが、バッファがあれば同一のメイン goroutine 内で FIFO としても使えます。

package main

import "fmt"

func main() {
    fifo := make(chan int, 5)
    fifo <- 1
    fifo <- 2
    fifo <- 3
    fmt.Println(<-fifo)
    fmt.Println(<-fifo)
    fmt.Println(<-fifo)
}

32
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
14