goroutine 각양각색

8448 단어 Gogoroutine

제목


반복적으로 고루틴과 장난치다...

관련 기사 색인

  • goroutine 각양각색
  • goroutine 각양각색
  • 각양각색
  • 개발 환경


    # OS

    $ cat /etc/os-release 
    NAME="Ubuntu"
    VERSION="18.04.1 LTS (Bionic Beaver)"
    

    # 언어

    $ go version
    go version go1.11.4 linux/amd64
    

    실천


    OS 신호 수신, 여러 goroutine 중지


    여러 개의goroutine를 생성하고 실행하며 메인 goroutine는 OS 신호를 기다립니다.
    OS 신호를 수신할 때 실행 중인 모든 goroutine에 대해 정지 알림을 합니다.

    ■ OS 신호 수신자


    OS 신호를 받은 후 미리 수신된goroutine 정지용 알림 취소 함수notifyToStop를 실행합니다.
    이로써 사전에 실행된 여러 개의 Goroutine에'정지'를 통지합니다.
    수신된 OS 신호는 SIGINT 뿐입니다.(아무튼Ctrl+C로 키보드를 삽입한 사례를 보면 된다)
    [signal_receiver.go]
    type signalReceiver struct {
        ch           chan os.Signal // OSからのシグナル受信用チャネル
        notifyToStop func()         // OSからのシグナル受信時の他チャネルへの停止通知関数
    }
    
    func newSignalReceiver(notifyToStop func()) *signalReceiver {
        ch := make(chan os.Signal, 1)
        signal.Notify(ch, syscall.SIGINT)
        return &signalReceiver{
            ch:           ch,
            notifyToStop: notifyToStop,
        }
    }
    
    func (r *signalReceiver) wait() {
        <-r.ch
        fmt.Println("received signal !!!!!")
        r.notifyToStop()
    }
    

    ■ goroutine 실행 대상의 함수


    1초 간격으로 name 받은 함수를 계속 출력하기만 하면 됩니다.
    컨텍스트에서 종료 알림을 수신하면 처리가 종료됩니다.
    [main.go]
    // 1秒おきにnameを出力
    func echoLangName(ctx context.Context, name string) {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("***** stop echo " + strings.TrimSpace(name) + " *****")
                return
            default:
                fmt.Println(name)
                time.Sleep(1 * time.Second)
                continue
            }
        }
    }
    

    ■ main 함수


    5개 언어(적당한 선택)의goroutine를 생성한 후 주goroutine에서 OS 신호가 수신되기를 기다립니다.
    [main.go]
    func main() {
        // エコー対象の言語は5つ
        langs := []string{
            "Go",
            "    Java",
            "         C++",
            "              PHP",
            "                  Ruby"}
    
        ctx, cancelFunc := context.WithCancel(context.Background())
    
        for _, lang := range langs {
            go echoLangName(ctx, lang)
        }
    
        rec := newSignalReceiver(cancelFunc)
        rec.wait()
    
        time.Sleep(3 * time.Second) // 本来はWaitGroup使う
    }
    

    실행


    시작 2초 정도 후Ctrl+C 중단됩니다.
    따라서 OS 신호로부터 중단된 wait() 함수를 기다리면서 "received signal !!!!!"를 출력합니다.
    이후 미리 준비한 알림 취소 함수의 실행으로main 이외의 각goroutine가 정지됩니다.

    참고 자료


    이번에 게재된 동영상 GIF는 참조↓.사용하기 편하고 GIF도 가볍습니다.
    https://qiita.com/syohex/items/d7076828c54114eb7657

    좋은 웹페이지 즐겨찾기