| <codewalk title="Share Memory By Communicating"> | 
 |  | 
 | <step title="Introduction" src="doc/codewalk/urlpoll.go"> | 
 | Go's approach to concurrency differs from the traditional use of | 
 | threads and shared memory. Philosophically, it can be summarized: | 
 | <br/><br/> | 
 | <i>Don't communicate by sharing memory; share memory by communicating.</i> | 
 | <br/><br/> | 
 | Channels allow you to pass references to data structures between goroutines. | 
 | If you consider this as passing around ownership of the data (the ability to | 
 | read and write it), they become a powerful and expressive synchronization  | 
 | mechanism. | 
 | <br/><br/> | 
 | In this codewalk we will look at a simple program that polls a list of | 
 | URLs, checking their HTTP response codes and periodically printing their state. | 
 | </step> | 
 |  | 
 | <step title="State type" src="doc/codewalk/urlpoll.go:/State/,/}/"> | 
 | The State type represents the state of a URL. | 
 | <br/><br/> | 
 | The Pollers send State values to the StateMonitor, | 
 | which maintains a map of the current state of each URL. | 
 | </step> | 
 |  | 
 | <step title="Resource type" src="doc/codewalk/urlpoll.go:/Resource/,/}/"> | 
 | A Resource represents the state of a URL to be polled: the URL itself | 
 | and the number of errors encountered since the last successful poll. | 
 | <br/><br/> | 
 | When the program starts, it allocates one Resource for each URL. | 
 | The main goroutine and the Poller goroutines send the Resources to | 
 | each other on channels. | 
 | </step> | 
 |  | 
 | <step title="Poller function" src="doc/codewalk/urlpoll.go:/func Poller/,/\n}/"> | 
 | Each Poller receives Resource pointers from an input channel. | 
 | In this program, the convention is that sending a Resource pointer on | 
 | a channel passes ownership of the underlying data from the sender | 
 | to the receiver.  Because of this convention, we know that | 
 | no two goroutines will access this Resource at the same time. | 
 | This means we don't have to worry about locking to prevent concurrent  | 
 | access to these data structures. | 
 | <br/><br/> | 
 | The Poller processes the Resource by calling its Poll method. | 
 | <br/><br/> | 
 | It sends a State value to the status channel, to inform the StateMonitor | 
 | of the result of the Poll. | 
 | <br/><br/> | 
 | Finally, it sends the Resource pointer to the out channel. This can be | 
 | interpreted as the Poller saying "I'm done with this Resource" and  | 
 | returning ownership of it to the main goroutine.  | 
 | <br/><br/> | 
 | Several goroutines run Pollers, processing Resources in parallel. | 
 | </step> | 
 |  | 
 | <step title="The Poll method" src="doc/codewalk/urlpoll.go:/Poll executes/,/\n}/"> | 
 | The Poll method (of the Resource type) performs an HTTP HEAD request | 
 | for the Resource's URL and returns the HTTP response's status code. | 
 | If an error occurs, Poll logs the message to standard error and returns the  | 
 | error string instead. | 
 | </step> | 
 |  | 
 | <step title="main function" src="doc/codewalk/urlpoll.go:/func main/,/\n}/"> | 
 | The main function starts the Poller and StateMonitor goroutines | 
 | and then loops passing completed Resources back to the pending | 
 | channel after appropriate delays. | 
 | </step> | 
 |  | 
 | <step title="Creating channels" src="doc/codewalk/urlpoll.go:/Create our/,/complete/"> | 
 | First, main makes two channels of *Resource, pending and complete. | 
 | <br/><br/> | 
 | Inside main, a new goroutine sends one Resource per URL to pending | 
 | and the main goroutine receives completed Resources from complete. | 
 | <br/><br/> | 
 | The pending and complete channels are passed to each of the Poller | 
 | goroutines, within which they are known as in and out.  | 
 | </step> | 
 |  | 
 | <step title="Initializing StateMonitor" src="doc/codewalk/urlpoll.go:/Launch the StateMonitor/,/statusInterval/"> | 
 | StateMonitor will initialize and launch a goroutine that stores the state  | 
 | of each Resource. We will look at this function in detail later.  | 
 | <br/><br/> | 
 | For now, the important thing to note is that it returns a channel of State,  | 
 | which is saved as status and passed to the Poller goroutines. | 
 | </step> | 
 |  | 
 | <step title="Launching Poller goroutines" src="doc/codewalk/urlpoll.go:/Launch some Poller/,/}/"> | 
 | Now that it has the necessary channels, main launches a number of | 
 | Poller goroutines, passing the channels as arguments. | 
 | The channels provide the means of communication between the main, Poller, and  | 
 | StateMonitor goroutines. | 
 | </step> | 
 |  | 
 | <step title="Send Resources to pending" src="doc/codewalk/urlpoll.go:/Send some Resources/,/}\(\)/"> | 
 | To add the initial work to the system, main starts a new goroutine | 
 | that allocates and sends one Resource per URL to pending. | 
 | <br/><br/> | 
 | The new goroutine is necessary because unbuffered channel sends and | 
 | receives are synchronous. That means these channel sends will block until | 
 | the Pollers are ready to read from pending. | 
 | <br/><br/> | 
 | Were these sends performed in the main goroutine with fewer Pollers than  | 
 | channel sends, the program would reach a deadlock situation, because | 
 | main would not yet be receiving from complete. | 
 | <br/><br/> | 
 | Exercise for the reader: modify this part of the program to read a list of | 
 | URLs from a file. (You may want to move this goroutine into its own | 
 | named function.) | 
 | </step> | 
 |  | 
 | <step title="Main Event Loop" src="doc/codewalk/urlpoll.go:/range complete/,/\n	}/"> | 
 | When a Poller is done with a Resource, it sends it on the complete channel. | 
 | This loop receives those Resource pointers from complete. | 
 | For each received Resource, it starts a new goroutine calling | 
 | the Resource's Sleep method.  Using a new goroutine for each | 
 | ensures that the sleeps can happen in parallel. | 
 | <br/><br/> | 
 | Note that any single Resource pointer may only be sent on either pending or | 
 | complete at any one time. This ensures that a Resource is either being | 
 | handled by a Poller goroutine or sleeping, but never both simultaneously.   | 
 | In this way, we share our Resource data by communicating. | 
 | </step> | 
 |  | 
 | <step title="The Sleep method" src="doc/codewalk/urlpoll.go:/Sleep/,/\n}/"> | 
 | Sleep calls time.Sleep to pause before sending the Resource to done. | 
 | The pause will either be of a fixed length (pollInterval) plus an | 
 | additional delay proportional to the number of sequential errors (r.errCount). | 
 | <br/><br/> | 
 | This is an example of a typical Go idiom: a function intended to run inside  | 
 | a goroutine takes a channel, upon which it sends its return value  | 
 | (or other indication of completed state). | 
 | </step> | 
 |  | 
 | <step title="StateMonitor" src="doc/codewalk/urlpoll.go:/StateMonitor/,/\n}/"> | 
 | The StateMonitor receives State values on a channel and periodically | 
 | outputs the state of all Resources being polled by the program. | 
 | </step> | 
 |  | 
 | <step title="The updates channel" src="doc/codewalk/urlpoll.go:/updates :=/"> | 
 | The variable updates is a channel of State, on which the Poller goroutines | 
 | send State values. | 
 | <br/><br/> | 
 | This channel is returned by the function. | 
 | </step> | 
 |  | 
 | <step title="The urlStatus map" src="doc/codewalk/urlpoll.go:/urlStatus/"> | 
 | The variable urlStatus is a map of URLs to their most recent status.  | 
 | </step> | 
 |  | 
 | <step title="The Ticker object" src="doc/codewalk/urlpoll.go:/ticker/"> | 
 | A time.Ticker is an object that repeatedly sends a value on a channel at a  | 
 | specified interval.  | 
 | <br/><br/> | 
 | In this case, ticker triggers the printing of the current state to  | 
 | standard output every updateInterval nanoseconds. | 
 | </step> | 
 |  | 
 | <step title="The StateMonitor goroutine" src="doc/codewalk/urlpoll.go:/go func/,/}\(\)/"> | 
 | StateMonitor will loop forever, selecting on two channels:  | 
 | ticker.C and update. The select statement blocks until one of its  | 
 | communications is ready to proceed. | 
 | <br/><br/> | 
 | When StateMonitor receives a tick from ticker.C, it calls logState to | 
 | print the current state.  When it receives a State update from updates, | 
 | it records the new status in the urlStatus map. | 
 | <br/><br/> | 
 | Notice that this goroutine owns the urlStatus data structure, | 
 | ensuring that it can only be accessed sequentially.  | 
 | This prevents memory corruption issues that might arise from parallel reads  | 
 | and/or writes to a shared map. | 
 | </step> | 
 |  | 
 | <step title="Conclusion" src="doc/codewalk/urlpoll.go"> | 
 | In this codewalk we have explored a simple example of using Go's concurrency | 
 | primitives to share memory through communication. | 
 | <br/><br/> | 
 | This should provide a starting point from which to explore the ways in which | 
 | goroutines and channels can be used to write expressive and concise concurrent | 
 | programs. | 
 | </step> | 
 | 	 | 
 | </codewalk> |