1
0
mirror of https://github.com/golang/go synced 2024-11-25 01:27:56 -07:00

bye-bye to old makehtml.

go can do the job just fine.

R=rsc
DELTA=290  (209 added, 13 deleted, 68 changed)
OCL=35699
CL=35699
This commit is contained in:
Rob Pike 2009-10-13 22:10:16 -07:00
parent 327b6c637e
commit bf983a0df2
6 changed files with 277 additions and 41 deletions

11
doc/Makefile Normal file
View File

@ -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

View File

@ -1,3 +0,0 @@
<!-- Let's Go -->
<h2>Introduction</h2>

View File

@ -1,15 +1,14 @@
<!-- Let's Go --> <!-- Let's Go -->
<h2>Introduction</h2> <h2>Introduction</h2>
<p> <p>
This document is a tutorial introduction to the basics of the Go systems programming 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 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 guide to the language; at the moment the document closest to that is the
<a href=/doc/go_spec.html>language specification.</a> <a href='/doc/go_spec.html'>language specification.</a>
<p> <p>
The presentation proceeds through a series of modest programs to illustrate 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 key features of the language. All the programs work (at time of writing) and are
checked into the repository in the directory <a href=/doc/progs><code>/doc/progs</code></a>. checked into the repository in the directory <a href='/doc/progs'><code>/doc/progs/</code></a>.
<p> <p>
Program snippets are annotated with the line number in the original file; for Program snippets are annotated with the line number in the original file; for
cleanliness, blank lines remain blank. cleanliness, blank lines remain blank.
@ -45,8 +44,8 @@ The comment convention is the same as in C++:
<pre> <pre>
/* ... */ /* ... */
// ... // ...
</pre> </pre>
<p>
Later we'll have much more to say about printing. Later we'll have much more to say about printing.
<p> <p>
<h2>Echo</h2> <h2>Echo</h2>
@ -94,8 +93,8 @@ But it's not necessary to do so; we could have said
<pre> <pre>
const Space = " " const Space = " "
const Newline = "\n" const Newline = "\n"
</pre> </pre>
<p>
Semicolons aren't needed here; in fact, semicolons are unnecessary after any Semicolons aren't needed here; in fact, semicolons are unnecessary after any
top-level declaration, even though they are needed as separators <i>within</i> top-level declaration, even though they are needed as separators <i>within</i>
a parenthesized list of declarations. a parenthesized list of declarations.
@ -128,8 +127,8 @@ The declaration statement has the form
<p> <p>
<pre> <pre>
var s string = ""; var s string = "";
</pre> </pre>
<p>
This is the <code>var</code> keyword, followed by the name of the variable, followed by This is the <code>var</code> keyword, followed by the name of the variable, followed by
its type, followed by an equals sign and an initial value for the variable. its type, followed by an equals sign and an initial value for the variable.
<p> <p>
@ -139,14 +138,14 @@ We could write
<p> <p>
<pre> <pre>
var s = ""; var s = "";
</pre> </pre>
<p>
or we could go even shorter and write the idiom or we could go even shorter and write the idiom
<p> <p>
<pre> <pre>
s := ""; s := "";
</pre> </pre>
<p>
The <code>:=</code> operator is used a lot in Go to represent an initializing declaration. The <code>:=</code> operator is used a lot in Go to represent an initializing declaration.
(For those who know Sawzall, its <code>:=</code> construct is the same, but notice (For those who know Sawzall, its <code>:=</code> construct is the same, but notice
that Go has no colon after the name in a full <code>var</code> declaration. that Go has no colon after the name in a full <code>var</code> declaration.
@ -177,8 +176,8 @@ It's defined that way. Falling off the end of <code>main.main</code> means
<p> <p>
<pre> <pre>
os.Exit(1) os.Exit(1)
</pre> </pre>
<p>
The <code>os</code> package contains other essentials for getting The <code>os</code> package contains other essentials for getting
started; for instance, <code>os.Args</code> is an array used by the started; for instance, <code>os.Args</code> is an array used by the
<code>flag</code> package to access the command-line arguments. <code>flag</code> package to access the command-line arguments.
@ -213,8 +212,8 @@ a <code>string</code> value:
<pre> <pre>
s[0] = 'x'; s[0] = 'x';
(*p)[1] = 'y'; (*p)[1] = 'y';
</pre> </pre>
<p>
In C++ terms, Go strings are a bit like <code>const strings</code>, while pointers In C++ terms, Go strings are a bit like <code>const strings</code>, while pointers
to strings are analogous to <code>const string</code> references. to strings are analogous to <code>const string</code> references.
<p> <p>
@ -225,8 +224,8 @@ Arrays are declared like this:
<p> <p>
<pre> <pre>
var array_of_int [10]int; var array_of_int [10]int;
</pre> </pre>
<p>
Arrays, like strings, are values, but they are mutable. This differs Arrays, like strings, are values, but they are mutable. This differs
from C, in which <code>array_of_int</code> would be usable as a pointer to <code>int</code>. from C, in which <code>array_of_int</code> would be usable as a pointer to <code>int</code>.
In Go, since arrays are values, it's meaningful (and useful) to talk In Go, since arrays are values, it's meaningful (and useful) to talk
@ -286,21 +285,21 @@ elements for you, use <code>...</code> as the array size:
<p> <p>
<pre> <pre>
s := sum(&amp;[...]int{1,2,3}); s := sum(&amp;[...]int{1,2,3});
</pre> </pre>
<p>
In practice, though, unless you're meticulous about storage layout within a In practice, though, unless you're meticulous about storage layout within a
data structure, a slice itself - using empty brackets and no <code>&</code> - is all you need: data structure, a slice itself - using empty brackets and no <code>&</code> - is all you need:
<p> <p>
<pre> <pre>
s := sum([]int{1,2,3}); s := sum([]int{1,2,3});
</pre> </pre>
<p>
There are also maps, which you can initialize like this: There are also maps, which you can initialize like this:
<p> <p>
<pre> <pre>
m := map[string] int {"one":1 , "two":2} m := map[string] int {"one":1 , "two":2}
</pre> </pre>
<p>
The built-in function <code>len()</code>, which returns number of elements, The built-in function <code>len()</code>, which returns number of elements,
makes its first appearance in <code>sum</code>. It works on strings, arrays, makes its first appearance in <code>sum</code>. It works on strings, arrays,
slices, and maps. slices, and maps.
@ -317,14 +316,14 @@ returns a pointer to the allocated storage.
<pre> <pre>
type T struct { a, b int } type T struct { a, b int }
var t *T = new(T); var t *T = new(T);
</pre> </pre>
<p>
or the more idiomatic or the more idiomatic
<p> <p>
<pre> <pre>
t := new(T); t := new(T);
</pre> </pre>
<p>
Some types - maps, slices, and channels (see below) - have reference semantics. 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 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 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 <code>make()</code>:
<p> <p>
<pre> <pre>
m := make(map[string] int); m := make(map[string] int);
</pre> </pre>
<p>
This statement initializes a new map ready to store entries. This statement initializes a new map ready to store entries.
If you just declare the map, as in If you just declare the map, as in
<p> <p>
<pre> <pre>
var m map[string] int; var m map[string] int;
</pre> </pre>
<p>
it creates a <code>nil</code> reference that cannot hold anything. To use the map, it creates a <code>nil</code> reference that cannot hold anything. To use the map,
you must first initialize the reference using <code>make()</code> or by assignment to an you must first initialize the reference using <code>make()</code> or by assignment to an
existing map. existing map.
@ -360,8 +359,8 @@ too little precision to represent the value.
<p> <p>
<pre> <pre>
const hard_eight = (1 &lt;&lt; 100) &gt;&gt; 97 // legal const hard_eight = (1 &lt;&lt; 100) &gt;&gt; 97 // legal
</pre> </pre>
<p>
There are nuances that deserve redirection to the legalese of the There are nuances that deserve redirection to the legalese of the
language specification but here are some illustrative examples: language specification but here are some illustrative examples:
<p> <p>
@ -373,8 +372,8 @@ language specification but here are some illustrative examples:
x := 1.5 // a float x := 1.5 // a float
i3div2 := 3/2 // integer division - result is 1 i3div2 := 3/2 // integer division - result is 1
f3div2 := 3./2. // floating point division - result is 1.5 f3div2 := 3./2. // floating point division - result is 1.5
</pre> </pre>
<p>
Conversions only work for simple cases such as converting <code>ints</code> of one Conversions only work for simple cases such as converting <code>ints</code> of one
sign or size to another, and between <code>ints</code> and <code>floats</code>, plus a few other sign or size to another, and between <code>ints</code> and <code>floats</code>, plus a few other
simple cases. There are no automatic numeric conversions of any kind in Go, 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.fd = fd;
n.name = name; n.name = name;
return n return n
</pre> </pre>
<p>
but for simple structures like <code>File</code> it's easier to return the address of a nonce but for simple structures like <code>File</code> it's easier to return the address of a nonce
composite literal, as is done here on line 21. composite literal, as is done here on line 21.
<p> <p>
@ -585,8 +584,8 @@ Finally we can run the program:
hello, world hello, world
can't open file; err=No such file or directory can't open file; err=No such file or directory
% %
</pre> </pre>
<p>
<h2>Rotting cats</h2> <h2>Rotting cats</h2>
<p> <p>
Building on the <code>file</code> package, here's a simple version of the Unix utility <code>cat(1)</code>, Building on the <code>file</code> package, here's a simple version of the Unix utility <code>cat(1)</code>,
@ -864,8 +863,8 @@ Within the <code>fmt</code> package, <code>Printf</code> is declared with this s
<p> <p>
<pre> <pre>
Printf(format string, v ...) (n int, errno os.Error) Printf(format string, v ...) (n int, errno os.Error)
</pre> </pre>
<p>
That <code>...</code> represents the variadic argument list that in C would That <code>...</code> represents the variadic argument list that in C would
be handled using the <code>stdarg.h</code> macros, but in Go is passed using be handled using the <code>stdarg.h</code> macros, but in Go is passed using
an empty interface variable (<code>interface {}</code>) that is then unpacked an empty interface variable (<code>interface {}</code>) that is then unpacked
@ -888,8 +887,8 @@ prints
<p> <p>
<pre> <pre>
18446744073709551615 -1 18446744073709551615 -1
</pre> </pre>
<p>
In fact, if you're lazy the format <code>%v</code> will print, in a simple In fact, if you're lazy the format <code>%v</code> will print, in a simple
appropriate style, any value, even an array or structure. The output of appropriate style, any value, even an array or structure. The output of
<p> <p>
@ -904,8 +903,8 @@ is
<p> <p>
<pre> <pre>
18446744073709551615 {77 Sunset Strip} [1 2 3 4] 18446744073709551615 {77 Sunset Strip} [1 2 3 4]
</pre> </pre>
<p>
You can drop the formatting altogether if you use <code>Print</code> or <code>Println</code> You can drop the formatting altogether if you use <code>Print</code> or <code>Println</code>
instead of <code>Printf</code>. Those routines do fully automatic formatting. instead of <code>Printf</code>. Those routines do fully automatic formatting.
The <code>Print</code> function just prints its elements out using the equivalent The <code>Print</code> 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
<p> <p>
<pre> <pre>
77 Sunset Strip 77 Sunset Strip
</pre> </pre>
<p>
Observe that the <code>String()</code> method calls <code>Sprint</code> (the obvious Go Observe that the <code>String()</code> method calls <code>Sprint</code> (the obvious Go
variant that returns a string) to do its formatting; special formatters variant that returns a string) to do its formatting; special formatters
can use the <code>fmt</code> library recursively. can use the <code>fmt</code> library recursively.
@ -970,15 +969,17 @@ Schematically, given a value <code>v</code>, it does this:
type Stringer interface { type Stringer interface {
String() string String() string
} }
</pre>
<p>
<pre>
s, ok := v.(Stringer); // Test whether v implements "String()" s, ok := v.(Stringer); // Test whether v implements "String()"
if ok { if ok {
result = s.String() result = s.String()
} else { } else {
result = default_output(v) result = default_output(v)
} }
</pre> </pre>
<p>
The code uses a ``type assertion'' (<code>v.(Stringer)</code>) to test if the value stored in The code uses a ``type assertion'' (<code>v.(Stringer)</code>) to test if the value stored in
<code>v</code> satisfies the <code>Stringer</code> interface; if it does, <code>s</code> <code>v</code> satisfies the <code>Stringer</code> interface; if it does, <code>s</code>
will become an interface variable implementing the method and <code>ok</code> will will become an interface variable implementing the method and <code>ok</code> will
@ -1000,8 +1001,8 @@ interface type defined in the <code>io</code> library:
type Writer interface { type Writer interface {
Write(p []byte) (n int, err os.Error); Write(p []byte) (n int, err os.Error);
} }
</pre> </pre>
<p>
(This interface is another conventional name, this time for <code>Write</code>; there are also (This interface is another conventional name, this time for <code>Write</code>; there are also
<code>io.Reader</code>, <code>io.ReadWriter</code>, and so on.) <code>io.Reader</code>, <code>io.ReadWriter</code>, and so on.)
Thus you can call <code>Fprintf</code> on any type that implements a standard <code>Write()</code> Thus you can call <code>Fprintf</code> on any type that implements a standard <code>Write()</code>
@ -1081,8 +1082,8 @@ computation but in the same address space:
<p> <p>
<pre> <pre>
go sum(huge_array); // calculate sum in the background go sum(huge_array); // calculate sum in the background
</pre> </pre>
<p>
If you want to know when the calculation is done, pass a channel If you want to know when the calculation is done, pass a channel
on which it can report back: on which it can report back:
<p> <p>
@ -1091,8 +1092,8 @@ on which it can report back:
go sum(huge_array, ch); go sum(huge_array, ch);
// ... do something else for a while // ... do something else for a while
result := &lt;-ch; // wait for, and retrieve, result result := &lt;-ch; // wait for, and retrieve, result
</pre> </pre>
<p>
Back to our prime sieve. Here's how the sieve pipeline is stitched Back to our prime sieve. Here's how the sieve pipeline is stitched
together: together:
<p> <p>

View File

@ -1,14 +1,15 @@
Let's Go <!-- Let's Go -->
Introduction
---- ----
This document is a tutorial introduction to the basics of the Go systems programming 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 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 guide to the language; at the moment the document closest to that is the
<a href=/doc/go_spec.html>language specification.</a> <a href='/doc/go_spec.html'>language specification.</a>
The presentation proceeds through a series of modest programs to illustrate 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 key features of the language. All the programs work (at time of writing) and are
checked into the repository in the directory <a href=/doc/progs>"/doc/progs"</a>. checked into the repository in the directory <a href='/doc/progs'>"/doc/progs/"</a>.
Program snippets are annotated with the line number in the original file; for Program snippets are annotated with the line number in the original file; for
cleanliness, blank lines remain blank. 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 If you are creating a regular array but want the compiler to count the
elements for you, use "..." as the array size: elements for you, use "..." as the array size:
s := sum(&[...]int{1,2,3}); s := sum(&amp;[...]int{1,2,3});
In practice, though, unless you're meticulous about storage layout within a 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: 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 can overflow only when they are assigned to an integer variable with
too little precision to represent the value. too little precision to represent the value.
const hard_eight = (1 << 100) >> 97 // legal const hard_eight = (1 &lt;&lt; 100) &gt;&gt; 97 // legal
There are nuances that deserve redirection to the legalese of the There are nuances that deserve redirection to the legalese of the
language specification but here are some illustrative examples: language specification but here are some illustrative examples:
@ -542,7 +543,7 @@ to implement the three methods for that type, like this:
Printing Printing
--- ----
The examples of formatted printing so far have been modest. In this section 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. 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); ch := make(chan int);
go sum(huge_array, ch); go sum(huge_array, ch);
// ... do something else for a while // ... do something else for a while
result := <-ch; // wait for, and retrieve, result result := &lt;-ch; // wait for, and retrieve, result
Back to our prime sieve. Here's how the sieve pipeline is stitched Back to our prime sieve. Here's how the sieve pipeline is stitched
together: 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 There's a lot more to Go programming and concurrent programming in general but this
quick tour should give you some of the basics. quick tour should give you some of the basics.
</table>
</body>
</html>

192
doc/htmlgen.go Normal file
View File

@ -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 <pre> blocks
// - blank lines become <p> marks
// - "quoted strings" become <code>quoted strings</code>
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("<pre>");
preEnd = strings.Bytes("</pre>\n");
pp = strings.Bytes("<p>\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 <pre> 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 <pre>-bounded slice
func foldTabs(i int) (n int, line []byte) {
buf := new(bytes.Buffer);
buf.WriteString("<pre>\n");
for i < len(lines) {
if !bytes.HasPrefix(lines[i], tab) {
break;
}
buf.Write(lines[i]);
n++;
i++;
}
buf.WriteString("</pre>\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("<h2>" + string(trim(lines[i-1])) + "</h2>\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("</code>")
} else {
buf.WriteString("<code>")
}
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];
}

31
doc/makehtml Executable file
View File

@ -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