summaryrefslogtreecommitdiff
path: root/doc/articles
diff options
context:
space:
mode:
authorFrancisco Souza <franciscossouza@gmail.com>2012-03-14 13:03:11 +1100
committerFrancisco Souza <franciscossouza@gmail.com>2012-03-14 13:03:11 +1100
commit3e6c856dab8ec5b27089d226205799c1d44da7cc (patch)
treec50839531d637db8a0e0a7e0a4a928702bf32cc2 /doc/articles
parent8d937cffa9645f184654f82ec9f55a4af3928602 (diff)
downloadgo-3e6c856dab8ec5b27089d226205799c1d44da7cc.tar.gz
doc: add Go Concurrency Patterns: Timing out, moving on article
Originally published on The Go Programming Language Blog, September 23, 2010. http://blog.golang.org/2010/09/go-concurrency-patterns-timing-out-and.html Update issue 2547. R=golang-dev, adg CC=golang-dev http://codereview.appspot.com/5815044 Committer: Andrew Gerrand <adg@golang.org>
Diffstat (limited to 'doc/articles')
-rw-r--r--doc/articles/go_concurrency_patterns_timing_out_moving_on.html79
1 files changed, 79 insertions, 0 deletions
diff --git a/doc/articles/go_concurrency_patterns_timing_out_moving_on.html b/doc/articles/go_concurrency_patterns_timing_out_moving_on.html
new file mode 100644
index 000000000..63c8cd59e
--- /dev/null
+++ b/doc/articles/go_concurrency_patterns_timing_out_moving_on.html
@@ -0,0 +1,79 @@
+<!--{
+"Title": "Go Concurrency Patterns: Timing out, moving on",
+"Template": true
+}-->
+
+<p>
+Concurrent programming has its own idioms. A good example is timeouts. Although
+Go's channels do not support them directly, they are easy to implement. Say we
+want to receive from the channel <code>ch</code>, but want to wait at most one
+second for the value to arrive. We would start by creating a signalling channel
+and launching a goroutine that sleeps before sending on the channel:
+</p>
+
+{{code "/doc/progs/timeout1.go" `/timeout :=/` `/STOP/`}}
+
+<p>
+We can then use a <code>select</code> statement to receive from either
+<code>ch</code> or <code>timeout</code>. If nothing arrives on <code>ch</code>
+after one second, the timeout case is selected and the attempt to read from
+<cde>ch</cde> is abandoned.
+</p>
+
+{{code "/doc/progs/timeout1.go" `/select {/` `/STOP/`}}
+
+<p>
+The <code>timeout</code> channel is buffered with space for 1 value, allowing
+the timeout goroutine to send to the channel and then exit. The goroutine
+doesn't know (or care) whether the value is received. This means the goroutine
+won't hang around forever if the <code>ch</code> receive happens before the
+timeout is reached. The <code>timeout</code> channel will eventually be
+deallocated by the garbage collector.
+</p>
+
+<p>
+(In this example we used <code>time.Sleep</code> to demonstrate the mechanics
+of goroutines and channels. In real programs you should use <code>
+<a href="/pkg/time/#After">time.After</a></code>, a function that returns
+a channel and sends on that channel after the specified duration.)
+</p>
+
+<p>
+Let's look at another variation of this pattern. In this example we have a
+program that reads from multiple replicated databases simultaneously. The
+program needs only one of the answers, and it should accept the answer that
+arrives first.
+</p>
+
+<p>
+The function <code>Query</code> takes a slice of database connections and a
+<code>query</code> string. It queries each of the databases in parallel and
+returns the first response it receives:
+</p>
+
+{{code "/doc/progs/timeout2.go" `/func Query/` `/STOP/`}}
+
+<p>
+In this example, the closure does a non-blocking send, which it achieves by
+using the send operation in <code>select</code> statement with a
+<code>default</code> case. If the send cannot go through immediately the
+default case will be selected. Making the send non-blocking guarantees that
+none of the goroutines launched in the loop will hang around. However, if the
+result arrives before the main function has made it to the receive, the send
+could fail since no one is ready.
+</p>
+
+<p>
+This problem is a textbook of example of what is known as a
+<a href="https://en.wikipedia.org/wiki/Race_condition">race condition</a>, but
+the fix is trivial. We just make sure to buffer the channel <code>ch</code> (by
+adding the buffer length as the second argument to <a href="/pkg/builtin/#make">make</a>),
+guaranteeing that the first send has a place to put the value. This ensures the
+send will always succeed, and the first value to arrive will be retrieved
+regardless of the order of execution.
+</p>
+
+<p>
+These two examples demonstrate the simplicity with which Go can express complex
+interactions between goroutines.
+</p>