본문 바로가기

Go46

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.
Effective Go - Concurrency - 2 - 출처: https://go.dev/doc/effective_go#channels - Channels channel은 map처럼 make 문법을 통해서 할당하며 결과값은 데이터 구조에 대한 참조 역할을 한다. 만약 2번째 인자로 integer parameter를 주면 channel에 대한 버퍼 사이즈를 설정한다. 기본값은 0이며, 0이면 버퍼를 갖지 않는(unbuffered) 동기화 channel을 의미한다. ci := make(chan int) // unbuffered channel of integers cj := make(chan int, 0) // unbuffered channel of integers cs := make(chan *os.File, 100) // buffered channel of.. 2022. 6. 1.
Effective Go - Concurrency - 1 - 출처: https://go.dev/doc/effective_go#concurrency - Share by communicating 동시성 프로그래밍은 매우 방대한 주제이다. 동시성 프로그래밍은 공유 변수에 대한 정확한 접근을 구현하기 위해 요구되는 미묘한 부분 때문에 어려운 주제이기도 하다. Go 언어는 공유되는 값들이 channel 이라는 개념을 통해 전달되고, 실제로는 실행되는 각 스레드들에서 공유가 활성화되지 않는 색다른 접근방식을 제안한다. 어느 시점에서든 하나의 값에는 하나의 goroutine만 접근이 가능하다. 이런 설계때문에 data race가 일어나지 않는다. effective go 문서에서는 이런 사고방식을 장려하기 위해 하나의 슬로건으로 이를 요약하고 있다. Do not commun.. 2022. 6. 1.
Effective Go - Embedding - 출처: https://go.dev/doc/effective_go#embedding - Embedding Go는 일반적으로 subclassing type 개념을 제공하지는 않지만, struct나 interface 내에서 type을 embedding 하면 해당 type이 구현하는 행위들을 가져올 수 있다. Interface embedding은 매우 간단하다. 아래 코드는 io.Reader와 io.Writer 이다. type Reader interface { Read(p []byte) (n int, err error) } type Writer interface { Write(p []byte) (n int, err error) } io package는 이런 메소드들을 구현할 수 있는 객체들을 지정하는 다른 .. 2022. 5. 29.
Effective Go - Interfaces and other types - 출처: https://go.dev/doc/effective_go#interfaces_and_types - Interfaces Go에서 interface는 객체의 행동을 지정하는 방법이다. 만약 A가 B를 할 수 있다면 A는 여기에 사용될 수 있다는것을 의미한다. Go에서 1개 혹은 2개의 메소드들로 구성된 interface 들을 어렵지 않게 볼 수 있는데, Write 메소드를 구현하는 io.Writer interface 처럼 이름은 대체적으로 해당 메소드들로 부터 파생된다. 하나의 형은 여러 개의 interface들을 구현할 수 있다. 예를 들어 아래 코드에서 Sequence는 Len(), Less(i, j int) bool, Swap(i, j int)를 포함하는 sort.Interface를 구현하는.. 2022. 5. 26.
Effective Go - Methods - 출처: https://go.dev/doc/effective_go#methods - Methods 메소드는 포인터나 인터페이스를 제외하고 명명된 유형에 대해 정의될 수 있다. 즉 Receiver가 반드시 구조체가 아니어도 된다. 예를 들어 Append라는 함수를 slice의 메소드로 정의할 수 있는데, 이렇게 하기 위해서는 우선 메소드를 묶을 수 있도록 명명된 유형을 정의해야 한다. 그리고 Receiver로 해당 형을 기술해준다. type ByteSlice []byte func (slice ByteSlice) Append(data []byte) []byte { // Body exactly the same as the Append function defined above. } 위의 메소드는 갱신된 sli.. 2022. 5. 17.
Effective Go - Array and Slice - 출처: https://go.dev/doc/effective_go#arrays - Arrays Go에서 Arrays는 주로 slice를 위한 block을 할당하는데 사용된다. Go와 C에서 array가 동작하는 방식의 주요 차이점은 아래와 같다. Arrays는 value 이므로 하나의 array를 다른 array에 할당하면 모든 요소들이 복사된다. 특히 array는 함수에 넘기면 함수는 해당 array의 pointer가 아니라 array의 복사본을 받는다. Array의 크기는 해당 type의 요소이므로 [10]int와 [20]int은 다르다. Value 특성은 유용하게 사용되긴 하지만 비용이 크다. 만약 C와 동일한 동작방식과 효율성을 원한다면 아래 코드처럼 array에 대한 pointer를 넘길 수 .. 2022. 5. 8.