1 분 소요

Golang Context Sample

Golang Context

WithCancel

package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var wg sync.WaitGroup

func main() {
	// 웨이팅 그룹은 메인에서 서부 루틴이 졸요하는 시점까지 기다림.
	wg.Add(1)

	// context 생성.
	ctx, cancel := context.WithCancel(context.Background())

	// 무한 루프 시작...
	go PrintTick(ctx)

	// 5초 후에 cancel 실행.
	time.Sleep(5 * time.Second)
	cancel()

	wg.Wait()
}

func PrintTick(ctx context.Context) {
	tick := time.Tick(time.Second)

	for {
		select {
		case <-ctx.Done():
			fmt.Println("Done:", ctx.Err())
			// waitGroup을 이곳에서 종료...
			wg.Done()
			return
		case <-tick:
			fmt.Println("tick")
		}
	}
}

WithDeadline

package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var wg sync.WaitGroup

func main() {
	wg.Add(1)

	// 현제시간에 5초을 추가해서 데드라인으로 설정.
	d := time.Now().Add(5 * time.Second)
	ctx, cancel := context.WithDeadline(context.Background(), d)

	go PrintTick(ctx)

	time.Sleep(time.Second * 5)
	cancel()

	wg.Wait()
}

func PrintTick(ctx context.Context) {
	tick := time.Tick(time.Second)
	for {
		select {
		case <-ctx.Done():
			fmt.Println("Done:", ctx.Err())
			// waitGroup을 이곳에서 종료...
			wg.Done()
			return
		case <-tick:
			fmt.Println("tick")
		}
	}
}

WithTimeout

package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var wg sync.WaitGroup

func main() {
	wg.Add(1)

	// 3초후 종료...
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)

	go PrintTick(ctx)

	// 5초후 cancel이 예정되어 있어도 영향을 주지 않음.
	time.Sleep(time.Second * 5)
	cancel()

	wg.Wait()
}

func PrintTick(ctx context.Context) {
	tick := time.Tick(time.Second)
	for {
		select {
		case <-ctx.Done():
			fmt.Println("Done:", ctx.Err())
			wg.Done()
			return
		case <-tick:
			fmt.Println("tick")
		}
	}
}

WithValue

package main

import (
	"context"
	"fmt"
	"sync"
)

var wg sync.WaitGroup

func main() {
	wg.Add(1)

	ctx := context.WithValue(context.Background(), "v", 3)

	go square(ctx)

	wg.Wait()
}

// 데이터 전달을 위해 사용된다.
func square(ctx context.Context) {
	if v := ctx.Value("v"); v != nil {
		n := v.(int)
		fmt.Println("Square:", n*n)
	}
	wg.Done()
}

Wrapping

package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var wg sync.WaitGroup

func main() {
	wg.Add(1)

	// multi value을 전달하기 위해서는 wrapping이 사용 된다.
	ctx, cancel := context.WithCancel(context.Background())
	ctx = context.WithValue(ctx, "s", 2)
	ctx = context.WithValue(ctx, "t", 3)

	go PrintTick(ctx)

	// 5초후 종료...
	time.Sleep(5 * time.Second)
	cancel()

	wg.Wait()
}

func PrintTick(ctx context.Context) {
	tick := time.Tick(time.Second)

	// 어떤 값을 받을지는 선택하면 된다. "s", "t"...
	// any -> int 변경하는 부분 참조...
	if v := ctx.Value("s"); v != nil {
		s := v.(int)
		tick = time.Tick(time.Duration(s) * time.Second)
	}

	for {
		select {
		case <-ctx.Done():
			fmt.Println("Done:", ctx.Err())
			wg.Done()
			return
		case <-tick:
			fmt.Println("tick")
		}
	}
}

댓글남기기