고루틴과 채널을 활용한 유사 액터 모델

액터 모델? 액터 모델은 동시성 문제를 해결하기 위해 등장한 개념입니다. 각 액터는 독립된 스레드에서 실행되며, 메시지를 통해 상호작용합니다. 액터 모델은 다음과 같은 특징을 가집니다. 액터는 메모리를 공유하지 않습니다. 액터는 고유의 상태를 가질 수 있습니다. 액터 간의 통신은 메시지를 통해 이루어집니다. 액터 간의 통신은 비동기적입니다. 액터는 해당 메시지에 대응하는 동작을 수행합니다. CSP와 너무 잘 맞지 않아? 고 언어는 기반 패러다임에 CSP가 있는 만큼, 고루틴과 채널이라는 강력한 도구가 있습니다. 이를 이용해 타 언어에 비해 손 쉽게 액터 모델을 구현할 수 있습니다....

March 19, 2023 · snowmerak

고랭과 아레나

Arena? 고랭은 가비지 컬렉터를 쓰는 언어이고, 덕분에 사용자는 메모리를 관리하는 데에 크게 신경을 쓸 필요가 없습니다. 하지만 프로젝트 크기가 커지고, 사용해야할 힙 메모리가 커질수록 더욱 빈번하게, 그리고 한번에 많은 양의 메모리를 수집하여 처리하게 됩니다. 하나의 기능을 수행하고 난 후에는 물론이고, 수행하는 도중에도 GC가 동작하여 응답이 늦어지는 상황이 생겨날 확률이 늘어납니다. 그런 상황에서 유용하게 쓸 수 있는 아레나(arena)라는 개념이 등장했습니다. 아레나는 미리 사용할 힙 메모리를 할당 받아서 사용합니다. 이 때 할당받는 큰 힙 메모리 덩어리 하나를 페이지라고 합니다....

May 19, 2022 · snowmerak

러스트로 알고리즘 테스트를 풀어봅시다

왜 러스트? 개인적으로 러스트로 알고리즘 문제를 푸는 건 좋은 선택이라 생각합니다. 아래의 다양한 자료구조를 빌트인으로 제공합니다. Vector VecDeque LinkedList HashMap HashSet BtreeMap BtreeSet BinaryHeap 유용한 이터러블과 빌트인 고차함수들이 있습니다. 일단 이터러블로 변환하면 뭐든지 가능하다는 장점이 있습니다. 이 과정은 당연히 정적 타입으로 이루어지기에 실수가 줄어듭니다. 튜플과 패턴 매칭 문법이 훌륭하고 표현식입니다. ()로 만드는 튜플은 어떤 타입, 어떤 길이로도 가능하여 유용합니다. match 문법은 튜플조차 패턴 매칭을 해내기에 어떤 조건도 직관적으로 표현할 수 있습니다....

April 12, 2022 · snowmerak

[A] enum in go

이 페이지의 고 코드는 제네릭이 포함되어 있습니다. enum? 고에서 열거형은 아래의 단순한 형태, 혹은 조금의 변형으로밖에 작성되지 않습니다. package week const ( Monday = iota Tuesday Wednesday Thursday Friday Saturday Sunday ) 단순하게 week 패키지 내에서 상수를 선언하여 가져다 쓰는 정도입니다. 하지만 그건 어디까지나 열거형을 위한 패키지를 분리하지 않았기에 제한되는 방식이라 생각합니다. package as class 단일 역할에 대해 단일 구현체만 패키지에 작성할 경우 패키지를 클래스처럼 이용할 수 있습니다....

March 12, 2022 · snowmerak

[A] role playing go

개요 고 언어를 사용하여 프로젝트를 구성할 때, 제가 주로 작성하는 스타일을 정리하는 글입니다. 대체로 import cycle을 해결하거나 어느정도의 OOP를 구현하는 데에도 용이하다고 생각합니다. 역할 각 패키지는 고유의 역할을 가지게 됩니다. 역할은 2가지 경우로 나뉩니다. 역할에 대해 단일 구현체만 존재할 경우 역할에 대해 여러 구현체가 존재할 경우 단일 구현체가 존재할 경우 여러 서비스 간 주고 받는 로그 객체를 만든다고 가정합시다. 저는 log라는 패키지를 만들 것입니다. package log type Log struct { UnixTime int64 `parquet:"name=unix_time, type=INT64" json:"unix_time"` AppID int32 `parquet:"name=app_id, type=INT32" json:"app_id"` Level int32 `parquet:"name=level, type=INT32" json:"level"` Message string `parquet:"name=message, type=BYTE_ARRAY, convertedtype=UTF8, encoding=PLAIN_DICTIONARY" json:"message"` } log라는 패키지 아래에 Log 구조체를 직접 생성하여 log 패키지를 클래스처럼 작성합니다....

March 11, 2022 · snowmerak

간단한 로드밸런서와 HTTP 프록시 서버 구현

레이트 리미터 Limiter interface package limiter type Limiter interface { TryTake([]byte) (bool, int) } 레이트 리미터 객체가 구현해야할 인터페이스로 Limiter 인터페이스가 있습니다. 바이트 슬라이스를 받아서 해당 슬라이스를 기반으로 레이트 리밋을 계산하여 이번 요청이 사용 가능하면 true와 적절한 status code를 반환합니다. slide count struct type SlideCount struct { lock *lock.Lock unit int64 maxConnPer float64 prevTime int64 prevCount int64 curCount int64 nextTime int64 } func New(maxConnPer float64, unit time.Duration) limiter.Limiter { now := int64(time....

March 11, 2022 · snowmerak

[A] 전략 패턴에 대해서

행위 패턴의 하나로, 어떤 문제를 해결함에 어떤 방법을 사용하는 지 적절히 선택, 혹은 작성할 수 있게 해주는 패턴 코틀린으로 평균을 구하는 계산기 만들기 이 계산기의 평균을 구하는 방법은 총 3가지가 있습니다. 산술 평균 : (a + b) / 2 기하 평균 : root2(a * b) 조화 평균 : 2ab / (a + b) 이 3가지를 각각 따로 입력 받아 실행하는 평균만 구하는 계산기의 코틀린 코드입니다....

March 4, 2022 · snowmerak

고루틴 풀링

이 글은 제 레포를 기반으로 작성되었습니다. 왜? 오픈톡방에서 고루틴에 대한 이야기가 나왔었습니다. 고루틴을 안전하게 관리하기 위한 보일러플레이트에 대한 것과 join과 반환값의 처리에 대한 것이었습니다. 그래서 한번 해당 건에 대해 나름의 해답을 라이브러리로 만들어봤습니다. gopool GoPool type GoPool struct { pool sync.Pool max int64 count int64 running int64 sync.Mutex } 고풀 구조체는 고루틴을 풀링할 sync.Pool, 그리고 int64 타입의 max, count, running을 가집니다. max는 최대 고루틴 수, count는 현재 생성된 고루틴 수, running은 현재 실행되고 있는 고루틴 수를 의미합니다....

January 21, 2022 · snowmerak

logstream

이 글은 제 로그 라이브러리를 작성하며 생각한 것을 작성한 것입니다. 개요 logstream 라이브러리는 로그를 생성하고 소비하는 패턴을 구현하기 위해 만든 일종의 고 프로그램 전역에서 돌아가는 메시지 큐입니다. 다른 메시지 큐와 마찬가지로 여러 생산자가 토픽에 값을 추가하고 소비자가 토픽에서 값을 꺼내서 사용합니다. 생산자(producer)는 코드 상 어디라도 될 수 있으며 스트림을 내포하고 있는 객체는 글로벌큐(global queue)로 전역 객체로 생성될 것입니다. 소비자(customer)는 글로벌큐 내부 스트림을 통해 순차적으로 생산자가 만들어낸 로그를 받아서 소비합니다. 소비는 가급적이면 모든 소비자 중 하나가 한번 소비하면 로그가 사라지는 게 아니라 모든 소비자에게 돌아가는 걸 목표로 합니다....

January 6, 2022 · snowmerak

스마트폰 파괴 방법과 매개변수 덕타핑

개요 인터페이스 비교로 에러를 처리하는 방식에 기반하여 인터페이스로 매개변수를 덕타이핑하는 건 어떨까 해서 한번 시도해봤습니다. 아이디어 아이디어는 쉽습니다. 베이스가 되는 인터페이스와 구조체를 작성합니다. 이후 필요에 따라 매개변수를 얻을 수 있는 새로운 인터페이스를 제공하고 해당 인터페이스에 대한 구조체를 작성합니다. 그렇다면 동일한 함수 원형에 여러가지 타입의 매개변수를 넘겨줄 수 있을 것입니다. 구현 스마트폰을 파괴하는 코드를 작성해보겠습니다. PhoneBreaker package phonebreaker type PhoneBreakable interface { Break(PhoneBreakingTool) int } type PhoneBreakingTool interface { Hand() int } 간단하게 PhoneBreakable 인터페이스로 휴대폰을 파괴할 수 있는 행위를 정의해 놓았습니다....

January 4, 2022 · snowmerak