diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:11:55 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:11:55 +0200 |
commit | 80f18fc933cf3f3e829c5455a1023d69f7b86e52 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /doc/codewalk | |
parent | 28592ee1ea1f5cdffcf85472f9de0285d928cf12 (diff) | |
download | golang-80f18fc933cf3f3e829c5455a1023d69f7b86e52.tar.gz |
Imported Upstream version 60
Diffstat (limited to 'doc/codewalk')
-rw-r--r-- | doc/codewalk/codewalk.css | 234 | ||||
-rw-r--r-- | doc/codewalk/codewalk.js | 305 | ||||
-rw-r--r-- | doc/codewalk/codewalk.xml | 124 | ||||
-rw-r--r-- | doc/codewalk/functions.xml | 115 | ||||
-rw-r--r-- | doc/codewalk/pig.go | 124 | ||||
-rw-r--r-- | doc/codewalk/popout.png | bin | 213 -> 0 bytes | |||
-rw-r--r-- | doc/codewalk/sharemem.xml | 181 | ||||
-rw-r--r-- | doc/codewalk/urlpoll.go | 117 |
8 files changed, 0 insertions, 1200 deletions
diff --git a/doc/codewalk/codewalk.css b/doc/codewalk/codewalk.css deleted file mode 100644 index a0814e4d2..000000000 --- a/doc/codewalk/codewalk.css +++ /dev/null @@ -1,234 +0,0 @@ -/* - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. -*/ - -#codewalk-main { - text-align: left; - width: 100%; - overflow: auto; -} - -#code-display { - border: 0; - width: 100%; -} - -.setting { - font-size: 8pt; - color: #888888; - padding: 5px; -} - -.hotkey { - text-decoration: underline; -} - -/* Style for Comments (the left-hand column) */ - -#comment-column { - margin: 0pt; - width: 30%; -} - -#comment-column.right { - float: right; -} - -#comment-column.left { - float: left; -} - -#comment-area { - overflow-x: hidden; - overflow-y: auto; -} - -.comment { - cursor: pointer; - font-size: 16px; - border: 2px solid #ba9836; - margin-bottom: 10px; - margin-right: 10px; /* yes, for both .left and .right */ -} - -.comment:last-child { - margin-bottom: 0px; -} - -.right .comment { - margin-left: 10px; -} - -.right .comment.first { -} - -.right .comment.last { -} - -.left .comment.first { -} - -.left .comment.last { -} - -.comment.selected { - border-color: #99b2cb; -} - -.right .comment.selected { - border-left-width: 12px; - margin-left: 0px; -} - -.left .comment.selected { - border-right-width: 12px; - margin-right: 0px; -} - -.comment-link { - display: none; -} - -.comment-title { - font-size: small; - font-weight: bold; - background-color: #fffff0; - padding-right: 10px; - padding-left: 10px; - padding-top: 5px; - padding-bottom: 5px; -} - -.right .comment-title { -} - -.left .comment-title { -} - -.comment.selected .comment-title { - background-color: #f8f8ff; -} - -.comment-text { - overflow: auto; - padding-left: 10px; - padding-right: 10px; - padding-top: 10px; - padding-bottom: 5px; - font-size: small; - line-height: 1.3em; -} - -.comment-text p { - margin-top: 0em; - margin-bottom: 0.5em; -} - -.comment-text p:last-child { - margin-bottom: 0em; -} - -.file-name { - font-size: x-small; - padding-top: 0px; - padding-bottom: 5px; -} - -.hidden-filepaths .file-name { - display: none; -} - -.path-dir { - color: #555; -} - -.path-file { - color: #555; -} - - -/* Style for Code (the right-hand column) */ - -/* Wrapper for the code column to make widths get calculated correctly */ -#code-column { - display: block; - position: relative; - margin: 0pt; - width: 70%; -} - -#code-column.left { - float: left; -} - -#code-column.right { - float: right; -} - -#code-area { - background-color: #f8f8ff; - border: 2px solid #99b2cb; - padding: 5px; -} - -.left #code-area { - margin-right: -1px; -} - -.right #code-area { - margin-left: -1px; -} - -#code-header { - margin-bottom: 5px; -} - -#code { - background-color: white; -} - -code { - font-size: 100%; -} - -.codewalkhighlight { - font-weight: bold; - background-color: #f8f8ff; -} - -#code-display { - margin-top: 0px; - margin-bottom: 0px; -} - -#sizer { - position: absolute; - cursor: col-resize; - left: 0px; - top: 0px; - width: 8px; -} - -/* Style for options (bottom strip) */ - -#code-options { - display: none; -} - -#code-options > span { - padding-right: 20px; -} - -#code-options .selected { - border-bottom: 1px dotted; -} - -#comment-options { - text-align: center; -} - -div#content { - padding-bottom: 0em; -} diff --git a/doc/codewalk/codewalk.js b/doc/codewalk/codewalk.js deleted file mode 100644 index f780bc7a5..000000000 --- a/doc/codewalk/codewalk.js +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/** - * A class to hold information about the Codewalk Viewer. - * @param {jQuery} context The top element in whose context the viewer should - * operate. It will not touch any elements above this one. - * @constructor - */ - var CodewalkViewer = function(context) { - this.context = context; - - /** - * The div that contains all of the comments and their controls. - */ - this.commentColumn = this.context.find('#comment-column'); - - /** - * The div that contains the comments proper. - */ - this.commentArea = this.context.find('#comment-area'); - - /** - * The div that wraps the iframe with the code, as well as the drop down menu - * listing the different files. - * @type {jQuery} - */ - this.codeColumn = this.context.find('#code-column'); - - /** - * The div that contains the code but excludes the options strip. - * @type {jQuery} - */ - this.codeArea = this.context.find('#code-area'); - - /** - * The iframe that holds the code (from Sourcerer). - * @type {jQuery} - */ - this.codeDisplay = this.context.find('#code-display'); - - /** - * The overlaid div used as a grab handle for sizing the code/comment panes. - * @type {jQuery} - */ - this.sizer = this.context.find('#sizer'); - - /** - * The full-screen overlay that ensures we don't lose track of the mouse - * while dragging. - * @type {jQuery} - */ - this.overlay = this.context.find('#overlay'); - - /** - * The hidden input field that we use to hold the focus so that we can detect - * shortcut keypresses. - * @type {jQuery} - */ - this.shortcutInput = this.context.find('#shortcut-input'); - - /** - * The last comment that was selected. - * @type {jQuery} - */ - this.lastSelected = null; -}; - -/** - * Minimum width of the comments or code pane, in pixels. - * @type {number} - */ -CodewalkViewer.MIN_PANE_WIDTH = 200; - -/** - * Navigate the code iframe to the given url and update the code popout link. - * @param {string} url The target URL. - * @param {Object} opt_window Window dependency injection for testing only. - */ -CodewalkViewer.prototype.navigateToCode = function(url, opt_window) { - if (!opt_window) opt_window = window; - // Each iframe is represented by two distinct objects in the DOM: an iframe - // object and a window object. These do not expose the same capabilities. - // Here we need to get the window representation to get the location member, - // so we access it directly through window[] since jQuery returns the iframe - // representation. - // We replace location rather than set so as not to create a history for code - // navigation. - opt_window['code-display'].location.replace(url); - var k = url.indexOf('&'); - if (k != -1) url = url.slice(0, k); - k = url.indexOf('fileprint='); - if (k != -1) url = url.slice(k+10, url.length); - this.context.find('#code-popout-link').attr('href', url); -}; - -/** - * Selects the first comment from the list and forces a refresh of the code - * view. - */ -CodewalkViewer.prototype.selectFirstComment = function() { - // TODO(rsc): handle case where there are no comments - var firstSourcererLink = this.context.find('.comment:first'); - this.changeSelectedComment(firstSourcererLink); -}; - -/** - * Sets the target on all links nested inside comments to be _blank. - */ -CodewalkViewer.prototype.targetCommentLinksAtBlank = function() { - this.context.find('.comment a[href], #description a[href]').each(function() { - if (!this.target) this.target = '_blank'; - }); -}; - -/** - * Installs event handlers for all the events we care about. - */ -CodewalkViewer.prototype.installEventHandlers = function() { - var self = this; - - this.context.find('.comment') - .click(function(event) { - if (jQuery(event.target).is('a[href]')) return true; - self.changeSelectedComment(jQuery(this)); - return false; - }); - - this.context.find('#code-selector') - .change(function() {self.navigateToCode(jQuery(this).val());}); - - this.context.find('#description-table .quote-feet.setting') - .click(function() {self.toggleDescription(jQuery(this)); return false;}); - - this.sizer - .mousedown(function(ev) {self.startSizerDrag(ev); return false;}); - this.overlay - .mouseup(function(ev) {self.endSizerDrag(ev); return false;}) - .mousemove(function(ev) {self.handleSizerDrag(ev); return false;}); - - this.context.find('#prev-comment') - .click(function() { - self.changeSelectedComment(self.lastSelected.prev()); return false; - }); - - this.context.find('#next-comment') - .click(function() { - self.changeSelectedComment(self.lastSelected.next()); return false; - }); - - // Workaround for Firefox 2 and 3, which steal focus from the main document - // whenever the iframe content is (re)loaded. The input field is not shown, - // but is a way for us to bring focus back to a place where we can detect - // keypresses. - this.context.find('#code-display') - .load(function(ev) {self.shortcutInput.focus();}); - - jQuery(document).keypress(function(ev) { - switch(ev.which) { - case 110: // 'n' - self.changeSelectedComment(self.lastSelected.next()); - return false; - case 112: // 'p' - self.changeSelectedComment(self.lastSelected.prev()); - return false; - default: // ignore - } - }); - - window.onresize = function() {self.updateHeight();}; -}; - -/** - * Starts dragging the pane sizer. - * @param {Object} ev The mousedown event that started us dragging. - */ -CodewalkViewer.prototype.startSizerDrag = function(ev) { - this.initialCodeWidth = this.codeColumn.width(); - this.initialCommentsWidth = this.commentColumn.width(); - this.initialMouseX = ev.pageX; - this.overlay.show(); -}; - -/** - * Handles dragging the pane sizer. - * @param {Object} ev The mousemove event updating dragging position. - */ -CodewalkViewer.prototype.handleSizerDrag = function(ev) { - var delta = ev.pageX - this.initialMouseX; - if (this.codeColumn.is('.right')) delta = -delta; - var proposedCodeWidth = this.initialCodeWidth + delta; - var proposedCommentWidth = this.initialCommentsWidth - delta; - var mw = CodewalkViewer.MIN_PANE_WIDTH; - if (proposedCodeWidth < mw) delta = mw - this.initialCodeWidth; - if (proposedCommentWidth < mw) delta = this.initialCommentsWidth - mw; - proposedCodeWidth = this.initialCodeWidth + delta; - proposedCommentWidth = this.initialCommentsWidth - delta; - // If window is too small, don't even try to resize. - if (proposedCodeWidth < mw || proposedCommentWidth < mw) return; - this.codeColumn.width(proposedCodeWidth); - this.commentColumn.width(proposedCommentWidth); - this.options.codeWidth = parseInt( - this.codeColumn.width() / - (this.codeColumn.width() + this.commentColumn.width()) * 100); - this.context.find('#code-column-width').text(this.options.codeWidth + '%'); -}; - -/** - * Ends dragging the pane sizer. - * @param {Object} ev The mouseup event that caused us to stop dragging. - */ -CodewalkViewer.prototype.endSizerDrag = function(ev) { - this.overlay.hide(); - this.updateHeight(); -}; - -/** - * Toggles the Codewalk description between being shown and hidden. - * @param {jQuery} target The target that was clicked to trigger this function. - */ -CodewalkViewer.prototype.toggleDescription = function(target) { - var description = this.context.find('#description'); - description.toggle(); - target.find('span').text(description.is(':hidden') ? 'show' : 'hide'); - this.updateHeight(); -}; - -/** - * Changes the side of the window on which the code is shown and saves the - * setting in a cookie. - * @param {string?} codeSide The side on which the code should be, either - * 'left' or 'right'. - */ -CodewalkViewer.prototype.changeCodeSide = function(codeSide) { - var commentSide = codeSide == 'left' ? 'right' : 'left'; - this.context.find('#set-code-' + codeSide).addClass('selected'); - this.context.find('#set-code-' + commentSide).removeClass('selected'); - // Remove previous side class and add new one. - this.codeColumn.addClass(codeSide).removeClass(commentSide); - this.commentColumn.addClass(commentSide).removeClass(codeSide); - this.sizer.css(codeSide, 'auto').css(commentSide, 0); - this.options.codeSide = codeSide; -}; - -/** - * Adds selected class to newly selected comment, removes selected style from - * previously selected comment, changes drop down options so that the correct - * file is selected, and updates the code popout link. - * @param {jQuery} target The target that was clicked to trigger this function. - */ -CodewalkViewer.prototype.changeSelectedComment = function(target) { - var currentFile = target.find('.comment-link').attr('href'); - if (!currentFile) return; - - if (!(this.lastSelected && this.lastSelected.get(0) === target.get(0))) { - if (this.lastSelected) this.lastSelected.removeClass('selected'); - target.addClass('selected'); - this.lastSelected = target; - var targetTop = target.position().top; - var parentTop = target.parent().position().top; - if (targetTop + target.height() > parentTop + target.parent().height() || - targetTop < parentTop) { - var delta = targetTop - parentTop; - target.parent().animate( - {'scrollTop': target.parent().scrollTop() + delta}, - Math.max(delta / 2, 200), 'swing'); - } - var fname = currentFile.match(/(?:select=|fileprint=)\/[^&]+/)[0]; - fname = fname.slice(fname.indexOf('=')+2, fname.length); - this.context.find('#code-selector').val(fname); - this.context.find('#prev-comment').toggleClass( - 'disabled', !target.prev().length); - this.context.find('#next-comment').toggleClass( - 'disabled', !target.next().length); - } - - // Force original file even if user hasn't changed comments since they may - // have nagivated away from it within the iframe without us knowing. - this.navigateToCode(currentFile); -}; - -/** - * Updates the viewer by changing the height of the comments and code so that - * they fit within the height of the window. The function is typically called - * after the user changes the window size. - */ -CodewalkViewer.prototype.updateHeight = function() { - var windowHeight = jQuery(window).height() - 5 // GOK - var areaHeight = windowHeight - this.codeArea.offset().top - var footerHeight = this.context.find('#footer').outerHeight(true) - this.commentArea.height(areaHeight - footerHeight - this.context.find('#comment-options').outerHeight(true)) - var codeHeight = areaHeight - footerHeight - 15 // GOK - this.codeArea.height(codeHeight) - this.codeDisplay.height(codeHeight - this.codeDisplay.offset().top + this.codeArea.offset().top); - this.sizer.height(codeHeight); -}; - -jQuery(document).ready(function() { - var viewer = new CodewalkViewer(jQuery()); - viewer.selectFirstComment(); - viewer.targetCommentLinksAtBlank(); - viewer.installEventHandlers(); - viewer.updateHeight(); -}); diff --git a/doc/codewalk/codewalk.xml b/doc/codewalk/codewalk.xml deleted file mode 100644 index 9cd8361e8..000000000 --- a/doc/codewalk/codewalk.xml +++ /dev/null @@ -1,124 +0,0 @@ -<codewalk title="How to Write a Codewalk"> - -<step title="Introduction" src="doc/codewalk/codewalk.xml"> - A codewalk is a guided tour through a piece of code. - It consists of a sequence of steps, each typically explaining - a highlighted section of code. - <br/><br/> - - The <a href="/cmd/godoc">godoc</a> web server translates - an XML file like the one in the main window pane into the HTML - page that you're viewing now. - <br/><br/> - - The codewalk with URL path <code>/doc/codewalk/</code><i>name</i> - is loaded from the input file <code>$GOROOT/doc/codewalk/</code><i>name</i><code>.xml</code>. - <br/><br/> - - This codewalk explains how to write a codewalk by examining - its own source code, - <code><a href="/doc/codewalk/codewalk.xml">$GOROOT/doc/codewalk/codewalk.xml</a></code>, - shown in the main window pane to the left. -</step> - -<step title="Title" src="doc/codewalk/codewalk.xml:/title=/"> - The codewalk input file is an XML file containing a single - <code><codewalk></code> element. - That element's <code>title</code> attribute gives the title - that is used both on the codewalk page and in the codewalk list. -</step> - -<step title="Steps" src="doc/codewalk/codewalk.xml:/<step/,/step>/"> - Each step in the codewalk is a <code><step></code> element - nested inside the main <code><codewalk></code>. - The step element's <code>title</code> attribute gives the step's title, - which is shown in a shaded bar above the main step text. - The element's <code>src</code> attribute specifies the source - code to show in the main window pane and, optionally, a range of - lines to highlight. - <br/><br/> - - The first step in this codewalk does not highlight any lines: - its <code>src</code> is just a file name. -</step> - -<step title="Specifiying a source line" src='doc/codewalk/codewalk.xml:/title="Title"/'> - The most complex part of the codewalk specification is - saying what lines to highlight. - Instead of ordinary line numbers, - the codewalk uses an address syntax that makes it possible - to describe the match by its content. - As the file gets edited, this descriptive address has a better - chance to continue to refer to the right section of the file. - <br/><br/> - - To specify a source line, use a <code>src</code> attribute of the form - <i>filename</i><code>:</code><i>address</i>, - where <i>address</i> is an address in the syntax used by the text editors <i>sam</i> and <i>acme</i>. - <br/><br/> - - The simplest address is a single regular expression. - The highlighted line in the main window pane shows that the - address for the “Title” step was <code>/title=/</code>, - which matches the first instance of that <a href="/pkg/regexp">regular expression</a> (<code>title=</code>) in the file. -</step> - -<step title="Specifying a source range" src='doc/codewalk/codewalk.xml:/title="Steps"/'> - To highlight a range of source lines, the simplest address to use is - a pair of regular expressions - <code>/</code><i>regexp1</i><code>/,/</code><i>regexp2</i><code>/</code>. - The highlight begins with the line containing the first match for <i>regexp1</i> - and ends with the line containing the first match for <i>regexp2</i> - after the end of the match for <i>regexp1</i>. - Ignoring the HTML quoting, - The line containing the first match for <i>regexp1</i> will be the first one highlighted, - and the line containing the first match for <i>regexp2</i>. - <br/><br/> - - The address <code>/<step/,/step>/</code> looks for the first instance of - <code><step</code> in the file, and then starting after that point, - looks for the first instance of <code>step></code>. - (Click on the “Steps” step above to see the highlight in action.) - Note that the <code><</code> and <code>></code> had to be written - using XML escapes in order to be valid XML. -</step> - -<step title="Advanced addressing" src="doc/codewalk/codewalk.xml:/Advanced/,/step>/"> - The <code>/</code><i>regexp</i><code>/</code> - and <code>/</code><i>regexp1</i><code>/,/</code><i>regexp2</i><code>/</code> - forms suffice for most highlighting. - <br/><br/> - - The full address syntax is summarized in this table - (an excerpt of Table II from - <a href="http://plan9.bell-labs.com/sys/doc/sam/sam.html">The text editor <code>sam</code></a>): - <br/><br/> - - <table> - <tr><td colspan="2"><b>Simple addresses</b></td></tr> - <tr><td><code>#</code><i>n</i></td> - <td>The empty string after character <i>n</i></td></tr> - <tr><td><i>n</i></td> - <td>Line <i>n</i></td></tr> - <tr><td><code>/</code><i>regexp</i><code>/</code></td> - <td>The first following match of the regular expression</td></tr> - <!-- not supported (yet?) - <tr><td><code>–/</code><i>regexp</i><code>/</code></td> - <td>The first previous match of the regular expression</td></tr> - --> - <tr><td><code>$</code></td> - <td>The null string at the end of the file</td></tr> - - <tr><td colspan="2"><b>Compound addresses</b></td></tr> - <tr><td><i>a1</i><code>+</code><i>a2</i></td> - <td>The address <i>a2</i> evaluated starting at the right of <i>a1</i></td></tr> - <tr><td><i>a1</i><code>-</code><i>a2</i></td> - <td>The address <i>a2</i> evaluated in the reverse direction starting at the left of <i>a1</i></td></tr> - <tr><td><i>a1</i><code>,</code><i>a2</i></td> - <td>From the left of <i>a1</i> to the right of <i>a2</i> (default <code>0,$</code>).</td></tr> - </table> -</step> - - - -</codewalk> diff --git a/doc/codewalk/functions.xml b/doc/codewalk/functions.xml deleted file mode 100644 index 986a017e1..000000000 --- a/doc/codewalk/functions.xml +++ /dev/null @@ -1,115 +0,0 @@ -<codewalk title="First-Class Functions in Go"> - -<step title="Introduction" src="doc/codewalk/pig.go"> - Go supports first class functions, higher-order functions, user-defined - function types, function literals, closures, and multiple return values. - <br/><br/> - - This rich feature set supports a functional programming style in a strongly - typed language. - <br/><br/> - - In this codewalk we will look at a simple program that simulates a dice game - called <a href="http://en.wikipedia.org/wiki/Pig_(dice)">Pig</a> and evaluates - basic strategies. -</step> - -<step title="Game overview" src="doc/codewalk/pig.go:/\/\/ A score/,/thisTurn int\n}/"> - Pig is a two-player game played with a 6-sided die. Each turn, you may roll or stay. - <ul> - <li> If you roll a 1, you lose all points for your turn and play passes to - your opponent. Any other roll adds its value to your turn score. </li> - <li> If you stay, your turn score is added to your total score, and play passes - to your opponent. </li> - </ul> - - The first person to reach 100 total points wins. - <br/><br/> - - The <code>score</code> type stores the scores of the current and opposing - players, in addition to the points accumulated during the current turn. -</step> - -<step title="User-defined function types" src="doc/codewalk/pig.go:/\/\/ An action/,/bool\)/"> - In Go, functions can be passed around just like any other value. A function's - type signature describes the types of its arguments and return values. - <br/><br/> - - The <code>action</code> type is a function that takes a <code>score</code> - and returns the resulting <code>score</code> and whether the current turn is - over. - <br/><br/> - - If the turn is over, the <code>player</code> and <code>opponent</code> fields - in the resulting <code>score</code> should be swapped, as it is now the other player's - turn. -</step> - -<step title="Multiple return values" src="doc/codewalk/pig.go:/\/\/ roll returns/,/stay.*true\n}/"> - Go functions can return multiple values. - <br/><br/> - - The functions <code>roll</code> and <code>stay</code> each return a pair of - values. They also match the <code>action</code> type signature. These - <code>action</code> functions define the rules of Pig. -</step> - -<step title="Higher-order functions" src="doc/codewalk/pig.go:/\/\/ A strategy/,/action\n/"> - A function can use other functions as arguments and return values. - <br/><br/> - - A <code>strategy</code> is a function that takes a <code>score</code> as input - and returns an <code>action</code> to perform. <br/> - (Remember, an <code>action</code> is itself a function.) -</step> - -<step title="Function literals and closures" src="doc/codewalk/pig.go:/return func/,/return roll\n\t}/"> - Anonymous functions can be declared in Go, as in this example. Function - literals are closures: they inherit the scope of the function in which they - are declared. - <br/><br/> - - One basic strategy in Pig is to continue rolling until you have accumulated at - least k points in a turn, and then stay. The argument <code>k</code> is - enclosed by this function literal, which matches the <code>strategy</code> type - signature. -</step> - -<step title="Simulating games" src="doc/codewalk/pig.go:/\/\/ play/,/currentPlayer\n}/"> - We simulate a game of Pig by calling an <code>action</code> to update the - <code>score</code> until one player reaches 100 points. Each - <code>action</code> is selected by calling the <code>strategy</code> function - associated with the current player. -</step> - -<step title="Comparing functions" src="doc/codewalk/pig.go:/if action/,/currentPlayer\)\)\n\t\t}/"> - Functions can be compared for equality in Go. From the - <a href="http://golang.org/doc/go_spec.html#Comparison_operators">language specification</a>: - Function values are equal if they refer to the same function or if both are <code>nil</code>. - <br/><br/> - - We enforce that a <code>strategy</code> function can only return a legal - <code>action</code>: either <code>roll</code> or <code>stay</code>. -</step> - -<step title="Simulating a tournament" src="doc/codewalk/pig.go:/\/\/ roundRobin/,/gamesPerStrategy\n}/"> - The <code>roundRobin</code> function simulates a tournament and tallies wins. - Each strategy plays each other strategy <code>gamesPerSeries</code> times. -</step> - -<step title="Variadic function declarations" src="doc/codewalk/pig.go:/\/\/ ratioS/,/string {/"> - Variadic functions like <code>ratioString</code> take a variable number of - arguments. These arguments are available as a slice inside the function. -</step> - -<step title="Simulation results" src="doc/codewalk/pig.go:/func main/,/\n}/"> - The <code>main</code> function defines 100 basic strategies, simulates a round - robin tournament, and then prints the win/loss record of each strategy. - <br/><br/> - - Among these strategies, staying at 25 is best, but the <a - href="http://www.google.com/search?q=optimal+play+pig">optimal strategy for - Pig</a> is much more complex. -</step> - -</codewalk> diff --git a/doc/codewalk/pig.go b/doc/codewalk/pig.go deleted file mode 100644 index 9e415f589..000000000 --- a/doc/codewalk/pig.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "fmt" - "rand" -) - -const ( - win = 100 // The winning score in a game of Pig - gamesPerSeries = 10 // The number of games per series to simulate -) - -// A score includes scores accumulated in previous turns for each player, -// as well as the points scored by the current player in this turn. -type score struct { - player, opponent, thisTurn int -} - -// An action transitions stochastically to a resulting score. -type action func(current score) (result score, turnIsOver bool) - -// roll returns the (result, turnIsOver) outcome of simulating a die roll. -// If the roll value is 1, then thisTurn score is abandoned, and the players' -// roles swap. Otherwise, the roll value is added to thisTurn. -func roll(s score) (score, bool) { - outcome := rand.Intn(6) + 1 // A random int in [1, 6] - if outcome == 1 { - return score{s.opponent, s.player, 0}, true - } - return score{s.player, s.opponent, outcome + s.thisTurn}, false -} - -// stay returns the (result, turnIsOver) outcome of staying. -// thisTurn score is added to the player's score, and the players' roles swap. -func stay(s score) (score, bool) { - return score{s.opponent, s.player + s.thisTurn, 0}, true -} - -// A strategy chooses an action for any given score. -type strategy func(score) action - -// stayAtK returns a strategy that rolls until thisTurn is at least k, then stays. -func stayAtK(k int) strategy { - return func(s score) action { - if s.thisTurn >= k { - return stay - } - return roll - } -} - -// play simulates a Pig game and returns the winner (0 or 1). -func play(strategy0, strategy1 strategy) int { - strategies := []strategy{strategy0, strategy1} - var s score - var turnIsOver bool - currentPlayer := rand.Intn(2) // Randomly decide who plays first - for s.player+s.thisTurn < win { - action := strategies[currentPlayer](s) - if action != roll && action != stay { - panic(fmt.Sprintf("Player %d is cheating", currentPlayer)) - } - s, turnIsOver = action(s) - if turnIsOver { - currentPlayer = (currentPlayer + 1) % 2 - } - } - return currentPlayer -} - -// roundRobin simulates a series of games between every pair of strategies. -func roundRobin(strategies []strategy) ([]int, int) { - wins := make([]int, len(strategies)) - for i := 0; i < len(strategies); i++ { - for j := i + 1; j < len(strategies); j++ { - for k := 0; k < gamesPerSeries; k++ { - winner := play(strategies[i], strategies[j]) - if winner == 0 { - wins[i]++ - } else { - wins[j]++ - } - } - } - } - gamesPerStrategy := gamesPerSeries * (len(strategies) - 1) // no self play - return wins, gamesPerStrategy -} - -// ratioString takes a list of integer values and returns a string that lists -// each value and its percentage of the sum of all values. -// e.g., ratios(1, 2, 3) = "1/6 (16.7%), 2/6 (33.3%), 3/6 (50.0%)" -func ratioString(vals ...int) string { - total := 0 - for _, val := range vals { - total += val - } - s := "" - for _, val := range vals { - if s != "" { - s += ", " - } - pct := 100 * float64(val) / float64(total) - s += fmt.Sprintf("%d/%d (%0.1f%%)", val, total, pct) - } - return s -} - -func main() { - strategies := make([]strategy, win) - for k := range strategies { - strategies[k] = stayAtK(k + 1) - } - wins, games := roundRobin(strategies) - - for k := range strategies { - fmt.Printf("Wins, losses staying at k =% 4d: %s\n", - k+1, ratioString(wins[k], games-wins[k])) - } -} diff --git a/doc/codewalk/popout.png b/doc/codewalk/popout.png Binary files differdeleted file mode 100644 index 9c0c23638..000000000 --- a/doc/codewalk/popout.png +++ /dev/null diff --git a/doc/codewalk/sharemem.xml b/doc/codewalk/sharemem.xml deleted file mode 100644 index 1a669f7b5..000000000 --- a/doc/codewalk/sharemem.xml +++ /dev/null @@ -1,181 +0,0 @@ -<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 commmunication. -<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> diff --git a/doc/codewalk/urlpoll.go b/doc/codewalk/urlpoll.go deleted file mode 100644 index b51be9502..000000000 --- a/doc/codewalk/urlpoll.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "http" - "log" - "time" -) - -const ( - numPollers = 2 // number of Poller goroutines to launch - second = 1e9 // one second is 1e9 nanoseconds - pollInterval = 60 * second // how often to poll each URL - statusInterval = 10 * second // how often to log status to stdout - errTimeout = 10 * second // back-off timeout on error -) - -var urls = []string{ - "http://www.google.com/", - "http://golang.org/", - "http://blog.golang.org/", -} - -// State represents the last-known state of a URL. -type State struct { - url string - status string -} - -// StateMonitor maintains a map that stores the state of the URLs being -// polled, and prints the current state every updateInterval nanoseconds. -// It returns a chan State to which resource state should be sent. -func StateMonitor(updateInterval int64) chan<- State { - updates := make(chan State) - urlStatus := make(map[string]string) - ticker := time.NewTicker(updateInterval) - go func() { - for { - select { - case <-ticker.C: - logState(urlStatus) - case s := <-updates: - urlStatus[s.url] = s.status - } - } - }() - return updates -} - -// logState prints a state map. -func logState(s map[string]string) { - log.Println("Current state:") - for k, v := range s { - log.Printf(" %s %s", k, v) - } -} - -// Resource represents an HTTP URL to be polled by this program. -type Resource struct { - url string - errCount int64 -} - -// Poll executes an HTTP HEAD request for url -// and returns the HTTP status string or an error string. -func (r *Resource) Poll() string { - resp, err := http.Head(r.url) - if err != nil { - log.Println("Error", r.url, err) - r.errCount++ - return err.String() - } - r.errCount = 0 - return resp.Status -} - -// Sleep sleeps for an appropriate interval (dependant on error state) -// before sending the Resource to done. -func (r *Resource) Sleep(done chan *Resource) { - time.Sleep(pollInterval + errTimeout*r.errCount) - done <- r -} - -func Poller(in <-chan *Resource, out chan<- *Resource, status chan<- State) { - for r := range in { - s := r.Poll() - status <- State{r.url, s} - out <- r - } -} - -func main() { - // create our input and output channels - pending, complete := make(chan *Resource), make(chan *Resource) - - // launch the StateMonitor - status := StateMonitor(statusInterval) - - // launch some Poller goroutines - for i := 0; i < numPollers; i++ { - go Poller(pending, complete, status) - } - - // send some Resources to the pending queue - go func() { - for _, url := range urls { - pending <- &Resource{url: url} - } - }() - - for r := range complete { - go r.Sleep(pending) - } -} |