Lecture Note

백엔드를 위한 Go 프로그래밍 서평 및 자유로운 기록

soohey 2022. 9. 11. 14:40

우연한 기회로 책을 읽게 되어 써보는 글입니다 :)

 

1. 책의 목표

우선 책을 주욱 읽어보니

책의 목표가 다른 언어를 사용하던 개발자가 Go 언어를 접하기 쉽도록 하는데에 초점을 두고 있다.

왜이렇게 생각하냐면, 

책안에서 계속해서 다른 언어와의 비교를 통해서 어떤 점이 다른지를 알려준다.

또한 이러한 비교를 통해서 Go가 가진 명확한 장점을 뽐내는 느낌을 받았다.

C, Java, Swift등 다양한 언어군들과의 비교를 사용하기 때문에 더 많은 언어에 대해 공부해본 사람일수록 더 Go에 대해 이해하기 쉬울 것 같다.

 

2. 책의 구성

1. 단원 시작 전에 짚고 넘어가면 좋을만한 부분을 소개해준다. 그리고 단원끝에는 스스로 정리할 수 있도록 Q가 정리되어있음. 그래서 내가 얼마나 대충 읽었는지 알 수 있었음 ㅎㅎㅋ. 아마 몇회독 한 후 그 부분을 스스로 정리 가능하다면 이 책을 완독했다고 할 수 있을거 같았다.

 

2. 앞서 말했듯이 다른 언어와 비교해서 코드 구현 설명을 해준다. 잊고 있었던 부분도 긁어 줘서 좋았고, Go에서는 어떤 부분이 다른지 명확히 알 수 있었다.

 

3. 적절한 분량. 요즘 자바의 정석을 읽고 있는 중이라 이 책이 정독서 보다는 입문자를 위해 소개하는 책이라고 느껴졌다. 두께도 180쪽 분량정도 되어 자바의 정석의 약 2단원 정도의 분량이다. Go를 찍먹하고 싶거나 가볍게 읽기 좋은 책이며, 그럼에도 불구하고 비교가 산뜻하게 되어있으며 코드에 대한 설명도 되어있다. 

 

4. 시작이 좋음. 소설이든 정독서든 서론이 중요하다는 생각을 하는데 (시작이 반이기 때문이다..) 이 책은 서론이 Go 한번 찍먹해볼래? 라는 느낌이라 시작하기 쉬웠다. 서론에서는 Go를 왜 사용하는지, 단점 장점들이 쉽게 정리되어있다.

궁금하다면 한번 읽어보는 걸로~

 

3. 자유롭게 기록해보기! (읽다가 흥미로운 부분을 기록해보았다.. 내맘대로 주의)

Go에는 채널이라는 기능이 있는데

작업 완료까지 기다리기 위해서 사용한다.

고루틴

  • 어떤 함수 A가 실행하는데 매우 긴 시간이 필요할 경우, 이것을 별도의 고루틴에서 실행하게 하고, 메인 함수는 함수A가 실행하는 동안 필요한 무언가를 계속 진행하게끔 할 수 있다.
  • 고루틴을 통해 함수A를 백그라운드에서 실행하도록 한 것이다.
  • "이것은 현재 우리가 있는 고루틴과 분리된 별도의 고루틴"
  • 효율성 부분에선 천재적

Go가 스레드들에서 여러개의 고루틴을 다루고 스케줄링을 처리하는 동안 특정 고루틴이 syscall을 위해 다른 고루틴들을 차단할 경우 프로그램이 느려진다.

이 상황에서 Go는 새로운 스레드를 생성하고 고루틴을 해당 스레드로 이동하여 고루틴을 계속 구동시키도록 한다.

-> 스레드간 전환 비용이 적다.

채널

  • 다른 고루틴에 데이터를 보낼 수 있음(통신)
  • 고루틴에 입력 채널, 출력 채널을 통해서 데이터를 전달하고 출력할 수가 있음

채널 종류 3가지

1. 버퍼링되지 않은 채널(동기화 채널) : 하나의 고루틴에서 요소 하나를 저장하고, 다른 고루틴에서 이걸 가지고 가서 다른 요소를 저장함

2. 버퍼링된 채널 : 잠재적으로 여러 고루틴에서 여러 요소를 저장하며, 채널이 가득 찼을때만 송신자를 블록

3. 크기가 0인 요소가 있는 채널

 

  • 데드락 : 모든 스레드가 다른 스레드의 작업을을 기다리는 상황이 발생함
  • 세마포어 : 멀티프로그래밍 환경에서 공유 자원에 대한 접근을 제한하는 방법 ( 세마포어를 생성하고 일부작업을 수행하는 새 스레드를 시작하고, 완료되면 세마포어를 해제함)
  • 백그라운드에서 작업이 진행되는 동안 메인 스레드는 세마포어를 기다리며, 백그라운드 스레드가 해당작업을 완료하기를 기다림

그런데 데드락이 생길수 있는 위험이 있음

이를 해결하기 위해서는 먼저 메인 고루틴이 종료되며 사용하던 함수 고루틴을 강제 종료할 때, 해당 고루틴이 정상적으로 종료되지 않는 문제가 존재한다.

이 문제는 입력 채널에서 데이터를 기다리는 작업이 완료되었는지 확인할 수 없으므로 발생한 것이다.

해결하기 위해 빌트인 기능 / Go의 동시성 설계를 이용한다.

1. 빌트인된 기능 -> 간단히 채널을 클로징하는 것으로 문제를 해결한다.

  • close(inputChannel)

2.  채널에 도입된 새로운 기능 select문

  • 고루틴이 다양한 채널로부터 데이터를 기다릴 수 있게 해줌, 가장 먼저 값을 제공하는 채널로부터 데이터를 가져갈 수 있게 함
  • select는 표현식이 무언가에 의해 블록되는 모든 케이스를 살펴보고, 먼저 블록 해제되는 코드를 실행하며, 해당 코드가 실행된 후에는 다음 코드가 가리키는 명령문으로 이동한다.

 

반복문 내에서 호출되는 함수가 변수를 "캡쳐"하는 작업이 수행됨

Go는 복사본을 만드는 대신 루프 변수 자체에 접근하도록 만들어짐

코드에서 반복을 진행하며 sleeep을 시작하는 여러개의 고루틴이 생성되며, 반복의 끝에서 고루틴 생성을 중지함

이즈음에서 모든 고루틴이 깨어나며 모두 똒같은 i를 참조하게 됨. 그래서 10을 열번 반복함

해결하려면 루프 변수를 캡쳐하는 대신 함수에 전달하는 것으로 해결

Go는 함수를 호출하고 값을 파라미터로 전달해 복사본을 만들도록 해야함