본문 바로가기
개발/Go

[Go] 기초 - 채널

by devhooney 2022. 8. 4.
728x90

1. Go 채널

- Go 채널은 그 채널을 통하여 데이터를 주고 받는 통로

- 채널은 make() 함수를 통해 미리 생성해야 한다.

- 채널 연산자 <- 을 통해 데이타를 보내고 받는다.

- 채널은 goroutine들 사이 데이터를 주고 받는데 사용

- 데이터를 받는 쪽이 준비될 때까지 채널에서 대기함으로써 별도의 lock을 걸지 않고 데이터를 동기화하는데 사용된다.

package main
 
func main() {
  // 정수형 채널을 생성한다 
  ch := make(chan int)
 
  go func() {
    ch <- 123   //채널에 123을 보낸다
  }()
 
  var i int
  i = <- ch  // 채널로부터 123을 받는다
  println(i)
}

- 채널이 데이터를 받기 위해 기다리는 코드 예시

package main
 
import "fmt"
 
func main() {
    done := make(chan bool)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(i)
        }
        done <- true
    }()
 
    // 위의 Go루틴이 끝날 때까지 대기
    <-done
}

 

2. Go 채널 버퍼링

- Go 채널 종류

(1) Unbuffered Channel

(2) Buffered Channel

- 버퍼 채널은 make(chan type, N) 함수를 통해 생성

- 버퍼 채널을 사용하지 않는다면 수신자가 없을 경우 에러가 발생한다.

package main
 
import "fmt"
 
func main() {
  c := make(chan int)
  c <- 1   //수신루틴이 없으므로 데드락 
  fmt.Println(<-c) //코멘트해도 데드락 (별도의 Go루틴없기 때문)
}
package main
 
import "fmt"
 
func main() {
    ch := make(chan int, 1)
 
    //수신자가 없더라도 보낼 수 있다.
    ch <- 101
 
    fmt.Println(<-ch)
}

 

728x90

 

3. 채널 파라미터

- 채널을 함수의 파라미터도 전달할 때, 일반적으로 송수신을 모두 하는 채널을 전달하지만, 특별히 해당 채널로 송신만 할 것인지 혹은 수신만할 것인지를 지정할 수도 있다. 

(1) 송신: p chan <- int

(2) 수신: p <-chan int

package main
 
import "fmt"
 
func main() {
    ch := make(chan string, 1)
    sendChan(ch)
    receiveChan(ch)
}
 
func sendChan(ch chan <- string) {
    ch <- "Data"
    // x := <-ch // 에러발생
}
 
func receiveChan(ch <-chan string) {
    data := <-ch
    fmt.Println(data)
}

 

4. 채널 닫기

- 채널을 오픈한 후 데이타를 송신한 후, close()함수를 사용하여 채널을 닫을 수 있다.

- 채널을 닫게 되면, 해당 채널로는 더이상 송신을 할 수 없지만, 채널이 닫힌 이후에도 계속 수신은 가능하다.

package main
 
func main() {
    ch := make(chan int, 2)
     
    // 채널에 송신
    ch <- 1
    ch <- 2
     
    // 채널을 닫는다
    close(ch)
 
    // 채널 수신
    println(<-ch)
    println(<-ch)
     
    if _, success := <-ch; !success {
        println("더이상 데이타 없음.")
    }
}

- 채널 수신에 사용되는 <- ch 은 두개의 리턴값을 갖는데, 첫째는 채널 메시지이고, 두번째는 수신이 제대로 되었는가를 나타낸다. 만약 채널이 닫혔다면, 두번째 리턴값은 false를 리턴한다.

 

- 난 Go 채널은 아예 사용해본 적이 없다. 동기/비동기 시 사용할 것 같은데, 사용해볼 기회가 있을 지 모르겠다.

728x90

'개발 > Go' 카테고리의 다른 글

[Go] 기초 - 루틴(goroutine)  (0) 2022.08.02
[Go] 기초 - defer&panic  (0) 2022.08.01
[Go] 기초 - Error  (0) 2022.07.31
[Go] 기초 - 인터페이스  (0) 2022.07.30
[Go] 기초 - 메소드  (1) 2022.07.27