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:
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 -->
|
<!-- 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(&[...]int{1,2,3});
|
s := sum(&[...]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 << 100) >> 97 // legal
|
const hard_eight = (1 << 100) >> 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 := <-ch; // wait for, and retrieve, result
|
result := <-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>
|
||||||
|
@ -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(&[...]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 << 100) >> 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 := <-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
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