Primrose Docs
  • Home
    • ⛓️Blockchain
      • Avalanche
        • What is AVAX?
      • Ethereum
        • Ethereum Cancun Upgrade Explained(draft)
        • go-ethereum: gas estimate
        • Blockchain Transaction Lifecycle
        • Mempool
        • Gas optimization in Solidity, Ethereum
      • Solidity DeepDive
        • Meta transaction
        • solidity: patterns
        • UUPS vs Transparent
        • Solidity Interface
        • Smart contract storage
        • ERC-2981 Contract
        • Solidity modifier
        • Solidity delete keyword
        • How To Make NFTs with On-Chain Metadata - Hardhat and JavaScript
        • How to Build "Buy Me a Coffee" DeFi dapp
        • How to Develop an NFT Smart Contract (ERC 721) with Alchemy
        • Upgradeable Contract
        • Smart Contract Verification
      • Common
        • Eigenlayer
        • MultiSig(draft)
        • Chain-Based Proof-of- Stake, BFT-Style Proof-of-Stake
        • Byzantine Fault Tolerance
        • Zero-knowledge
        • Hierarchical Deterministic Wallet
        • Maker DAO
        • Defi
        • Uniswap
        • IBC
        • Cosmos
        • Gossip Protocol
        • Tendermint
        • UTXO vs Account
        • Blockchain Layer
        • Consensus Algorithm
        • How does mining work?
        • Immutable Ledger
        • SHA256 Hash
        • Filecoin
        • IPFS - InterPlanetary File System
        • IPFS와 파일코인
        • Livepeer
        • Layer 0
      • Bitcoin
        • BIP for HD Wallet
        • P2WPKH
        • Segwit vs Native Segwit
    • 📖Languages
      • Javascript/Typescript
        • Hoisting
        • This value in Javascript
        • Execution Context
        • About Javscript
        • tsconfig.json
        • Nest js Provider
        • 'return await promise' vs 'return promise'
      • Python
        • Pythonic
        • Python: Iterable, Iterator
        • Uvicorn & Gunicorn
        • WSGI, ASGI
        • Python docstring
        • Decorator in Python
        • Namespace in Python
        • Python Method
      • Go
        • GORM+MySQL Connection Pool
        • Context in golang
        • How to sign Ethereum EIP-1559 transactions using AWS KMS
        • Mongo DB in golang(draft)
        • Golang HTTP Package
        • Panic
        • Golang new/make
        • golang container package
        • errgroup in golang
        • Generic Programming in Golang
        • Goroutine(draft)
    • 📝Database
      • MongoDB in golang
      • Nested loop join, Hash join
      • DB Query plan
      • Index
      • Optimistic Lock Pessimistic Lock
    • 💻Computer Science
      • N+1 query in go
      • Web server 를 구성할 때 Thread, Process 개수를 어떻게 정할 것인가?
      • CAP
      • Socket programming
      • DNS, IP
      • URL, URI
      • TLS과 SSL
      • Caching(draft)
      • Building Microservices: Micro Service 5 Deploy Principle
      • Red Black Tree
      • AOP
      • Distributed Lock
      • VPC
      • Docker
      • All about Session and JWT
      • Closure
      • Singleton Pattern
      • TCP 3 way handshake & 4 way handshake
      • Race Condition
      • Process Address Space 
      • Call by value, Call by reference, Call by assignment
      • Zookeeper, ETCD
      • URL Shortening
      • Raft consensus
      • Sharding, Partitioning
    • 📒ETC
      • K8S SIGTERM
      • SQS
      • Git Branch Strategy: Ship / Show / Ask
      • Kafka
      • Redis Data Types
      • CI/CD
      • How does Google design APIs?
      • Minishell (42 cursus)
      • Coroutine & Subroutine
      • Redis
Powered by GitBook
On this page
  1. Home
  2. Languages
  3. Go

golang container package

container package

golang에는 빌트인으로 사용할 수 있는 container package가 있다.

개발을 하다보면, 자료구조를 사용할 일이 꽤 생긴다.

go에서는 container 패키지에서 기본 자료구조를 제공해주므로 꽤나 편리하게 사용할 수 있다.

패키지에서 제공하는 자료구조는 다음과 같다.

  • Linked list

  • Heap

  • Ring (Circular list)

container 패키지를 이용해서 간단한 자료구조를 구현해보자.

container/list

package main

import (
	"container/list"
	"log"
)

func main() {
	lst := list.New()
	lst.PushBack(1)
	lst.PushBack(2)
	lst.PushBack(3)

	log.Println(lst.Len())
}

위와 같이 container/list 패키지를 import하면, 손쉽게 linked list를 사용할 수 있다.

개발을 하면서 linked list를 사용해야 한다면, 꽤나 시간을 단축시킬 수 있을 것이다.

list를 순회하고 싶다면 아래와 같은 방법도 가능하다.

package main

import (
	"container/list"
	"fmt"
	"log"
)

func main() {
	lst := list.New()
	lst.PushBack(1)
	lst.PushBack(2)
	lst.PushBack(3)

	log.Println(lst.Len())

	for e := lst.Front(); e != nil; e = e.Next() { // 연결 리스트의 맨 앞부터 끝까지 순회
		fmt.Println(e.Value)
	}
}

container/heap

다음은 heap 패키지이다. 필자는 최근 회사에서 체결엔진/오더북을 구현하면서 min heap과 max heap을 구현할 일이 있었는데,

container/heap 패키지를 통해 간단하게 구현할 수 있었다.

heap 패키지에서는 기본적으로 다음과 같은 인터페이스가 필요하다.

package heap 

type Interface interface {
	Len() int
	Less(i, j int) bool
	Swap(i, j int)
	Push(x any)
	Pop() any  
}

한 번 구현해서 사용해보자. 예제에서는 min heap을 구현해본다.

package main

import (
	"container/heap"
	"log"
)

type IMinHeap interface {
	heap.Interface
}

type MinHeap struct {
	heap []uint
}

func (m *MinHeap) Len() int {
	return len(m.heap)
}

func (m *MinHeap) Less(i, j int) bool {
	return m.heap[i] < m.heap[j]
}

func (m *MinHeap) Swap(i, j int) {
	m.heap[i], m.heap[j] = m.heap[j], m.heap[i]
}

func (m *MinHeap) Push(x any) {
	m.heap = append(m.heap, x.(uint))
}

func (m *MinHeap) Pop() any {
	old := m.heap
	n := len(old)
	element := old[n-1]
	m.heap = old[0 : n-1]
	return element
}

func main() {
	minHeap := &MinHeap{heap: []uint{}}

	heap.Init(minHeap)

	heap.Push(minHeap, uint(10))
	heap.Push(minHeap, uint(20))
	heap.Push(minHeap, uint(50))
	heap.Push(minHeap, uint(5))

	log.Println(heap.Pop(minHeap)) // 5
	log.Println(heap.Pop(minHeap)) // 10
	log.Println(heap.Pop(minHeap)) // 20
	log.Println(heap.Pop(minHeap)) // 50
}

Less 조건의 부호만 반대로 바꿔줘도 max heap으로 바꾸어 사용할 수 있어 편하다.

container/ring

다음은 ring이다. ring은 비교적 사용할 일이 많이 없는 듯 보이지만, 알아두면 때때로 도움이 될 수도 있다.

개인적으로는 list를 쓰는 편이긴 하다.

package main

import (
	"container/ring"
	"fmt"
)

func main() {
	data := []string{"Maria", "John", "Andrew", "James"}
	r := ring.New(len(data))       // 노드의 개수를 지정하여 링 생성
	for i := 0; i < r.Len(); i++ { // 링 노드 개수만큼 반복
		r.Value = data[i] // 링의 노드에 값 넣기
		r = r.Next()      // 다음 노드로  이동
	}

	r.Do(func(x interface{}) { // 링의 모든 노드 순회
		fmt.Println(x)
	})

	// "Maria" 
	// "John" 
	// "Andrew"
	// "James"
}

두 개의 ring을 연결하는 것도 물론 가능하다.

package main

import (
	"container/ring"
	"fmt"
)

func main() {
	data := []string{"Maria", "John", "Andrew", "James"}
	r := ring.New(len(data))       // 노드의 개수를 지정하여 링 생성
	for i := 0; i < r.Len(); i++ { // 링 노드 개수만큼 반복
		r.Value = data[i] // 링의 노드에 값 넣기
		r = r.Next()      // 다음 노드로  이동
	}

	r.Do(func(x interface{}) { // 링의 모든 노드 순회
		fmt.Println(x)
	})

	// "Maria" 
	// "John" 
	// "Andrew"
	// "James"

	newData := []uint{1, 2, 3, 4}

	r2 := ring.New(len(newData))
	for i := 0; i < r2.Len(); i++ { // 링 노드 개수만큼 반복
		r2.Value = newData[i] // 링의 노드에 값 넣기
		r2 = r2.Next()        // 다음 노드로  이동
	}

	r3 := r.Link(r2)

	r3.Do(func(x interface{}) { // 링의 모든 노드 순회
		fmt.Println(x)
	})
	// John
	// Andrew
	// James
	// Maria
	// 1
	// 2
	// 3
	// 4
}
PreviousGolang new/makeNexterrgroup in golang

Last updated 1 year ago

📖