프로그래밍 검색 블로그

go context Timeout, deadline 본문

go

go context Timeout, deadline

코딩조무사 2018. 12. 22. 20:45

go 에서 기본으로 제공하고 있는 패키지 중에 다른 언어에는 기본적으로는 없는 유용한 패키지중의 하나가 context 이다


context.Background()


기본적으로 Background()를 제외한 다른 context들은 다른 context를 받는데

기능 상으로 해당 인자로 준 context를 상속 받는다고 생각하면 된다




context의 동작은 조건이 충족되지 않을 시에는 Err() 함수의 반환값을 통해서 알 수 있다

간단하게 nil이 아니면 에러




db 연결 부분은 제외하고 

context만 사용하는 간단한 예제

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()
	//cancel이 3초안에 실행되지 않으면 에러

	row := db.QueryRowContext(ctx, "select 87")

	if err := ctx.Err(); err != nil {
		fmt.Println("ERROR!", err)
		return
	}

	var a int
	row.Scan(&a)
	fmt.Println(a)
}

출력 87

db에 연결후 87의 값을 꺼내온다

쿼리에는 에러가 없어 ctx.Err()는 체크되지 않고 넘어간다



func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()
	//cancel이 3초안에 실행되지 않으면 에러

	row := db.QueryRowContext(ctx, "WAITFOR DELAY '0:0:5'")

	if err := ctx.Err(); err != nil {
		fmt.Println("ERROR!", err)
		return
	}

	var a int
	row.Scan(&a)
	fmt.Println(a)
}

출력 ERROR! context deadline exceeded

쿼리로 5초간 정지 했을 때는 3초안에 끝나지 못했으므로

에러가 발생한다






context를 인자로 받는 함수 생성


func sumWithContext(c context.Context, a, b int) (result int) { //받은 context를 바탕으로 새 context 생성 ctx, cancel := context.WithCancel(c) go func() { defer cancel() result = a + b }() //계산이 끝나거나 부모 context 에서 에러 검사 <-ctx.Done() return }

기능은 간단하게 a + b를 하는 함수이다

인자로 받는 함수 생성 시에는 어떤 context가 들어올지 알 수 없으므로

일단 주어진 context를 바탕으로 cancel이 가능한 context를 생성한다


그 후 다른 go루틴을 통해서 계산을 진행한다

이때 a + b의 작업이 오래 걸린다고 해서 해당 go루틴이 종료되진 않지만

sumWithContext를 호출한 함수는 제한을 건 조건 안에 응답을 받을 수 있다






'go' 카테고리의 다른 글

go AES 암호화  (0) 2018.05.22
go reflect 호출  (0) 2018.05.15
go 파일 압축  (0) 2018.05.12
Comments