diff --git a/doc/Makefile b/doc/Makefile index b275dfe4dd..687f1b1eb5 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -7,6 +7,8 @@ RAWHTML=\ articles/error_handling.rawhtml\ articles/slices_usage_and_internals.rawhtml\ articles/laws_of_reflection.rawhtml\ + articles/c_go_cgo.rawhtml\ + articles/go_concurrency_patterns_timing_out_moving_on.rawhtml\ articles/image_draw.rawhtml\ effective_go.rawhtml\ go1.rawhtml\ @@ -17,4 +19,4 @@ all: $(RAWHTML) godoc -url /doc/$< >$@ clean: - rm -f $(RAWHTML) + rm -f $(RAWHTML) 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 0000000000..63c8cd59e8 --- /dev/null +++ b/doc/articles/go_concurrency_patterns_timing_out_moving_on.html @@ -0,0 +1,79 @@ + + +
+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 ch, 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:
+
+We can then use a select statement to receive from either
+ch or timeout. If nothing arrives on ch
+after one second, the timeout case is selected and the attempt to read from
+
+The timeout 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 ch receive happens before the
+timeout is reached. The timeout channel will eventually be
+deallocated by the garbage collector.
+
+(In this example we used time.Sleep to demonstrate the mechanics
+of goroutines and channels. In real programs you should use
+time.After, a function that returns
+a channel and sends on that channel after the specified duration.)
+
+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. +
+ +
+The function Query takes a slice of database connections and a
+query string. It queries each of the databases in parallel and
+returns the first response it receives:
+
+In this example, the closure does a non-blocking send, which it achieves by
+using the send operation in select statement with a
+default 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.
+
+This problem is a textbook of example of what is known as a
+race condition, but
+the fix is trivial. We just make sure to buffer the channel ch (by
+adding the buffer length as the second argument to make),
+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.
+
+These two examples demonstrate the simplicity with which Go can express complex +interactions between goroutines. +
diff --git a/doc/docs.html b/doc/docs.html index cc637b038a..39e4573eb6 100644 --- a/doc/docs.html +++ b/doc/docs.html @@ -105,7 +105,7 @@ Guided tours of Go programs.