Updated:

2 minute read

개요

  • 고루틴(goroutine)
    • 쓰레드와 유사
    • 쓰레드보다 적은 메모리 사용
    • go 키워드 사용
  • 채널(channel)
    • 고루틴간의 데이터 송수신 및 동기화
    • chan 타입 사용
    • 버퍼링(buffering)
      • unbuffered channel
        • channel := make(chan int)
        • 수신하기전까지 송신 채널이 차단
      • buffered channel
        • channel := make(chan bool, 10)
        • 지정된 크기의 버퍼가 다 채워지기 전까지 송신 채널이 차단되지 않음
    • 송신
      • channel <- 1
    • 수신
      • <-channel
      • 송신될 때까지 차단
    • 방향(directions)
      • 기본적으로는 양뱡향
      • make 시 단방향 채널 생성 가능
      • 파라미터를 통해 양뱡향 채널을 단방향 채널로 변환 가능
      • 단방향 채널을 양뱡향 채널 파라미터로 전달하거나 송(수)신 채널을 수(송)신 채널 파라미터로 넘기면 컴파일 에러 발생
      • 송신
        • chan <- int
      • 수신
        • <-chan int
    • 닫기
      • close 함수 사용
      • 호출 이후 송신은 불가능, 수신은 가능
      • 채널이 닫힐 떄까지 수신하는 방법
        • 방법 1
           for {
             if data, ok := <-channel; ok {
                 log.Println("receive data : ", data)
             } else {
                 break
             }
           }
          
        • 방법 2
           for data := range channel {
               log.Println("receive data : ", data)
           }
          
    • select
      • n개의 채널을 수신 대기
      • switch문과 유사하게 case/default문 등을 사용
      • 준비된 채널이 없을 경우 default문이 없으면 대기, 있으면 default문 수행
  • 대기 그룹(WaitGroup)
    • 고루틴들의 대기에 사용
    • Add
      • 대기 수 증가
    • Done
      • 대기 수 감소
    • Wait
      • 대기 수가 0이 될 때까지 대기


예제

  • 코드
     package main
        
     import (
     	"log"
     	"sync"
     	"time"
     )
        
     func bufferingJob(channel chan int, dataCount int) {
     	wgSend := sync.WaitGroup{}
        
     	for i := 0; i < dataCount; i++ {
     		wgSend.Add(1)
     		go func(channel chan int, wg *sync.WaitGroup, data int) {
     			defer wg.Done()
        
     			channel <- data
     			log.Println("send data : ", data)
     		}(channel, &wgSend, i)
     	}
        
     	time.Sleep(time.Second)
        
     	wgReceive := sync.WaitGroup{}
     	wgReceive.Add(1)
     	go func(channel chan int, wg *sync.WaitGroup) {
     		defer wg.Done()
        
     		/*
     			for {
     				if data, ok := <-channel; ok {
     					log.Println("receive data : ", data)
     				} else {
     					break
     				}
     			}
     		*/
        
     		for data := range channel {
     			log.Println("receive data : ", data)
     		}
     	}(channel, &wgReceive)
        
     	wgSend.Wait()
     	close(channel)
     	wgReceive.Wait()
     }
        
     func unbufferedChannelTest() {
     	channel := make(chan int)
        
     	bufferingJob(channel, 3)
     }
        
     func bufferedChannelTest() {
     	channel := make(chan int, 3)
        
     	bufferingJob(channel, 5)
     }
        
     func directionsTest() {
     	channel := make(chan int, 1)
        
     	func(channel chan<- int) { channel <- 1 }(channel)
        
     	func(channel <-chan int) { println(<-channel) }(channel)
     }
        
     func selectTest() {
     	channel1 := make(chan int)
     	channel2 := make(chan bool)
        
     	go func() {
     		count := 0
     	EXIT:
     		for {
     			select {
     			case data := <-channel1:
     				println(data)
     			case data := <-channel2:
     				println(data)
     				break EXIT
     			default:
     				count++
     			}
     		}
        
     		println("default call : ", count)
     	}()
        
     	channel1 <- 1
     	channel1 <- 2
        
     	channel2 <- true
     }
        
     func main() {
     	unbufferedChannelTest()
        
     	println("------")
        
     	bufferedChannelTest()
        
     	println("------")
        
     	directionsTest()
        
     	println("------")
        
     	selectTest()
     }
    
  • 실행 결과
     2022/12/14 02:16:27 receive data :  0
     2022/12/14 02:16:27 receive data :  1
     2022/12/14 02:16:27 receive data :  2
     2022/12/14 02:16:27 send data :  2
     2022/12/14 02:16:27 send data :  0
     2022/12/14 02:16:27 send data :  1
     ------
     2022/12/14 02:16:27 send data :  4
     2022/12/14 02:16:27 send data :  0
     2022/12/14 02:16:27 send data :  1
     2022/12/14 02:16:28 send data :  2
     2022/12/14 02:16:28 receive data :  4
     2022/12/14 02:16:28 receive data :  0
     2022/12/14 02:16:28 receive data :  1
     2022/12/14 02:16:28 receive data :  2
     2022/12/14 02:16:28 receive data :  3
     2022/12/14 02:16:28 send data :  3
     ------
     1
     ------
     1
     2
     true
     default call :  256