잠시만 기다려 주세요

     '대통령을 욕하는 것은 민주사회에서 주권을 가진 시민의 당연한 권리입니다. 대통령을 욕하는 것으로 주권자가 스트레스를 해소할 수 있다면 저는 기쁜 마음으로 들을 수 있습니다. - 노무현 -'
전체검색 :  
이번주 로또 및 연금번호 발생!!   |  HOME   |  여기는?   |  바다물때표   |  알림 (19)  |  여러가지 팁 (1095)  |  추천 및 재미 (163)  |  자료실 (28)  |  
시사, 이슈, 칼럼, 평론, 비평 (795)  |  끄적거림 (142)  |  문예 창작 (719)  |  바람 따라 (75)  |  시나리오 (760)  |  드라마 대본 (248)  |  
살인!


    golang

golang - golang 채널 channel, select, go 루틴 예제
이 름 : 바다아이   |   조회수 : 10778         짧은 주소 : https://www.bada-ie.com/su/?831591799905
서두에 가장 중요한 것 이야기 드립니다.
채널에 빈값이 오면 먹통 됩니다. 이 점은 생각하고 작업 하셔야 합니다.


채널(channel)은 두 고루틴이 서로 통신하고 실행흐름을 동기화하는 수단을 제공한다. 다음은 채널을 사용하는 예제 프로그램이다.

 
package main
 
import (
    "fmt"
    "time"
)
 
func pinger(c chan string) {
    for i := 0; ; i++ {
        c <- "ping"
    }
}
func printer(c chan string) {
    for {
        msg := <- c
        fmt.Println(msg)
        time.Sleep(time.Second * 1)
    }
}
func main() {
    var c chan string = make(chan string)
 
    go pinger(c)
    go printer(c)
 
    var input string
    fmt.Scanln(&input)
}


이 프로그램은 "ping"을 끊임없이 출력할 것이다(중단하려면 엔터 키를 친다). 
채널의 타입은 chan이라는 키워드 다음에 채널에 전달되는 것의 타입을 지정해서 나타낸다
(여기서는 문자열을 전달한다). <-(왼쪽 화살표) 연산자는 채널에 메시지를 전달하고 채널로부터 
메시지를 전달받는 데 사용한다. c <- "ping""ping"을 전달한다는 의미다. msg := <- c는 
메시지를 받아 그것을 msg에 저장한다는 의미다. fmt가 나오는 줄은 fmt.Println(<-c)라고도 작성할 수 있다. 
이 경우 앞의 줄을 제거해도 된다.
 

이 같은 식으로 채널을 이용하면 두 고루틴이 동기화된다. pinger가 메시지를 채널에 전송하려고 시도할 
경우 printer가 해당 메시지를 받을 준비가 될 때까지 대기할 것이다(이것은 블로킹으로 알려져 있다). 
이번에는 프로그램에 다른 전달자를 추가해서 무슨 일이 일어나는지 살펴보자. 다음 함수를 추가한다.
 
func ponger(c chan string) {
    for i := 0; ; i++ {
        c <- "pong"
    }
}


그리고 main 함수를 다음과 같이 수정한다.
 
func main() {
    var c chan string = make(chan string)
 
    go pinger(c)
    go ponger(c)
    go printer(c)
 
    var input string
    fmt.Scanln(&input)
}


이제 프로그램에서는 "ping""pong"이 번갈아 가면서 출력될 것이다.
 

채널 방향
 

채널 타입에 방향을 지정할 수 있는데, 그렇게 함으로써 채널이 보내거나 받기만 하도록 제한할 수 있다. 
예를 들어, pinger 함수의 서명을 다음과 같이 변경할 수 있다.
 
func pinger(c chan<- string)


이제 c는 보내기만 할 수 있다. c로부터 메시지를 받으려고 하면 컴파일 오류가 발생할 것이다. 
이와 비슷하게 출력기를 다음과 같이 변경할 수 있다.
 
func printer(c <-chan string)


이러한 제한이 없는 채널을 양방향 채널이라 한다. 양방향 채널은 전송 전용 채널이나 수신 전용 채널에 인자로 
받는 함수에 전달할 수 있지만 그 역은 성립하지 않는다.
 
Select
 

Go에는 switch와 비슷하게 동작하지만 채널에 대해서만 동작하는 select라는 특별한 구문이 있다.
 
func main() {
    c1 := make(chan string)
    c2 := make(chan string)
 
    go func() {
        for {
            c1 <- "from 1"
            time.Sleep(time.Second * 2)
        }
    }()
    go func() {
        for {
            c2 <- "from 2"
            time.Sleep(time.Second * 3)
        }
    }()
    go func() {
        for {
            select {
                case msg1 := <- c1:
                fmt.Println(msg1)
                case msg2 := <- c2:
                fmt.Println(msg2)
            }
        }
    }()
 
    var input string
    fmt.Scanln(&input)
}


이 프로그램은 "from 1"2초마다 출력하고 "from 2"3초마다 출력한다. select는 준비된 첫 번째 채널을 
골라 해당 채널로부터 메시지를 받는다(또는 해당 채널로 메시지를 보낸다). 하나 이상의 채널이 준비되면 
어느 채널로부터 메시지를 받을지 무작위로 선택한다. 준비된 채널이 없으면 사용 가능해질 때까지 문장 실행이 
차단된다.


select 구문은 제한 시간을 구현할 때 자주 사용된다.
 
select {
    case msg1 := <- c1:
        fmt.Println("Message 1", msg1)
    case msg2 := <- c2:
        fmt.Println("Message 2", msg2)
    case <- time.After(time.Second):
        fmt.Println("timeout")
}


time.After는 채널을 생성한 후 지정한 시간이 지나면 현재 시간을 해당 채널로 보낸다
(여기서는 현재 시간에 관심을 두지 않으므로 변수에 저장하지 않았다). 아울러 default 케이스를 지정할 수도 있다.
 
select {
    case msg1 := <- c1:
        fmt.Println("Message 1", msg1)
    case msg2 := <- c2:
        fmt.Println("Message 2", msg2)
    case <- time.After(time.Second):
        fmt.Println("timeout")
    default:
        fmt.Println("nothing ready")
}


default 케이스는 준비된 채널이 없을 경우 즉시 실행된다.

 
버퍼 채널
 

채널을 만들 때 make 함수에 두 번째 매개변수를 전달하는 것도 가능하다.
 
c := make(chan int, 1)


이렇게 하면 용량이 1인 버퍼 채널이 만들어진다. 보통 채널은 동기적으로 동작한다. 
즉, 채널의 양쪽이 다른 쪽이 준비될 때까지 기다린다. 버퍼 채널은 비동기적이다. 
즉, 메시지를 보내거나 받을 때 채널이 이미 꽉 차 있지 않는 이상 기다리지 않는다.



출처 : http://www.codingnuri.com/golang-book/10.html#section2
| |





      1 page / 6 page
번 호 카테고리 제 목 이름 조회수
180 golang golang ... 바다아이 119
179 golang golang , ... 바다아이 2700
178 golang golang , map . 바다아이 2088
177 golang Golang (, , data ) , ... 바다아이 2403
176 golang golang sort ... 바다아이 2788
175 golang golang html.EscapeString html.UnescapeString input value ... 바다아이 2708
174 golang golang go.mod go.sum . GOPATH SRC not module, 1.16 . 바다아이 6231
173 golang go 1.16 ... is not in GOROOT.. GOPATH .... . 바다아이 7385
172 golang , String Formatting 바다아이 8699
171 golang rand.Intn , random, , . 바다아이 8218
170 golang golang ... 바다아이 11976
169 golang golang gopath, goroot .. golang 바다아이 8948
168 golang golang ... Force download file example 바다아이 10973
167 golang golang , , cpu, memory, disk 바다아이 12036
166 golang golang , ... GOOS, GOARCH 바다아이 9695
165 golang golang checkbox ... 바다아이 9555
164 golang golang , , http .... 바다아이 9377
163 golang golang nil , nil , nil ... 바다아이 9458
162 golang 2 golang, go , .... golang .... 바다아이 12704
161 golang golang postgresql, mysql, mariadb ... ` Grave () .. .. 바다아이 10016
160 golang golang postgresql mysql, mariadb scan , null .. 바다아이 10077
159 golang golang , iconv 바다아이 12893
158 golang golang quote escape, unquote 바다아이 10319
157 golang golang , http errorLog , , ... 바다아이 10702
156 golang golang interface , 바다아이 9777
155 golang golang struct .... 바다아이 10502
154 golang golang map map , 바다아이 9985
153 golang golang map .... .... 바다아이 9309
152 golang golang slice copy 바다아이 9500
151 golang golang goto 바다아이 10692
| |









Copyright ⓒ 2001.12. bada-ie.com. All rights reserved.
이 사이트는 리눅스에서 firefox 기준으로 작성되었습니다. 기타 브라우저에서는 다르게 보일 수 있습니다.
[ Ubuntu + GoLang + PostgreSQL + Mariadb ]
서버위치 : 오라클 클라우드 춘천  실행시간 : 0.22686
to webmaster... gogo sea. gogo sea.