본문 바로가기
프로그래밍/golang

ultimate go-(12) context사용

by 나도한강뷰 2023. 1. 31.

context

  • context패키지를 이용해보자
  • cancellation과 deadline을 지원한다.
package main
import (
    "context"
    "fmt"
)
type user struct {  // context내에 값을 저장하기 위해 만든 구조체
    name string
}
type userKey int // user값에 대한 키 타입
func main()
    u := user {         //user값 생성
        name: "Hoanh",
    }

    const uk userKey = 0    //key값 0으로 생성

    ctx := context.WithValue(context.Background(), uk, &u)  // value를 넣기위한 함수 withValue, 키값과 키값으로 찾을 값의 주소값을 저장한다.
                                                            // context는 파이프라인을 위해 고안된 형태이므로 그전값을 받는게 필요하다
                                                            // 그게 backgroud이다.
    if u, ok := ctx.Value(uk).(*user); ok {     // uk를 쓰고 타입단언을 통해서 값을 받을 수 있다.
        fmt.Println("User", u.name)
    }
    if _, ok := ctx.Value(0).(*user); !ok {     //값은 0이지만, userKey type이 아니기때문에  값을 받을 수 없다.
                                                //그렇기때문에 사용자 정의 키값을 사용하는게 중요하다.
        fmt.Println("User Not Found")
    }
User Hoanh
User Not Found

with cancel

package main
import (
    "context"
    "fmt"
    "time"
)
func main() {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    go func() {
        time.Sleep(50 * time.Millisecond)
        cancel()
    }()

    select {
    case <-time.After(100 * time.Millisecond):
        fmt.Println("moving on")
    case <-ctx.Done():
        fmt.Println("work complete")
    }
}
work complete

with deadline

package main
import (
    "context"
    "fmt"
    "time"
)
type data struct {
    UserID string
}
func main() {
    deadline := time.Now().Add(150 * time.Millisecond) //deadline 설정
    ctx, cancel := context.WithDeadline(context.Background(), deadline) //deadline입력
                                                                        //비슷한 함수로 withTimeOut이 있다.
    defer cancel()

   ch := make(chan data, 1)

    go func() {
        time.Sleep(200 * time.Millisecond)
        ch <- data{"123"}                   //작업이 끝났음을 알린다.
    }()

    select {
    case d := <-ch:                         //
        fmt.Println("work complete", d)
    case <-ctx.Done():                      //timeout을 감지한다.
        fmt.Println("work cancelled")
    }
}
work cancelled