Created
July 9, 2017 05:12
-
-
Save casualjim/eafdb60dce1efb0e64a7716738fd2b65 to your computer and use it in GitHub Desktop.
examples of golang context and channels
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() { | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment