golang에서는 signal과 context를 이용하여 여러가지 제어를 할 수 있습니다.
먼저 signal 제어 방법을 알아볼건데 syscall.SIGINT 와 syscall.SIGTERM 을 알아보겠습니다.
syscall.SIGINT는 ctrl+c 에 대한 시그널이고 syscall.SIGTERM은 종료에 대한 시그널입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
cancelChan := make(chan os.Signal)
signal.Notify(cancelChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
fmt.Println("goroutine works!")
cancelChan <- syscall.SIGTERM
}()
sig := <-cancelChan
fmt.Println("main end", sig)
}
|
cs |
위 코드는 SIGTERM을 받은 예제입니다.
main function은 cancelChan으로부터 시그널이 올 때 까지 기다립니다. (즉, 시그널이 올 때 까지 fmt.Println이 실행되지 않습니다.)
go function이 "goroutine works! terminated"를 출력 후에 cancelChan으로 종료 시그널을 보내면 main function이 시그널을 받고 "main end"가 출력되고 프로그램이 종료됩니다. sig는 출력해보면 terminated라고 나옵니다. 종료 시그널을 의미합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
cancelChan := make(chan os.Signal)
signal.Notify(cancelChan, syscall.SIGINT, syscall.SIGTERM)
fmt.Println("waiting...")
sig := <-cancelChan
fmt.Println("main end", sig)
}
|
cs |
위 코드는 syscall.SIGINT에 대한 예제입니다. 코드를 실행하면 "waiting..."이 출력되고 더 이상 프로그램이 진행되지 않습니다.
sig := <-cancelChan 이 부분에서 멈춰있기 때문입니다. ctrl+c로 시그널을 주면 sig가 채널로부터 시그널을 받고 "main end interrupt"가 출력되고 종료 됩니다. interrupt는 syscall.SIGINT를 의미합니다.
이제 context와 타임아웃에 대해 알아보겠습니다.
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 | package main import ( "context" "fmt" "time" ) func Ping(sigChan chan struct{}){ fmt.Println("ping departed") time.Sleep(5*time.Second) sigChan <- struct{}{} fmt.Println("ping arrived") } func main() { rootCtx := context.Background() ctx, cancel := context.WithTimeout(rootCtx, 3*time.Second) defer cancel() ch := make(chan struct{}) go Ping(ch) select { case <- ctx.Done(): fmt.Println("terminated by timeout") case <- ch: fmt.Println("terminated by ping") } } | cs |
Ping함수는 보다시피 "ping departed"를 출력 후에 5초를 기다린 후 채널에 empty struct를 보내고 도착을 했다고 알립니다.
main함수를 보면 context.WithTimeout함수를 통해 3초 후에 알림이 오게 설정해놓았습니다.
그 후 go Ping(ch)을 통해 Ping함수는 고루틴으로 비동기 처리가 됩니다.
그리고 select문을 통해 context로 부터 알림을 받거나 Ping이 도착했을 때(채널에 struct{}{}를 보내므로) 알림을 받을 수 있습니다.
그런데 예제에서 Ping함수는 채널에 struct{}{}를 보낼 때까지 5초가 걸리고 timeout은 3초이므로 ctx.Done()함수에 의해 3초 후에 타임아웃 알림을 받고 "terminated by timeout"이 출력되고 프로그램은 종료됩니다.
'golang' 카테고리의 다른 글
Golang network#2 tcp buffer (0) | 2021.04.12 |
---|---|
golang cancel과 waitGroup 기초 (0) | 2021.04.11 |
Golang network TCP hello world 예제 (0) | 2021.04.05 |
golang에서 heap 사용하기 (0) | 2021.04.03 |
golang 인터페이스 활용 (0) | 2021.03.25 |