Go만의 어떤 것

Ryu·2022년 5월 17일
0

2021-archive

목록 보기
8/8

2021년에 작성한 노트를 옮겨 적은 것입니다.

Go의 특징

장점

  • 성능면에서 유리
    • 병렬 프로그래밍에 유리하기 때문. C보다 쓰기 쉬움
  • 컴파일이 빠르다.
  • 라이브러리의 문서화가 잘되어있다.

특징

C 90 % + javascript 10%의 느낌

알려진 것과 다르게 진입 장벽이 낮진 않음.

  • 클래스가 없고
  • Exception이 없음 (!?)
  • goroutine + channel이라는 개념
  • context라는 개념

요약

병렬 프로그래밍을 위한 언어이고, 그걸 잘 만들수 있도록 여러 라이브러리를 언어 레벨에서 구현하였으니

프로그래머가 알아서 똑똑하게 잘 써야함.

너가 병렬처리 못해서 프로그램이 돌릴 때마다 다른 결과 나와도 너의 탓이고 go가 뭘 말해주진 않음.

Go를 잘 쓰려면 알아야하는 것

Concurrency Control

  • C의 thread를 사용하기 쉽게 구현했다
    • goroutine: a light weight thread
    • channel: goroutine의 결과값을 받기 위한 통로
  • 반드시 종료해야한다.
    • 언제 종료하는지 모르는 루틴은 시작도 하면 안됨 → memory leak 때문
  • 그래서 약간 Promise 같다
func main() {
  ch := make(chan int)
  go foo(ch)
  go bar(ch)
}
 
func foo(ch chan int) {
  ...
  ch <- 45 // 채널에 값 넣는다
}
 
func bar(ch chan int) {
  ...
  v := <- ch // 값이 올 때까지 기다리다가 오면 처리함
  println(v)
}

Sync

  • Mutex, WaitGroup등을 통해서 여러 goroutine을 제어
  • 약간 promise await이나 thread 라이브러리 같다

WaitGroup은 고루틴이 완료될 때까지 기다립니다. 메인 고루틴은 Add를 호출하여 몇 개의 고루틴을 기다릴 것인지 설정합니다. 각각의 고루틴은 작업이 완료되면 Done을 호출합니다. Wait는 모든 고루틴이 완료될 때까지 프로그램을 블락합니다.

Context

  • 여러 goroutine 사이에 통하는 맥락
  • 약간 Promise chain 같다
    • 유저 조회 Reqeust → fetch db → trim data → response
    • 위 goroutine 중 하나가 취소되거나 하면 이하 작업들을 수행하지 않게 할 수 있다
package main
 
import (
  "context"
  "fmt"
  "sync"
  "time"
)
 
func longFunc() string {
  <-time.After(time.Second * 5)
  return "Success"
}
 
func longFuncWithCtx(ctx context.Context) (string, error) {
  done := make(chan string)
 
  go func() {
    done <- longFunc()
  }()
 
  select {
  case result := <-done:
    return result, nil
  case <-ctx.Done():
    return "Fail", ctx.Err()
  }
}
 
func main() {
  ctx, cancel := context.WithCancel(context.Background())
  go func() {
    time.Sleep(2 * time.Second)
    cancel()
  }()
  var wg sync.WaitGroup
  for i := 0; i < 5; i++ {
    wg.Add(1) // 기다릴 goroutine이 1개
 
    go func() {
      defer wg.Done()
      result, err := longFuncWithCtx(ctx)
      if err != nil {
        fmt.Println(err)
      }
      fmt.Println(result)
    }()
  }
  wg.Wait()  // 모든 goroutine이 완료될 때까지 기다림
}

읽어보기: https://lynlab.co.kr/blog/82

0개의 댓글