일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- hyperledger fabric
- 하이퍼레저 패브릭
- Golang
- 블록체인
- Akka
- 스칼라
- Play2
- Hyperledger fabric gossip protocol
- 엔터프라이즈 블록체인
- 파이썬 강좌
- 파이썬 데이터분석
- 파이썬
- 스위프트
- 주키퍼
- 스칼라 강좌
- Adapter 패턴
- akka 강좌
- 그라파나
- 안드로이드 웹뷰
- Play2 로 웹 개발
- 하이브리드앱
- 플레이프레임워크
- 파이썬 머신러닝
- Actor
- play 강좌
- 이더리움
- CORDA
- 파이썬 동시성
- play2 강좌
- 스칼라 동시성
- Today
- Total
HAMA 블로그
[이더리움으로 배우는 GO언어] 자료구조 & 컬렉션 본문
[이더리움으로 배우는 GO언어] 자료구조 & 컬렉션
이번 글에서는 사실 이더리움하고 크게 상관없이 go 자료구조 기본에 대해서 알아 봅니다.
Array
var a [5]int // [0 0 0 0 0]
a[4] = 100 // [0 0 0 0 100]
5개의 비어있는 배열 생성과 값 삽입
b := [5]int{1, 2, 3, 4, 5} // [1 2 3 4 5]
5개 요소가 들어있는 배열 생성
a2 := [...]string{"USA", "China", "India", "Germany", "France"}
b2 := a2 // a copy of a is assigned to b
b2[0] = "Singapore"
fmt.Println("a is ", a2) // [USA China India Germany France]
fmt.Println("b is ", b2) // [Singapore China India Germany France]
5개 요소가 들어있는 배열 생성과 배열복사시 깊은 복사 이루어 지는 모습
a3 := [...]float64{67.7, 89.8, 21, 78}
for i := 0; i < len(a3); i++ {
fmt.Printf("%d th element of a is %.2f\n", i, a[i])
}
sum := float64(0)
for i, v := range a3 {// i는 인덱스, v 는 값
fmt.Printf("%d the element of a is %.2f\n", i, v)
sum += v
}
순회를 도는 2가지 방식
Slice
a4 := [5]int{76, 77, 78, 79, 80}
var b4 []int = a4[1:4] //creates a slice from a[1] to a[3]
b4[0] = 100
fmt.Println(a4) // [76 100 78 79 80]
배열을 가지고 슬라이스 생성 / 그렇게 만들어진 슬라이스는 배열과 레퍼런스로 연결되어 있다.
i := make([]int, 5, 5)
make 를 이용한 슬라이스 생성
cars := []string{"Ferrari", "Honda", "Ford"}
cars = append(cars, "Toyota") // [Ferrari Honda Ford Toyota]
append를 이용하여 슬라이스 뒤에 요소 추가
cars := []string{"Ferrari", "Honda", "Ford"}
cars = append(cars[:0], "Toyota","KIA") // [Toyota KIA]
fmt.Println(cars)
append를 이용하여 새로운 슬라이스 생성.
veggies := []string{"potatoes","tomatoes","brinjal"}
fruits := []string{"oranges","apples"}
food := append(veggies, fruits...)
append를 이용하여 슬라이스 뒤에 슬라이스 추가 ( 추가될 슬라이스 변수에 ... 를 추가한다)
countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}
neededCountries := countries[:len(countries)-2]
countriesCpy := make([]string, len(neededCountries))
countriesCpy2 := countries[:len(countries)-2]
copy(countriesCpy, neededCountries) //copies neededCountries to countriesCpy
countriesCpy[0] = "korea"
countriesCpy2[1] = "japan"
fmt.Println(countriesCpy) // 깊은복사 [korea Singapore Germany]
fmt.Println(countriesCpy2) // 얖은복사 [USA japan Germany]
fmt.Println(countries) // [USA japan Germany India Australia]
슬라이스의 일부분을 복사하는데 make로 만든 배열에 copy를 이용하여 복사하면 깊은 복사가 된다.
startTasks := func(ts []task) (rest []task) {
i := 0
for ; len(runningTasks) < maxActiveDialTasks && i < len(ts); i++ {
t := ts[i]
...
runningTasks = append(runningTasks, t)
}
return ts[i:]
}
현재 실행되고 있는 업무(runningTasks)가 정해진 숫자(maxActiveDialTasks) 를 넘지 않아서 대기중인 업무를 할 수 있는 상태일때, 매개변수로 받은 대기중인 업무들을 실행한다. 추가 실행한 업무는 runningTasks 에 append를 통해서 실행중인 업무로 추가되고, 실행업무에 추가되지 못한 업무들은 ts[i:] 로 리턴된다.
scheduleTasks := func() {
queuedTasks = append(queuedTasks[:0], startTasks(queuedTasks)...)
if len(runningTasks) < maxActiveDialTasks {
nt := dialstate.newTasks(len(runningTasks)+len(queuedTasks), peers, time.Now())
queuedTasks = append(queuedTasks, startTasks(nt)...)
}
}
대기업무중인 업무들을 startTasks로 보내서 실행하게 하고, 실행이 안된 업무를 queuedTasks[:0] 같이 append 하여 다시 구성한다. 실행중인 업무가 maxActiveDialTasks 작을경우 새로운 업무들을 만들어서 (newTasks) startTasks로 실행한후에 남은 태스크는 queuedTasks 에 append한다.
Map
m := make(map[string]int)
m["first"] = 1
fmt.Println(m["first"]) // 1
키가 string 값이 int 은 맵을 make 를 통해 만들어서 추가/출력 한다.
var fileExtensions = map[string]string{
"Python": ".py",
"C++": ".cpp",
"Java": ".java",
"Golang": ".go",
"Kotlin": ".kt",
}
fmt.Println(fileExtensions) // map[Python:.py C++:.cpp Java:.java Golang:.go Kotlin:.kt]
delete(fileExtensions, "Kotlin")
delete(fileExtensions, "Javascript")
fmt.Println(fileExtensions) // map[Python:.py C++:.cpp Java:.java Golang:.go]
delete 를 통해서 삭제한다.
s := map[int]string{5: "five", 2: "second"}
_, ok := s[5] // check for existence // ok 는 true
_, ok2 := s[6] // check for existence // ok 는 false
키가 없을 경우에는 ok 가 false
var m1 = map[string]int{
"one": 1,
"two": 2,
"three": 3,
"four": 4,
"five": 5,
}
var m2 = m1
fmt.Println("m1 = ", m1) // map[one:1 two:2 three:3 four:4 five:5]
fmt.Println("m2 = ", m2) // map[one:1 two:2 three:3 four:4 five:5]
m2["ten"] = 10
fmt.Println("m1 = ", m1) // map[ten:10 one:1 two:2 three:3 four:4 five:5]
fmt.Println("m2 = ", m2) // map[ten:10 one:1 two:2 three:3 four:4 five:5]
맵끼리의 대입은 레퍼런스식으로 공유한다.
var personAge = map[string]int{
"Rajeev": 25,
"James": 32,
"Sarah": 29,
}
for name, age := range personAge {
fmt.Println(name, age)
}
맵을 순회하는 방식은 range를 사용하여 key와 value를 추출한다.
MapSet("github.com/deckarep/golang-set")
이 자료구조는 도커,이더리움,쿠버네이트에서 사용되는 간단한 set 타입이다.
s := mapset.NewSet()
s.Add("Cooking")
s.Add("English")
s.Add("Math")
s.Add("Biology")
s.Add("Biology")
s.Add("Biology")
s.Add("Biology")
fmt.Printf(s.String()) // Set{Biology, Cooking, English, Math}
중복적재가 안되는 모습이구요~
s.Pop() // 아무거나 랜덤으로 하나 제거 합니다.
scienceSlice := []interface{}{"Biology", "Chemistry","Biology"}
scienceClasses := mapset.NewSetFromSlice(scienceSlice)
fmt.Printf(scienceClasses.String()) //Set{Biology, Chemistry}
슬라이스로부터 셋을 만드는 모습이구요~ 덤으로 중복요소가 없어졌습니다.
requiredClasses := mapset.NewSet()
requiredClasses.Add("Biology")
requiredClasses.Add("Cooking")
scienceSlice := []interface{}{"Biology", "Chemistry"}
scienceClasses := mapset.NewSetFromSlice(scienceSlice)
electiveClasses := mapset.NewSet()
electiveClasses.Add("Welding")
electiveClasses.Add("Music")
bonusClasses := mapset.NewSet()
bonusClasses.Add("Go Programming")
bonusClasses.Add("Python Programming")
allClasses := requiredClasses.Union(scienceClasses).Union(electiveClasses).Union(bonusClasses)
fmt.Println(allClasses) //Set{Python Programming, Biology, Cooking, Chemistry, Welding, Music, Go Programming}
Set 을 Union으로 합쳤습니다. 역시 중복요소는 제거됩니다.
//포함여부 검사?
fmt.Println(scienceClasses.Contains("Cooking")) //false
//과학클래스 과목을 제외한 모든 클래스는?
fmt.Println(allClasses.Difference(scienceClasses)) //Set{Music, Go Programming, Python Programming, Cooking, Welding}
//교집합
fmt.Println(scienceClasses.Intersect(requiredClasses)) //Set{Biology}
//How many bonus classes do you offer?
fmt.Println(bonusClasses.Cardinality()) //2
Contains 로 포함여부 검사/Difference 로 포함그룹군 제외/ Intersect로 교집합추출/ Cardinality로 요소갯수
container/List
values := list.New()
// Add 3 elements to the list.
values.PushBack("bird")
values.PushBack("cat")
values.PushFront("snake")
// Add 100 elements at the front.
for i := 0; i < 20; i++ {
// Convert ints to strings.
values.PushFront(strconv.Itoa(i))
}
// Loop over container list.
for temp := values.Front(); temp != nil; temp = temp.Next() {
fmt.Println(temp.Value)
}
앞,뒤로 삽입할수 있는 리스트
container/heap
// An Item is something we manage in a priority queue.
type Item struct {
value string // The value of the item; arbitrary.
priority int // The priority of the item in the queue.
// The index is needed by update and is maintained by the heap.Interface methods.
index int // The index of the item in the heap.
}
// A PriorityQueue implements heap.Interface and holds Items.
type PriorityQueue []*Item
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool {
// We want Pop to give us the highest, not lowest, priority so we use greater than here.
return pq[i].priority > pq[j].priority
}
func (pq PriorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
pq[i].index = i
pq[j].index = j
}
func (pq *PriorityQueue) Push(x interface{}) {
n := len(*pq)
item := x.(*Item)
item.index = n
*pq = append(*pq, item)
}
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
item := old[n-1]
item.index = -1 // for safety
*pq = old[0 : n-1]
return item
}
// update modifies the priority and value of an Item in the queue.
func (pq *PriorityQueue) update(item *Item, value string, priority int) {
item.value = value
item.priority = priority
heap.Fix(pq, item.index)
}
// This example creates a PriorityQueue with some items, adds and manipulates an item,
// and then removes the items in priority order.
func main() {
// Some items and their priorities.
items := map[string]int{
"banana": 3, "apple": 2, "pear": 4,
}
// Create a priority queue, put the items in it, and
// establish the priority queue (heap) invariants.
pq := make(PriorityQueue, len(items))
i := 0
for value, priority := range items {
pq[i] = &Item{
value: value,
priority: priority,
index: i,
}
i++
}
heap.Init(&pq)
// Insert a new item and then modify its priority.
item := &Item{
value: "orange",
priority: 1,
}
heap.Push(&pq, item)
pq.update(item, item.value, 5)
// Take the items out; they arrive in decreasing priority order.
for pq.Len() > 0 {
item := heap.Pop(&pq).(*Item)
fmt.Printf("%.2d:%s ", item.priority, item.value)
// 05:orange 04:pear 03:banana 02:apple
}
}
heap을 이용해서 우선순위큐를 구현한 모습이구요~
container/ring
package main
import (
"container/ring"
"fmt"
"time"
)
func main() {
number := []string{"1", "2", "3", "4", "5"}
// 버퍼 생성
r := ring.New(len(number)) // 버퍼에 값 채움
for i := 0; i < r.Len(); i++ {
r.Value = number[i]
r = r.Next()
}
// 버퍼 순회하며 출력
r.Do(func(x interface{}) {
fmt.Println(x)
})
// 버퍼 무한 순회하며 출력
for _ = range time.Tick(time.Second * 1) {
fmt.Println(r.Value)
r = r.Next()
}
}
Do를 통해서 한바퀴 순회하고, Next()를 통해서 무한이 순회할 수 있는 환영큐입니다.
'Go' 카테고리의 다른 글
고성능을 위한 GO (0) | 2019.02.13 |
---|---|
[이더리움에서 배우는 Go언어] select 의 거의 모든 패턴들 (1) | 2019.02.08 |
[이더리움에서 배우는 Go언어] 강력하게 밀착된 컴포지션 (0) | 2019.01.10 |
[이더리움에서 배우는 Go언어] nat 옵션 이야기 - (2) (0) | 2018.12.14 |
[이더리움에서 배우는 Go언어] nat 옵션 이야기 - (1) (0) | 2018.12.14 |