diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 00000000000..0abb881b17a --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,11 @@ +# Copyright 2009 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. + +include $(GOROOT)/src/Make.$(GOARCH) + +TARG=htmlgen +GOFILES=\ + htmlgen.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/doc/go_tutorial.head b/doc/go_tutorial.head deleted file mode 100644 index a15e53683bf..00000000000 --- a/doc/go_tutorial.head +++ /dev/null @@ -1,3 +0,0 @@ - - -

Introduction

diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html index f966ef936a4..27710ed268c 100644 --- a/doc/go_tutorial.html +++ b/doc/go_tutorial.html @@ -1,15 +1,14 @@ -

Introduction

This document is a tutorial introduction to the basics of the Go systems programming language, intended for programmers familiar with C or C++. It is not a comprehensive guide to the language; at the moment the document closest to that is the -language specification. +language specification.

The presentation proceeds through a series of modest programs to illustrate key features of the language. All the programs work (at time of writing) and are -checked into the repository in the directory /doc/progs. +checked into the repository in the directory /doc/progs/.

Program snippets are annotated with the line number in the original file; for cleanliness, blank lines remain blank. @@ -45,8 +44,8 @@ The comment convention is the same as in C++:

     /* ... */
     // ...
-
 
+

Later we'll have much more to say about printing.

Echo

@@ -94,8 +93,8 @@ But it's not necessary to do so; we could have said
     const Space = " "
     const Newline = "\n"
-
 
+

Semicolons aren't needed here; in fact, semicolons are unnecessary after any top-level declaration, even though they are needed as separators within a parenthesized list of declarations. @@ -128,8 +127,8 @@ The declaration statement has the form

     var s string = "";
-
 
+

This is the var keyword, followed by the name of the variable, followed by its type, followed by an equals sign and an initial value for the variable.

@@ -139,14 +138,14 @@ We could write

     var s = "";
-
 
+

or we could go even shorter and write the idiom

     s := "";
-
 
+

The := operator is used a lot in Go to represent an initializing declaration. (For those who know Sawzall, its := construct is the same, but notice that Go has no colon after the name in a full var declaration. @@ -177,8 +176,8 @@ It's defined that way. Falling off the end of main.main means

     os.Exit(1)
-
 
+

The os package contains other essentials for getting started; for instance, os.Args is an array used by the flag package to access the command-line arguments. @@ -213,8 +212,8 @@ a string value:

     s[0] = 'x';
     (*p)[1] = 'y';
-
 
+

In C++ terms, Go strings are a bit like const strings, while pointers to strings are analogous to const string references.

@@ -225,8 +224,8 @@ Arrays are declared like this:

     var array_of_int [10]int;
-
 
+

Arrays, like strings, are values, but they are mutable. This differs from C, in which array_of_int would be usable as a pointer to int. In Go, since arrays are values, it's meaningful (and useful) to talk @@ -286,21 +285,21 @@ elements for you, use ... as the array size:

     s := sum(&[...]int{1,2,3});
-
 
+

In practice, though, unless you're meticulous about storage layout within a data structure, a slice itself - using empty brackets and no & - is all you need:

     s := sum([]int{1,2,3});
-
 
+

There are also maps, which you can initialize like this:

     m := map[string] int {"one":1 , "two":2}
-
 
+

The built-in function len(), which returns number of elements, makes its first appearance in sum. It works on strings, arrays, slices, and maps. @@ -317,14 +316,14 @@ returns a pointer to the allocated storage.

     type T struct { a, b int }
     var t *T = new(T);
-
 
+

or the more idiomatic

     t := new(T);
-
 
+

Some types - maps, slices, and channels (see below) - have reference semantics. If you're holding a slice or a map and you modify its contents, other variables referencing the same underlying data will see the modification. For these three @@ -332,15 +331,15 @@ types you want to use the built-in function make():

     m := make(map[string] int);
-
 
+

This statement initializes a new map ready to store entries. If you just declare the map, as in

     var m map[string] int;
-
 
+

it creates a nil reference that cannot hold anything. To use the map, you must first initialize the reference using make() or by assignment to an existing map. @@ -360,8 +359,8 @@ too little precision to represent the value.

     const hard_eight = (1 << 100) >> 97  // legal
-
 
+

There are nuances that deserve redirection to the legalese of the language specification but here are some illustrative examples:

@@ -373,8 +372,8 @@ language specification but here are some illustrative examples: x := 1.5 // a float i3div2 := 3/2 // integer division - result is 1 f3div2 := 3./2. // floating point division - result is 1.5 - +

Conversions only work for simple cases such as converting ints of one sign or size to another, and between ints and floats, plus a few other simple cases. There are no automatic numeric conversions of any kind in Go, @@ -446,8 +445,8 @@ object. We could write n.fd = fd; n.name = name; return n - +

but for simple structures like File it's easier to return the address of a nonce composite literal, as is done here on line 21.

@@ -585,8 +584,8 @@ Finally we can run the program: hello, world can't open file; err=No such file or directory % - +

Rotting cats

Building on the file package, here's a simple version of the Unix utility cat(1), @@ -864,8 +863,8 @@ Within the fmt package, Printf is declared with this s

     Printf(format string, v ...) (n int, errno os.Error)
-
 
+

That ... represents the variadic argument list that in C would be handled using the stdarg.h macros, but in Go is passed using an empty interface variable (interface {}) that is then unpacked @@ -888,8 +887,8 @@ prints

     18446744073709551615 -1
-
 
+

In fact, if you're lazy the format %v will print, in a simple appropriate style, any value, even an array or structure. The output of

@@ -904,8 +903,8 @@ is

     18446744073709551615 {77 Sunset Strip} [1 2 3 4]
-
 
+

You can drop the formatting altogether if you use Print or Println instead of Printf. Those routines do fully automatic formatting. The Print function just prints its elements out using the equivalent @@ -946,8 +945,8 @@ default formatter for that type will use it and produce the output

     77 Sunset Strip
-
 
+

Observe that the String() method calls Sprint (the obvious Go variant that returns a string) to do its formatting; special formatters can use the fmt library recursively. @@ -970,15 +969,17 @@ Schematically, given a value v, it does this: type Stringer interface { String() string } - + +

+

     s, ok := v.(Stringer);  // Test whether v implements "String()"
     if ok {
         result = s.String()
     } else {
         result = default_output(v)
     }
-
 
+

The code uses a ``type assertion'' (v.(Stringer)) to test if the value stored in v satisfies the Stringer interface; if it does, s will become an interface variable implementing the method and ok will @@ -1000,8 +1001,8 @@ interface type defined in the io library: type Writer interface { Write(p []byte) (n int, err os.Error); } - +

(This interface is another conventional name, this time for Write; there are also io.Reader, io.ReadWriter, and so on.) Thus you can call Fprintf on any type that implements a standard Write() @@ -1081,8 +1082,8 @@ computation but in the same address space:

     go sum(huge_array); // calculate sum in the background
-
 
+

If you want to know when the calculation is done, pass a channel on which it can report back:

@@ -1091,8 +1092,8 @@ on which it can report back: go sum(huge_array, ch); // ... do something else for a while result := <-ch; // wait for, and retrieve, result - +

Back to our prime sieve. Here's how the sieve pipeline is stitched together:

diff --git a/doc/go_tutorial.txt b/doc/go_tutorial.txt index 15e29281b58..dd7cd9fd878 100644 --- a/doc/go_tutorial.txt +++ b/doc/go_tutorial.txt @@ -1,14 +1,15 @@ -Let's Go + +Introduction ---- This document is a tutorial introduction to the basics of the Go systems programming language, intended for programmers familiar with C or C++. It is not a comprehensive guide to the language; at the moment the document closest to that is the -language specification. +language specification. The presentation proceeds through a series of modest programs to illustrate key features of the language. All the programs work (at time of writing) and are -checked into the repository in the directory "/doc/progs". +checked into the repository in the directory "/doc/progs/". Program snippets are annotated with the line number in the original file; for cleanliness, blank lines remain blank. @@ -215,7 +216,7 @@ pointer to "sum()" by (automatically) promoting it to a slice. If you are creating a regular array but want the compiler to count the elements for you, use "..." as the array size: - s := sum(&[...]int{1,2,3}); + s := sum(&[...]int{1,2,3}); In practice, though, unless you're meticulous about storage layout within a data structure, a slice itself - using empty brackets and no "&" - is all you need: @@ -277,7 +278,7 @@ constants are evaluated as large-precision values that can overflow only when they are assigned to an integer variable with too little precision to represent the value. - const hard_eight = (1 << 100) >> 97 // legal + const hard_eight = (1 << 100) >> 97 // legal There are nuances that deserve redirection to the legalese of the language specification but here are some illustrative examples: @@ -542,7 +543,7 @@ to implement the three methods for that type, like this: Printing ---- +---- The examples of formatted printing so far have been modest. In this section we'll talk about how formatted I/O can be done well in Go. @@ -721,7 +722,7 @@ on which it can report back: ch := make(chan int); go sum(huge_array, ch); // ... do something else for a while - result := <-ch; // wait for, and retrieve, result + result := <-ch; // wait for, and retrieve, result Back to our prime sieve. Here's how the sieve pipeline is stitched together: @@ -824,3 +825,6 @@ at the end of main: There's a lot more to Go programming and concurrent programming in general but this quick tour should give you some of the basics. + + + diff --git a/doc/htmlgen.go b/doc/htmlgen.go new file mode 100644 index 00000000000..8d44fc0787b --- /dev/null +++ b/doc/htmlgen.go @@ -0,0 +1,192 @@ +// Copyright 2009 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. + +// Process plain text into HTML. +// - h2's are made from lines followed by a line "----\n" +// - tab-indented blocks become

 blocks
+//	- blank lines become 

marks +// - "quoted strings" become quoted strings + +package main + +import ( + "bufio"; + "bytes"; + "log"; + "os"; + "strings"; +) + +var ( + lines = make([][]byte, 0, 10000); // assume big enough + linebuf = make([]byte, 10000); // assume big enough + + empty = strings.Bytes(""); + newline = strings.Bytes("\n"); + tab = strings.Bytes("\t"); + quote = strings.Bytes(`"`); + + sectionMarker = strings.Bytes("----\n"); + preStart = strings.Bytes("

");
+	preEnd = strings.Bytes("
\n"); + pp = strings.Bytes("

\n"); +); + +func main() { + read(); + headings(); + paragraphs(); + coalesce(preStart, foldPre); + coalesce(tab, foldTabs); + quotes(); + write(); +} + +func read() { + b := bufio.NewReader(os.Stdin); + for { + line, err := b.ReadBytes('\n'); + if err == os.EOF { + break; + } + if err != nil { + log.Exit(err) + } + n := len(lines); + lines = lines[0:n+1]; + lines[n] = line; + } +} + +func write() { + b := bufio.NewWriter(os.Stdout); + for _, line := range lines { + b.Write(expandTabs(line)); + } + b.Flush(); +} + +// each time prefix is found on a line, call fold and replace +// line with return value from fold. +func coalesce(prefix []byte, fold func(i int) (n int, line []byte)) { + j := 0; // output line number; goes up by one each loop + for i := 0; i < len(lines); { + if bytes.HasPrefix(lines[i], prefix) { + nlines, block := fold(i); + lines[j] = block; + i += nlines; + } else { + lines[j] = lines[i]; + i++; + } + j++; + } + lines = lines[0:j]; +} + +// return the

 block as a single slice
+func foldPre(i int) (n int, line []byte) {
+	buf := new(bytes.Buffer);
+	for i < len(lines) {
+		buf.Write(lines[i]);
+		n++;
+		if bytes.Equal(lines[i], preEnd) {
+			break
+		}
+		i++;
+	}
+	return n, buf.Bytes();
+}
+
+// return the tab-indented block as a single 
-bounded slice
+func foldTabs(i int) (n int, line []byte) {
+	buf := new(bytes.Buffer);
+	buf.WriteString("
\n");
+	for i < len(lines) {
+		if !bytes.HasPrefix(lines[i], tab) {
+			break;
+		}
+		buf.Write(lines[i]);
+		n++;
+		i++;
+	}
+	buf.WriteString("
\n"); + return n, buf.Bytes(); +} + +func headings() { + b := bufio.NewWriter(os.Stdout); + for i, l := range lines { + if i > 0 && bytes.Equal(l, sectionMarker) { + lines[i-1] = strings.Bytes("

" + string(trim(lines[i-1])) + "

\n"); + lines[i] = empty; + } + } + b.Flush(); +} + +func paragraphs() { + for i, l := range lines { + if bytes.Equal(l, newline) { + lines[i] = pp; + } + } +} + +func quotes() { + for i, l := range lines { + lines[i] = codeQuotes(l); + } +} + +func codeQuotes(l []byte) []byte { + if bytes.HasPrefix(l, preStart) { + return l + } + n := bytes.Index(l, quote); + if n < 0 { + return l + } + buf := new(bytes.Buffer); + inQuote := false; + for _, c := range l { + if c == '"' { + if inQuote { + buf.WriteString("") + } else { + buf.WriteString("") + } + inQuote = !inQuote + } else { + buf.WriteByte(c) + } + } + return buf.Bytes(); +} + +// drop trailing newline +func trim(l []byte) []byte { + n := len(l); + if n > 0 && l[n-1] == '\n' { + return l[0:n-1] + } + return l +} + +// expand tabs to 4 spaces. don't worry about columns. +func expandTabs(l []byte) []byte { + j := 0; // position in linebuf. + for _, c := range l { + if c == '\t' { + for k := 0; k < 4; k++ { + linebuf[j] = ' '; + j++; + } + } else { + linebuf[j] = c; + j++; + } + } + return linebuf[0:j]; +} diff --git a/doc/makehtml b/doc/makehtml new file mode 100755 index 00000000000..c9ac0c8e8dd --- /dev/null +++ b/doc/makehtml @@ -0,0 +1,31 @@ +#!/bin/sh +# Copyright 2009 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. + +set -e + +TXT=${1:-go_tutorial.txt} # input file +HTML=$(basename $TXT .txt).html # output file (basename) +TMP=TEMP.txt # input to htmlgen + +if ! test -w $HTML +then + echo 1>&2 makehtml: cannot open $HTML for write + exit 1 +fi + +if grep -q '^--PROG' $TXT +then + echo >&2 makehtml: processing PROG sections + <$TXT >$TMP awk ' + /^--PROG/ { system("sh ./prog.sh "$2" "$3" "$4" "); getline } + /^/ {print} + ' +else + cp $TXT $TMP +fi + +make htmlgen && ./htmlgen < $TMP > $HTML + +rm -f $TMP