본문 바로가기

Language89

Go - context (blog) - 출처: https://go.dev./blog/context - 소개 Go 서버에서 들어오는 요청은 goroutine 으로 다루어지며, 요청 핸들러는 DB나 RPC 서비스 접근을 위해 추가적인 goroutine을 생성하기도 한다. 때로는 이런 goroutine 들이 공유해야 하는 값들(ex - end user 식별값, authorization token, 요청 deadline 등)이 있을 수 있다. 만약 요청이 취소되거나 timeout이 발생하면 사용중이던 자원을 회수해야 한다. go 에서는 이런 상황들을 해결할 수 있도록 Context를 제공한다. - Context context package의 핵심인 Context 형을 살펴보자. // A Context carries a deadline, cance.. 2022. 11. 13.
Go - pipelines and cancellation - 출처: https://go.dev/blog/pipelines - 개요 Go 언어는 동시성을 잘 지원하는 언어라서 I/O나 CPU를 효율적으로 사용하는 스트리밍 데이터 파이프라인 구축이 수월하다. 하지만 파이프라인을 구축하다보면 인지하거나 처리하기 어려운 오류 혹은 미묘한 부분이 발생할 수 있는데 이를 자세히 알아보고 어떻게 깔끔하게 처리 하는지 알아본다. - 파이프라인이란? 공식적인 정의는 없지만 비공식적으로는 채널에 의해 연결되는 단계(Stage) 들이 연속적으로 연결된것이라고 할 수 있다. 각 단계에서 고루틴은 아래와 같은 동작을 취한다. inbound 채널을 통해 upstream 으로 부터 값들을 수신한다. 해당 데이터에 대해 일부기능을 수행하는데 일반적으로는 데이터를 생성하는 행위이다. out.. 2022. 10. 21.
package name base, util, or common - 출처: https://dave.cheney.net/2019/01/08/avoid-package-names-like-base-util-or-common - package name 좋은 Go package를 작성하려면 이름을 잘 지어야 한다. 하나의 단어로 해당 package가 무엇을 하는지 간략하게 나타낼 수 있어야 한다. package name을 보다보면 utility 라는 이름을 종종 볼 수 있다. 이런 package명은 관계없는 기능들이 많이 포함되어있어서 package 명을 보고 무엇을 제공하는지 알기가 힘들다. utils나 helpers 같은 package 이름은 계층 구조가 깊은package를 개발하고 순환참조 없이 helper 기능들을 공유하기를 원할 때 사용하곤 한다. utility 기.. 2022. 6. 26.
Empty struct - 출처: https://dave.cheney.net/2014/03/25/the-empty-struct - Introduction empty struct란 말 그대로 field가 하나도 없는 struct type 이다. type Q struct{} var q struct{} 근데 여기서 한 가지 의문점이 생긴다. field도 없고 데이터도 포함되어있지 않은 struct를 왜 사용하는것인가? - Width empty struct를 알아보기 전에 width에 대해서 알아보자. width 라는 용어는 gc 컴파일러에서 유래했는데, type의 instance를 저장할 때 필요한 byte 수라고 할 수 있다. 이 블로그의 원문을 쓴 필자는 프로세스의 주소 공간은 1차원이기 때문에 width가 size보다 더 적절.. 2022. 6. 21.
Zero value - 출처: https://dave.cheney.net/2013/01/19/what-is-the-zero-value-and-why-is-it-useful - Zero value 내장 함수 new나 make를 호출하거나 선언을 통한 값을 저장하기 위해 메모리가 할당될 때, 명시적으로 초기화를 하지 않으면 메모리에는 기본 초기화된 값이 저장된다. 이때에는 해당 type에 맞는 zero value가 설정된다. boolean은 false, integer는 0, float은 0.0, string은 "", pointer, function, interface, slice, channel, map은 nil로 초기화된다. 초기화는 재귀적으로 일어나는데, struct 배열의 각 요소 인스턴스에는 값이 주어지지 않으면 해당 .. 2022. 6. 17.
Error handling을 간단하게 - 출처: https://dave.cheney.net/2019/01/27/eliminate-error-handling-by-eliminating-errors - 개요 Go2는 오류를 처리할 때 오버헤드를 줄이는 방향으로 목표하고 있다. 오류를 처리할 때 향상된 문법보다 더 중요한것이 있는데, 그건 바로 오류를 처리할 필요가 없도록 하는것이다. 이 말의 의미는 "error를 다루는 코드를 없애라"는 의미가 아니라 "다루어야 할 오류가 많아 지지 않도록 코드를 변경하라"는 의미이다. 원문의 저자는 해당 글을 John Ousterhout's의 A philosophy of Software Design에서 영감을 받았다고 한다. - Example 1 아래 코드는 파일의 라인 수를 세는 코드이다. func Coun.. 2022. 6. 16.
Exception - 출처: https://dave.cheney.net/2012/01/18/why-go-gets-exceptions-right - History C는 단일값을 반환하는 구조였기 때문에 함수 실행과정에서 문제가 생겼을 때 이를 파악하는 과정이 복잡했다. 물론 이런 문제를 다루기 위한 프로그래밍 스킬들이 있었다. 예를 들면 구조체의 내용을 변경하는 함수에 포인터를 넘겨주면 반환된 코드가 해당 작업을 성공했는지를 나타내는것과 같은 방식이다. 다른 스킬들도 있지만 이 글에서 다루고자하는 중심적인 얘기는 아니므로 넘어가겠다. C++이 되면서 error를 다루는 작업이 진화했다. 어떤 함수가 값을 반환하거나 exception을 던지면 이를 잡아서 다루는게 가능해졌다. C++ 프로그래머들은 error 상황을 함수가 반.. 2022. 6. 14.
Error handling - 출처: https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully - Errors are just values error를 다루는데 있어서 많은 의견들과 조언들이 있지만 정돈된 하나의 규칙은 없는듯하다. 대신 일반적으로 Go에서 error를 다루는 3 가지 방법에 대해서 알아보도록 하자. - Sentinel error error를 다루는 첫번째 전략은 일명 "sentinel error"이다. if err == ErrSomething { … } 이 이름은 더이상 처리가 불가능함을 나타내기 위해 특정값을 사용하는 컴퓨터 프로그래밍의 관행에서 따온것이다. Go에서는 오류를 나타내기 위해 특정값을 사용한다. 이런 예로는 i.. 2022. 6. 12.
Effective Go - Errors - 출처: https://go.dev/doc/effective_go#errors - Errors 라이브러리 함수들을 사용하다보면 호출자에게 오류를 반환하는 경우를 본적이 있을것이다. Go의 다중 값 반환을 이용하면 일반적인 반환 값과 함께 자세한 error도 같이 반환할 수 있다. 자세한 error 정보를 반환하기 위해 다중 값 반환을 사용하는것은 좋은 습관이다. 예를 들어 os.Open은 실패시 nil pointer만 반환하지 않고 무엇이 잘못되었는지를 기술하는 error 값도 같이 반환한다. Convention에 의해 error 들은 간단한 빌트인 인터페이스인 error type을 갖는다. type error interface { Error() string } 라이브러리 작성자는 풍부한 모델을 사용.. 2022. 6. 5.
Effective Go - Concurrency - 3 - 출처: https://go.dev/doc/effective_go#parallel - Parallelization 앞의 파트(Concurrency - 2)까지 알아보았던 동시성과 관련해서 여러 개의 Core를 사용하여 계산을 병렬처리 하는 부분도 생각해볼 수 있다. 만약 계산이 독립적으로 실행될 수 있는 조각들로 분리될 수 있다면 각 조각들의 완료 여부를 channel을 통해 signal을 보내면 병렬화가 가능하다. vector의 요소들이 비용이 큰 연산들로 구성되어있고 각 요소의 연산 값이 독립적인 경우를 생각해보자. type Vector []float64 // Apply the operation to v[i], v[i+1] ... up to v[n-1]. func (v Vector) DoSome(i.. 2022. 6. 2.