Golang

[GoLang 시작하기 10] Channels

여니여니_ 2020. 4. 10. 00:50

Go 채널은 데이터를 주고 받는 통로이다.

 

Go 채널은 Go루틴들 사이의 데이터를 주고받는 데에 사용된다.

 

 

 

이 파이프라인을 통해서 메세지를 보내거나 받을 수 있다.

 

이 채널을 이용하여 동시성 구현 시 락 등을 이용하지 않고도 할 수 있다.

또 교착 상태나 경쟁 상태를 파악하기 쉽도록 지원된다. 

예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main
 
import (
  "fmt"
)
 
func main() {
  
  ch:=make(chan bool)
  nums:=[2]string{"one","two"}
 
  for _, n :=range nums{
    go isReady(n,ch)
  }
 
  fmt.Println(<-ch)
  fmt.Println(<-ch)
 
  //deadlock
  //fmt.Println(<-ch)
 
  //result:=<-ch
  //fmt.Println(result)
 
}
 
  func isReady(nums string,ch chan bool){
    fmt.Println(nums)
    ch<-true
  }
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

 

채널(ch)은 make 함수로 먼저 생성한다.

nums는 "one", "two" 두 개의 문자열이 담겨있는 배열이다.

 

nums 배열 요소들 수만큼 isReady를 고루틴으로 실행한다.

 

그러면 isReady 함수에서는 nums를 출력하고 채널로 bool형인 true를 main함수로 보낸다.

time.Sleep을 사용하지 않아도 고루틴이 실행된다. main에서는 채널에서 값을 받기를 기다리고 있기 때문이다.

 

그래서 프린트문으로 두 개의 값을 채널에서 받아준다.

 

다음과 같이 결과가 출력된다.

 

 

결과

결과에는 one two 순서로 출력되었지만 엄밀하게는 이 둘이 동시에 실행된 것이다. 

 

 

만약 프린트문을 하나 더 입력하면 deadlock이 걸리게 된다. 받을 값이 없어서 무한 대기상태가 되는 것 같다. 

 

 

 

 

 

 

Go 채널 버퍼링

  • Unbuffered Channel
  • Buffered Channel

위 예제에서는 Unbuffered Channel로 하나의 수신자가 데이터를 받을 때까지 송신자가 데이터를 보내는 채널에 묶여있다.

 

반면 Buffered Channel은 수신자가 받을 준비가 되어있지 않아도, 지정된 버퍼만큼 데이터를 보내고 계속 다른 일을 수행할 수 있다. 

 

버퍼 채널은 make(chan type, N) 으로 생성한다. 두번째 인수 N에는 사용할 버퍼 갯수를 넣는다. 

 

위 예제에서는 버퍼채널을 이용하지 않아서 오류가 발생했다. 

 

하지만 버퍼 채널을 사용하면 수신사자 없어도 에러가 발생하지 않는다. (이해 필요)

 

 

채널 파라미터

 

(작성중...)

 

Fast URL Checker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package main
 
import (
    "errors"
    "net/http"
 
)
 
type requestResult struct {
    url    string
    status string
}
 
var errRequestFailed = errors.New("Request failed")
 
func main() {
    results := make(map[string]string)
    c := make(chan requestResult)
    urls := []string{
        "https://www.facebook.com/",
        "https://www.instagram.com/",
        "https://www.airbnb.co.kr/",
        "https://www.google.com/",
        "https://github.com/",
        "https://www.amazon.com/",
        "https://www.reddit.com/",
    }
    for _, url := range urls {
        go hitURL(url, c)
 
    }
    for i := 0; i < len(urls); i++ {
    requestResult:=<-c
        results[requestResult.url] = requestResult.status
    }
}
func hitURL(url string, c chan<- requestResult) {
    resp, err := http.Get(url)
    status := "OK"
    if err != nil || resp.StatusCode >= 400 {
        status = "FAILED"
    } else {
        c <- requestResult{url: url, status: status}
 
    }
 
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

 

 

 

 

 

Reference

 

https://academy.nomadcoders.co/courses/769984/lectures/13962832

 

#3.7 FAST URLChecker

Write fast and beautiful code

academy.nomadcoders.co

 

 

http://golang.site/go/article/22-Go-%EC%B1%84%EB%84%90

 

예제로 배우는 Go 프로그래밍 - Go 채널

1. Go 채널 Go 채널은 그 채널을 통하여 데이타를 주고 받는 통로라 볼 수 있는데, 채널은 make() 함수를 통해 미리 생성되어야 하며, 채널 연산자 <- 을 통해 데이타를 보내고 받는다. 채널은 흔히 goroutine들 사이 데이타를 주고 받는데 사용되는데, 상대편이 준비될 때까지 채널에서 대기함으로써 별도의 lock을 걸지 않고 데이타를 동기화하는데 사용된다. 아래 예제는 정수형 채널을 생성하고, 한 goroutine 에서 그 채널에 123이란

golang.site