Skip to content

Instantly share code, notes, and snippets.

@neumachen
Forked from casualjim/channel_example_test.go
Created July 21, 2019 16:51
Show Gist options
  • Save neumachen/fa9182147cd5d7ccbe5f8e1ccff436b3 to your computer and use it in GitHub Desktop.
Save neumachen/fa9182147cd5d7ccbe5f8e1ccff436b3 to your computer and use it in GitHub Desktop.

Revisions

  1. @casualjim casualjim created this gist Jul 9, 2017.
    134 changes: 134 additions & 0 deletions channel_example_test.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,134 @@
    package channel

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

    func ExampleUnbufferedSend() {
    c1 := make(chan string)

    wg := &sync.WaitGroup{}
    wg.Add(1)
    go func() {
    defer wg.Done()
    select {
    case c1 <- "got message":
    return
    case <-time.After(20 * time.Millisecond):
    return
    }
    }()

    wg.Wait() // explicitly defer until goroutine is done
    select {
    case msg := <-c1:
    fmt.Println(msg)
    default:
    fmt.Println("no message")
    }

    // Output: no message
    }

    func ExampleBufferedSend() {
    c1 := make(chan string, 1)

    wg := &sync.WaitGroup{}
    wg.Add(1)
    go func() {
    defer wg.Done()
    select {
    case c1 <- "got message":
    return
    case <-time.After(20 * time.Millisecond):
    return
    }
    }()

    wg.Wait() // explicitly defer until goroutine is done
    select {
    case msg := <-c1:
    fmt.Println(msg)
    default:
    fmt.Println("no message")
    }

    // Output: got message
    }

    func ExampleNilChannelSend() {
    var c1 chan string

    wg := &sync.WaitGroup{}
    wg.Add(1)

    result := make(chan string, 1)
    go func() {
    defer wg.Done()
    select {
    case c1 <- "got message":
    return
    case <-time.After(20 * time.Millisecond):
    result <- "nil channel send blocks"
    return
    }
    }()

    wg.Wait()
    select {
    case msg := <-c1:
    fmt.Println(msg)
    case msg := <-result:
    fmt.Println(msg)
    }

    // Output: nil channel send blocks
    }

    func ExampleClosedChannelSend() {
    c1 := make(chan string, 1)
    close(c1)

    // using a channel so we know when its done
    result := make(chan string)
    go func() {
    defer func() {
    if r := recover(); r != nil { // handling the panic of the send on closed channel that will happen below
    result <- r.(error).Error()
    return
    }
    result <- "timed out"
    }()
    select {
    case c1 <- "got message": // closed channels panic when you send on them
    return
    case <-time.After(20 * time.Millisecond):
    return
    }
    }()

    fmt.Println(<-result)

    // Output: send on closed channel
    }

    func ExampleCloseNilChannel() {
    defer func() {
    if r := recover(); r != nil { // handling the panic of the close of nil channel
    fmt.Println(r)
    return
    }
    fmt.Println("timed out")
    }()

    var c1 chan string
    close(c1) // close of nil channel panics

    // Output: close of nil channel
    }

    func ExampleWaitArbitraryNumberOfChannels() {

    }
    94 changes: 94 additions & 0 deletions context_example_test.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,94 @@
    package tasks

    import (
    "context"
    "log"
    "sync"
    "time"
    )

    type ctxExamplesKey string

    func ExampleSimpleContext() {
    wg := &sync.WaitGroup{}

    start := time.Now()
    estop := make(chan time.Time, 1)
    ectx := context.Background()

    ctx, cancel := context.WithCancel(ectx) // with cancel needed to be able to do
    stop1 := make(chan time.Time, 1)
    wg.Add(1)
    go func() {
    defer wg.Done()
    for {
    select {
    case <-ctx.Done():
    log.Println("done ctx")
    stop1 <- time.Now()
    return
    case <-time.After(1 * time.Second):
    log.Println("iteration for ctx")
    }
    }
    }()

    wg.Add(1)
    go func() {
    defer func() {
    estop <- time.Now()
    wg.Done()
    }()
    for {
    select {
    case <-ectx.Done():
    log.Println("done ectx, should not occur")
    return
    case <-time.After(1 * time.Second):
    log.Println("iteration for ectx because nil channel blocks forever")
    select {
    case <-ctx.Done():
    log.Println("done ectx through escaping with ctx.Done()")
    return
    default:
    }
    }
    }
    }()

    ctx2 := context.WithValue(ctx, ctxExamplesKey("ctx2val"), 0)
    stop2 := make(chan time.Time, 1)
    wg.Add(1)
    go func() {
    defer wg.Done()
    for {
    select {
    case <-ctx2.Done():
    log.Println("done ctx2")
    stop2 <- time.Now()
    return
    default:
    time.Sleep(2 * time.Second)
    log.Println("iteration for ctx2")
    ctx2 = context.WithValue(ctx2, ctxExamplesKey("ctx2val"), ctx2.Value(ctxExamplesKey("ctx2val")).(int)+1)
    }
    }
    }()

    wg.Add(1)
    go func() {
    defer wg.Done()
    <-time.After(9 * time.Second)
    cancel()
    log.Println("iteration for ctx")
    }()

    wg.Wait()

    log.Printf("ctx2val (ctx): %v", ctx.Value(ctxExamplesKey("ctx2val")))
    log.Printf("ctx2val (ctx2): %d", ctx2.Value(ctxExamplesKey("ctx2val")))
    log.Println("took", time.Now().Sub(start))
    log.Printf("ectx took: %v", (<-estop).Sub(start))
    log.Printf("ctx took: %v", (<-stop1).Sub(start))
    log.Printf("ctx2 took: %v", (<-stop2).Sub(start))
    }