mirror of
https://github.com/golang/go
synced 2024-11-25 00:17:58 -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:
parent
327b6c637e
commit
bf983a0df2
11
doc/Makefile
Normal file
11
doc/Makefile
Normal 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
|
@ -1,3 +0,0 @@
|
||||
<!-- Let's Go -->
|
||||
|
||||
<h2>Introduction</h2>
|
@ -1,15 +1,14 @@
|
||||
<!-- Let's Go -->
|
||||
|
||||
<h2>Introduction</h2>
|
||||
<p>
|
||||
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
|
||||
<a href=/doc/go_spec.html>language specification.</a>
|
||||
<a href='/doc/go_spec.html'>language specification.</a>
|
||||
<p>
|
||||
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 <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>
|
||||
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++:
|
||||
<pre>
|
||||
/* ... */
|
||||
// ...
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
Later we'll have much more to say about printing.
|
||||
<p>
|
||||
<h2>Echo</h2>
|
||||
@ -94,8 +93,8 @@ But it's not necessary to do so; we could have said
|
||||
<pre>
|
||||
const Space = " "
|
||||
const Newline = "\n"
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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>
|
||||
a parenthesized list of declarations.
|
||||
@ -128,8 +127,8 @@ The declaration statement has the form
|
||||
<p>
|
||||
<pre>
|
||||
var s string = "";
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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.
|
||||
<p>
|
||||
@ -139,14 +138,14 @@ We could write
|
||||
<p>
|
||||
<pre>
|
||||
var s = "";
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
or we could go even shorter and write the idiom
|
||||
<p>
|
||||
<pre>
|
||||
s := "";
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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
|
||||
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>
|
||||
<pre>
|
||||
os.Exit(1)
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
The <code>os</code> package contains other essentials for getting
|
||||
started; for instance, <code>os.Args</code> is an array used by the
|
||||
<code>flag</code> package to access the command-line arguments.
|
||||
@ -213,8 +212,8 @@ a <code>string</code> value:
|
||||
<pre>
|
||||
s[0] = 'x';
|
||||
(*p)[1] = 'y';
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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.
|
||||
<p>
|
||||
@ -225,8 +224,8 @@ Arrays are declared like this:
|
||||
<p>
|
||||
<pre>
|
||||
var array_of_int [10]int;
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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>.
|
||||
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>
|
||||
<pre>
|
||||
s := sum(&[...]int{1,2,3});
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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:
|
||||
<p>
|
||||
<pre>
|
||||
s := sum([]int{1,2,3});
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
There are also maps, which you can initialize like this:
|
||||
<p>
|
||||
<pre>
|
||||
m := map[string] int {"one":1 , "two":2}
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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,
|
||||
slices, and maps.
|
||||
@ -317,14 +316,14 @@ returns a pointer to the allocated storage.
|
||||
<pre>
|
||||
type T struct { a, b int }
|
||||
var t *T = new(T);
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
or the more idiomatic
|
||||
<p>
|
||||
<pre>
|
||||
t := new(T);
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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 <code>make()</code>:
|
||||
<p>
|
||||
<pre>
|
||||
m := make(map[string] int);
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
This statement initializes a new map ready to store entries.
|
||||
If you just declare the map, as in
|
||||
<p>
|
||||
<pre>
|
||||
var m map[string] int;
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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
|
||||
existing map.
|
||||
@ -360,8 +359,8 @@ too little precision to represent the value.
|
||||
<p>
|
||||
<pre>
|
||||
const hard_eight = (1 << 100) >> 97 // legal
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
There are nuances that deserve redirection to the legalese of the
|
||||
language specification but here are some illustrative examples:
|
||||
<p>
|
||||
@ -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
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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
|
||||
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
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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.
|
||||
<p>
|
||||
@ -585,8 +584,8 @@ Finally we can run the program:
|
||||
hello, world
|
||||
can't open file; err=No such file or directory
|
||||
%
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
<h2>Rotting cats</h2>
|
||||
<p>
|
||||
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>
|
||||
<pre>
|
||||
Printf(format string, v ...) (n int, errno os.Error)
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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
|
||||
an empty interface variable (<code>interface {}</code>) that is then unpacked
|
||||
@ -888,8 +887,8 @@ prints
|
||||
<p>
|
||||
<pre>
|
||||
18446744073709551615 -1
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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
|
||||
<p>
|
||||
@ -904,8 +903,8 @@ is
|
||||
<p>
|
||||
<pre>
|
||||
18446744073709551615 {77 Sunset Strip} [1 2 3 4]
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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.
|
||||
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>
|
||||
<pre>
|
||||
77 Sunset Strip
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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
|
||||
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 {
|
||||
String() string
|
||||
}
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
<pre>
|
||||
s, ok := v.(Stringer); // Test whether v implements "String()"
|
||||
if ok {
|
||||
result = s.String()
|
||||
} else {
|
||||
result = default_output(v)
|
||||
}
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
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>
|
||||
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 {
|
||||
Write(p []byte) (n int, err os.Error);
|
||||
}
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
(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.)
|
||||
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>
|
||||
<pre>
|
||||
go sum(huge_array); // calculate sum in the background
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
If you want to know when the calculation is done, pass a channel
|
||||
on which it can report back:
|
||||
<p>
|
||||
@ -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
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
Back to our prime sieve. Here's how the sieve pipeline is stitched
|
||||
together:
|
||||
<p>
|
||||
|
@ -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
|
||||
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
|
||||
<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
|
||||
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
|
||||
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.
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
192
doc/htmlgen.go
Normal file
192
doc/htmlgen.go
Normal 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
31
doc/makehtml
Executable 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
|
Loading…
Reference in New Issue
Block a user