Commit a40065ac authored by Russ Cox's avatar Russ Cox

cmd/godoc: add support for serving templates

doc: convert to use godoc built-in templates

tmpltohtml is gone, to avoid having a second copy of the code.
Instead, godoc -url /doc/go1.html will print the actual HTML
served for that URL.  "make" will generate files named go1.rawhtml
etc, which can be fed through tidy.

It can be hard to tell from the codereview diffs, but all the
tmpl files have been renamed to be html files and then
have "Template": true added.

R=golang-dev, adg, r, gri
CC=golang-dev
https://golang.org/cl/5782046
parent e38c5fb2
......@@ -2,21 +2,18 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
HTML=\
articles/defer_panic_recover.html\
articles/error_handling.html\
articles/slices_usage_and_internals.html\
articles/laws_of_reflection.html\
effective_go.html\
go1.html\
RAWHTML=\
articles/defer_panic_recover.rawhtml\
articles/error_handling.rawhtml\
articles/slices_usage_and_internals.rawhtml\
articles/laws_of_reflection.rawhtml\
effective_go.rawhtml\
go1.rawhtml\
all: tmpltohtml $(HTML)
all: $(RAWHTML)
tmpltohtml: tmpltohtml.go
go build tmpltohtml.go
%.html: %.tmpl tmpltohtml
./tmpltohtml $*.tmpl > $@
%.rawhtml: %.html
godoc -url /doc/$* >$@
clean:
rm -f $(HTML) tmpltohtml
rm -f $(RAWHTML)
<!--{
"Title": "Defer, Panic, and Recover"
"Title": "Defer, Panic, and Recover",
"Template": true
}-->
<!--
DO NOT EDIT: created by
tmpltohtml articles/defer_panic_recover.tmpl
-->
<p>
Go has the usual mechanisms for control flow: if, for, switch, goto. It also
......@@ -23,23 +20,7 @@ For example, let's look at a function that opens two files and copies the
contents of one file to the other:
</p>
<pre><!--{{code "progs/defer.go" `/func CopyFile/` `/STOP/`}}
-->func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
dst, err := os.Create(dstName)
if err != nil {
return
}
written, err = io.Copy(dst, src)
dst.Close()
src.Close()
return
}</pre>
{{code "/doc/progs/defer.go" `/func CopyFile/` `/STOP/`}}
<p>
This works, but there is a bug. If the call to os.Create fails, the
......@@ -50,22 +31,7 @@ noticed and resolved. By introducing defer statements we can ensure that the
files are always closed:
</p>
<pre><!--{{code "progs/defer2.go" `/func CopyFile/` `/STOP/`}}
-->func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
defer src.Close()
dst, err := os.Create(dstName)
if err != nil {
return
}
defer dst.Close()
return io.Copy(dst, src)
}</pre>
{{code "/doc/progs/defer2.go" `/func CopyFile/` `/STOP/`}}
<p>
Defer statements allow us to think about closing each file right after opening
......@@ -88,13 +54,7 @@ In this example, the expression "i" is evaluated when the Println call is
deferred. The deferred call will print "0" after the function returns.
</p>
<pre><!--{{code "progs/defer.go" `/func a/` `/STOP/`}}
-->func a() {
i := 0
defer fmt.Println(i)
i++
return
}</pre>
{{code "/doc/progs/defer.go" `/func a/` `/STOP/`}}
<p>
2. <i>Deferred function calls are executed in Last In First Out order
......@@ -105,12 +65,7 @@ deferred. The deferred call will print "0" after the function returns.
This function prints "3210":
</p>
<pre><!--{{code "progs/defer.go" `/func b/` `/STOP/`}}
-->func b() {
for i := 0; i &lt; 4; i++ {
defer fmt.Print(i)
}
}</pre>
{{code "/doc/progs/defer.go" `/func b/` `/STOP/`}}
<p>
3. <i>Deferred functions may read and assign to the returning function's named
......@@ -122,11 +77,7 @@ In this example, a deferred function increments the return value i <i>after</i>
the surrounding function returns. Thus, this function returns 2:
</p>
<pre><!--{{code "progs/defer.go" `/func c/` `/STOP/`}}
-->func c() (i int) {
defer func() { i++ }()
return 1
}</pre>
{{code "/doc/progs/defer.go" `/func c/` `/STOP/`}}
<p>
This is convenient for modifying the error return value of a function; we will
......@@ -156,36 +107,7 @@ to panic and resume normal execution.
Here's an example program that demonstrates the mechanics of panic and defer:
</p>
<pre><!--{{code "progs/defer2.go" `/package main/` `/STOP/`}}
-->package main
import &#34;fmt&#34;
func main() {
f()
fmt.Println(&#34;Returned normally from f.&#34;)
}
func f() {
defer func() {
if r := recover(); r != nil {
fmt.Println(&#34;Recovered in f&#34;, r)
}
}()
fmt.Println(&#34;Calling g.&#34;)
g(0)
fmt.Println(&#34;Returned normally from g.&#34;)
}
func g(i int) {
if i &gt; 3 {
fmt.Println(&#34;Panicking!&#34;)
panic(fmt.Sprintf(&#34;%v&#34;, i))
}
defer fmt.Println(&#34;Defer in g&#34;, i)
fmt.Println(&#34;Printing in g&#34;, i)
g(i + 1)
}</pre>
{{code "/doc/progs/defer2.go" `/package main/` `/STOP/`}}
<p>
The function g takes the int i, and panics if i is greater than 3, or else it
......
<!--{
"Title": "Defer, Panic, and Recover"
}-->
{{donotedit}}
<p>
Go has the usual mechanisms for control flow: if, for, switch, goto. It also
has the go statement to run code in a separate goroutine. Here I'd like to
discuss some of the less common ones: defer, panic, and recover.
</p>
<p>
A <b>defer statement</b> pushes a function call onto a list. The list of saved
calls is executed after the surrounding function returns. Defer is commonly
used to simplify functions that perform various clean-up actions.
</p>
<p>
For example, let's look at a function that opens two files and copies the
contents of one file to the other:
</p>
{{code "progs/defer.go" `/func CopyFile/` `/STOP/`}}
<p>
This works, but there is a bug. If the call to os.Create fails, the
function will return without closing the source file. This can be easily
remedied by putting a call to src.Close() before the second return statement,
but if the function were more complex the problem might not be so easily
noticed and resolved. By introducing defer statements we can ensure that the
files are always closed:
</p>
{{code "progs/defer2.go" `/func CopyFile/` `/STOP/`}}
<p>
Defer statements allow us to think about closing each file right after opening
it, guaranteeing that, regardless of the number of return statements in the
function, the files <i>will</i> be closed.
</p>
<p>
The behavior of defer statements is straightforward and predictable. There are
three simple rules:
</p>
<p>
1. <i>A deferred function's arguments are evaluated when the defer statement is
evaluated.</i>
</p>
<p>
In this example, the expression "i" is evaluated when the Println call is
deferred. The deferred call will print "0" after the function returns.
</p>
{{code "progs/defer.go" `/func a/` `/STOP/`}}
<p>
2. <i>Deferred function calls are executed in Last In First Out order
</i>after<i> the surrounding function returns.</i>
</p>
<p>
This function prints "3210":
</p>
{{code "progs/defer.go" `/func b/` `/STOP/`}}
<p>
3. <i>Deferred functions may read and assign to the returning function's named
return values.</i>
</p>
<p>
In this example, a deferred function increments the return value i <i>after</i>
the surrounding function returns. Thus, this function returns 2:
</p>
{{code "progs/defer.go" `/func c/` `/STOP/`}}
<p>
This is convenient for modifying the error return value of a function; we will
see an example of this shortly.
</p>
<p>
<b>Panic</b> is a built-in function that stops the ordinary flow of control and
begins <i>panicking</i>. When the function F calls panic, execution of F stops,
any deferred functions in F are executed normally, and then F returns to its
caller. To the caller, F then behaves like a call to panic. The process
continues up the stack until all functions in the current goroutine have
returned, at which point the program crashes. Panics can be initiated by
invoking panic directly. They can also be caused by runtime errors, such as
out-of-bounds array accesses.
</p>
<p>
<b>Recover</b> is a built-in function that regains control of a panicking
goroutine. Recover is only useful inside deferred functions. During normal
execution, a call to recover will return nil and have no other effect. If the
current goroutine is panicking, a call to recover will capture the value given
to panic and resume normal execution.
</p>
<p>
Here's an example program that demonstrates the mechanics of panic and defer:
</p>
{{code "progs/defer2.go" `/package main/` `/STOP/`}}
<p>
The function g takes the int i, and panics if i is greater than 3, or else it
calls itself with the argument i+1. The function f defers a function that calls
recover and prints the recovered value (if it is non-nil). Try to picture what
the output of this program might be before reading on.
</p>
<p>
The program will output:
</p>
<pre>Calling g.
Printing in g 0
Printing in g 1
Printing in g 2
Printing in g 3
Panicking!
Defer in g 3
Defer in g 2
Defer in g 1
Defer in g 0
Recovered in f 4
Returned normally from f.</pre>
<p>
If we remove the deferred function from f the panic is not recovered and
reaches the top of the goroutine's call stack, terminating the program. This
modified program will output:
</p>
<pre>Calling g.
Printing in g 0
Printing in g 1
Printing in g 2
Printing in g 3
Panicking!
Defer in g 3
Defer in g 2
Defer in g 1
Defer in g 0
panic: 4
panic PC=0x2a9cd8
[stack trace omitted]</pre>
<p>
For a real-world example of <b>panic</b> and <b>recover</b>, see the
<a href="/pkg/encoding/json/">json package</a> from the Go standard library.
It decodes JSON-encoded data with a set of recursive functions.
When malformed JSON is encountered, the parser calls panic to unwind the
stack to the top-level function call, which recovers from the panic and returns
an appropriate error value (see the 'error' and 'unmarshal' functions in
<a href="/src/pkg/encoding/json/decode.go">decode.go</a>).
</p>
<p>
The convention in the Go libraries is that even when a package uses panic
internally, its external API still presents explicit error return values.
</p>
<p>
Other uses of <b>defer</b> (beyond the file.Close() example given earlier)
include releasing a mutex:
</p>
<pre>mu.Lock()
defer mu.Unlock()</pre>
<p>
printing a footer:
</p>
<pre>printHeader()
defer printFooter()</pre>
<p>
and more.
</p>
<p>
In summary, the defer statement (with or without panic and recover) provides an
unusual and powerful mechanism for control flow. It can be used to model a
number of features implemented by special-purpose structures in other
programming languages. Try it out.
</p>
This diff is collapsed.
This diff is collapsed.
<!--{
"Title": "The Laws of Reflection"
"Title": "The Laws of Reflection",
"Template": true
}-->
<!--
DO NOT EDIT: created by
tmpltohtml articles/laws_of_reflection.tmpl
-->
<p>
Reflection in computing is the
......@@ -36,11 +32,7 @@ exactly one type known and fixed at compile time: <code>int</code>,
and so on. If we declare
</p>
<pre><!--{{code "progs/interface.go" `/type MyInt/` `/STOP/`}}
-->type MyInt int
var i int
var j MyInt</pre>
{{code "/doc/progs/interface.go" `/type MyInt/` `/STOP/`}}
<p>
then <code>i</code> has type <code>int</code> and <code>j</code>
......@@ -60,16 +52,7 @@ interface's methods. A well-known pair of examples is
"http://golang.org/pkg/io/">io package</a>:
</p>
<pre><!--{{code "progs/interface.go" `/// Reader/` `/STOP/`}}
-->// Reader is the interface that wraps the basic Read method.
type Reader interface {
Read(p []byte) (n int, err error)
}
// Writer is the interface that wraps the basic Write method.
type Writer interface {
Write(p []byte) (n int, err error)
}</pre>
{{code "/doc/progs/interface.go" `/// Reader/` `/STOP/`}}
<p>
Any type that implements a <code>Read</code> (or
......@@ -80,12 +63,7 @@ purposes of this discussion, that means that a variable of type
<code>Read</code> method:
</p>
<pre><!--{{code "progs/interface.go" `/func readers/` `/STOP/`}}
--> var r io.Reader
r = os.Stdin
r = bufio.NewReader(r)
r = new(bytes.Buffer)
// and so on</pre>
{{code "/doc/progs/interface.go" `/func readers/` `/STOP/`}}
<p>
It's important to be clear that whatever concrete value
......@@ -138,13 +116,7 @@ that implements the interface and the type describes the full type
of that item. For instance, after
</p>
<pre><!--{{code "progs/interface.go" `/func typeAssertions/` `/STOP/`}}
--> var r io.Reader
tty, err := os.OpenFile(&#34;/dev/tty&#34;, os.O_RDWR, 0)
if err != nil {
return nil, err
}
r = tty</pre>
{{code "/doc/progs/interface.go" `/func typeAssertions/` `/STOP/`}}
<p>
<code>r</code> contains, schematically, the (value, type) pair,
......@@ -156,9 +128,7 @@ the type information about that value. That's why we can do things
like this:
</p>
<pre><!--{{code "progs/interface.go" `/var w io.Writer/` `/STOP/`}}
--> var w io.Writer
w = r.(io.Writer)</pre>
{{code "/doc/progs/interface.go" `/var w io.Writer/` `/STOP/`}}
<p>
The expression in this assignment is a type assertion; what it
......@@ -176,9 +146,7 @@ methods.
Continuing, we can do this:
</p>
<pre><!--{{code "progs/interface.go" `/var empty interface{}/` `/STOP/`}}
--> var empty interface{}
empty = w</pre>
{{code "/doc/progs/interface.go" `/var empty interface{}/` `/STOP/`}}
<p>
and our empty interface value <code>e</code> will again contain
......@@ -232,18 +200,7 @@ now.)
Let's start with <code>TypeOf</code>:
</p>
<pre><!--{{code "progs/interface2.go" `/package main/` `/STOP main/`}}
-->package main
import (
&#34;fmt&#34;
&#34;reflect&#34;
)
func main() {
var x float64 = 3.4
fmt.Println(&#34;type:&#34;, reflect.TypeOf(x))
}</pre>
{{code "/doc/progs/interface2.go" `/package main/` `/STOP main/`}}
<p>
This program prints
......@@ -281,9 +238,7 @@ value (from here on we'll elide the boilerplate and focus just on
the executable code):
</p>
<pre><!--{{code "progs/interface2.go" `/var x/` `/STOP/`}}
--> var x float64 = 3.4
fmt.Println(&#34;type:&#34;, reflect.TypeOf(x))</pre>
{{code "/doc/progs/interface2.go" `/var x/` `/STOP/`}}
<p>
prints
......@@ -307,12 +262,7 @@ on. Also methods on <code>Value</code> with names like
<code>int64</code> and <code>float64</code>) stored inside:
</p>
<pre><!--{{code "progs/interface2.go" `/START f1/` `/STOP/`}}
--> var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println(&#34;type:&#34;, v.Type())
fmt.Println(&#34;kind is float64:&#34;, v.Kind() == reflect.Float64)
fmt.Println(&#34;value:&#34;, v.Float())</pre>
{{code "/doc/progs/interface2.go" `/START f1/` `/STOP/`}}
<p>
prints
......@@ -342,12 +292,7 @@ instance. That is, the <code>Int</code> method of
necessary to convert to the actual type involved:
</p>
<pre><!--{{code "progs/interface2.go" `/START f2/` `/STOP/`}}
--> var x uint8 = &#39;x&#39;
v := reflect.ValueOf(x)
fmt.Println(&#34;type:&#34;, v.Type()) // uint8.
fmt.Println(&#34;kind is uint8: &#34;, v.Kind() == reflect.Uint8) // true.
x = uint8(v.Uint()) // v.Uint returns a uint64.</pre>
{{code "/doc/progs/interface2.go" `/START f2/` `/STOP/`}}
<p>
The second property is that the <code>Kind</code> of a reflection
......@@ -356,10 +301,7 @@ reflection object contains a value of a user-defined integer type,
as in
</p>
<pre><!--{{code "progs/interface2.go" `/START f3/` `/STOP/`}}
--> type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)</pre>
{{code "/doc/progs/interface2.go" `/START f3/` `/STOP/`}}
<p>
the <code>Kind</code> of <code>v</code> is still
......@@ -395,9 +337,7 @@ func (v Value) Interface() interface{}
As a consequence we can say
</p>
<pre><!--{{code "progs/interface2.go" `/START f3b/` `/STOP/`}}
--> y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)</pre>
{{code "/doc/progs/interface2.go" `/START f3b/` `/STOP/`}}
<p>
to print the <code>float64</code> value represented by the
......@@ -415,8 +355,7 @@ the <code>Interface</code> method to the formatted print
routine:
</p>
<pre><!--{{code "progs/interface2.go" `/START f3c/` `/STOP/`}}
--> fmt.Println(v.Interface())</pre>
{{code "/doc/progs/interface2.go" `/START f3c/` `/STOP/`}}
<p>
(Why not <code>fmt.Println(v)</code>? Because <code>v</code> is a
......@@ -425,8 +364,7 @@ Since our value is a <code>float64</code>, we can even use a
floating-point format if we want:
</p>
<pre><!--{{code "progs/interface2.go" `/START f3d/` `/STOP/`}}
--> fmt.Printf(&#34;value is %7.1e\n&#34;, v.Interface())</pre>
{{code "/doc/progs/interface2.go" `/START f3d/` `/STOP/`}}
<p>
and get in this case
......@@ -467,10 +405,7 @@ enough to understand if we start from first principles.
Here is some code that does not work, but is worth studying.
</p>
<pre><!--{{code "progs/interface2.go" `/START f4/` `/STOP/`}}
--> var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1) // Error: will panic.</pre>
{{code "/doc/progs/interface2.go" `/START f4/` `/STOP/`}}
<p>
If you run this code, it will panic with the cryptic message
......@@ -492,10 +427,7 @@ The <code>CanSet</code> method of <code>Value</code> reports the
settability of a <code>Value</code>; in our case,
</p>
<pre><!--{{code "progs/interface2.go" `/START f5/` `/STOP/`}}
--> var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println(&#34;settability of v:&#34;, v.CanSet())</pre>
{{code "/doc/progs/interface2.go" `/START f5/` `/STOP/`}}
<p>
prints
......@@ -518,9 +450,7 @@ determined by whether the reflection object holds the original
item. When we say
</p>
<pre><!--{{code "progs/interface2.go" `/START f6/` `/STOP/`}}
--> var x float64 = 3.4
v := reflect.ValueOf(x)</pre>
{{code "/doc/progs/interface2.go" `/START f6/` `/STOP/`}}
<p>
we pass a <em>copy</em> of <code>x</code> to
......@@ -530,8 +460,7 @@ argument to <code>reflect.ValueOf</code> is a <em>copy</em> of
statement
</p>
<pre><!--{{code "progs/interface2.go" `/START f6b/` `/STOP/`}}
--> v.SetFloat(7.1)</pre>
{{code "/doc/progs/interface2.go" `/START f6b/` `/STOP/`}}
<p>
were allowed to succeed, it would not update <code>x</code>, even
......@@ -577,11 +506,7 @@ and then create a reflection value that points to it, called
<code>p</code>.
</p>
<pre><!--{{code "progs/interface2.go" `/START f7/` `/STOP/`}}
--> var x float64 = 3.4
p := reflect.ValueOf(&amp;x) // Note: take the address of x.
fmt.Println(&#34;type of p:&#34;, p.Type())
fmt.Println(&#34;settability of p:&#34;, p.CanSet())</pre>
{{code "/doc/progs/interface2.go" `/START f7/` `/STOP/`}}
<p>
The output so far is
......@@ -601,9 +526,7 @@ and save the result in a reflection <code>Value</code> called
<code>v</code>:
</p>
<pre><!--{{code "progs/interface2.go" `/START f7b/` `/STOP/`}}
--> v := p.Elem()
fmt.Println(&#34;settability of v:&#34;, v.CanSet())</pre>
{{code "/doc/progs/interface2.go" `/START f7b/` `/STOP/`}}
<p>
Now <code>v</code> is a settable reflection object, as the output
......@@ -620,10 +543,7 @@ and since it represents <code>x</code>, we are finally able to use
<code>x</code>:
</p>
<pre><!--{{code "progs/interface2.go" `/START f7c/` `/STOP/`}}
--> v.SetFloat(7.1)
fmt.Println(v.Interface())
fmt.Println(x)</pre>
{{code "/doc/progs/interface2.go" `/START f7c/` `/STOP/`}}
<p>
The output, as expected, is
......@@ -664,19 +584,7 @@ but the fields themselves are regular <code>reflect.Value</code>
objects.
</p>
<pre><!--{{code "progs/interface2.go" `/START f8/` `/STOP/`}}
--> type T struct {
A int
B string
}
t := T{23, &#34;skidoo&#34;}
s := reflect.ValueOf(&amp;t).Elem()
typeOfT := s.Type()
for i := 0; i &lt; s.NumField(); i++ {
f := s.Field(i)
fmt.Printf(&#34;%d: %s %s = %v\n&#34;, i,
typeOfT.Field(i).Name, f.Type(), f.Interface())
}</pre>
{{code "/doc/progs/interface2.go" `/START f8/` `/STOP/`}}
<p>
The output of this program is
......@@ -699,10 +607,7 @@ Because <code>s</code> contains a settable reflection object, we
can modify the fields of the structure.
</p>
<pre><!--{{code "progs/interface2.go" `/START f8b/` `/STOP/`}}
--> s.Field(0).SetInt(77)
s.Field(1).SetString(&#34;Sunset Strip&#34;)
fmt.Println(&#34;t is now&#34;, t)</pre>
{{code "/doc/progs/interface2.go" `/START f8b/` `/STOP/`}}
<p>
And here's the result:
......
This diff is collapsed.
<!--{
"Title": "Slices: usage and internals"
"Title": "Slices: usage and internals",
"Template": true
}-->
<!--
DO NOT EDIT: created by
tmpltohtml articles/slices_usage_and_internals.tmpl
-->
<p>
Go's slice type provides a convenient and efficient means of working with
......@@ -326,20 +322,7 @@ appends byte elements to a slice of bytes, growing the slice if necessary, and
returns the updated slice value:
</p>
<pre><!--{{code "progs/slices.go" `/AppendByte/` `/STOP/`}}
-->func AppendByte(slice []byte, data ...byte) []byte {
m := len(slice)
n := m + len(data)
if n &gt; cap(slice) { // if necessary, reallocate
// allocate double what&#39;s needed, for future growth.
newSlice := make([]byte, (n+1)*2)
copy(newSlice, slice)
slice = newSlice
}
slice = slice[0:n]
copy(slice[m:n], data)
return slice
}</pre>
{{code "/doc/progs/slices.go" `/AppendByte/` `/STOP/`}}
<p>
One could use <code>AppendByte</code> like this:
......@@ -398,18 +381,7 @@ Since the zero value of a slice (<code>nil</code>) acts like a zero-length
slice, you can declare a slice variable and then append to it in a loop:
</p>
<pre><!--{{code "progs/slices.go" `/Filter/` `/STOP/`}}
-->// Filter returns a new slice holding only
// the elements of s that satisfy f()
func Filter(s []int, fn func(int) bool) []int {
var p []int // == nil
for _, i := range s {
if fn(i) {
p = append(p, i)
}
}
return p
}</pre>
{{code "/doc/progs/slices.go" `/Filter/` `/STOP/`}}
<p>
<b>A possible "gotcha"</b>
......@@ -428,13 +400,7 @@ searches it for the first group of consecutive numeric digits, returning them
as a new slice.
</p>
<pre><!--{{code "progs/slices.go" `/digit/` `/STOP/`}}
-->var digitRegexp = regexp.MustCompile(&#34;[0-9]+&#34;)
func FindDigits(filename string) []byte {
b, _ := ioutil.ReadFile(filename)
return digitRegexp.Find(b)
}</pre>
{{code "/doc/progs/slices.go" `/digit/` `/STOP/`}}
<p>
This code behaves as advertised, but the returned <code>[]byte</code> points
......@@ -449,14 +415,7 @@ To fix this problem one can copy the interesting data to a new slice before
returning it:
</p>
<pre><!--{{code "progs/slices.go" `/CopyDigits/` `/STOP/`}}
-->func CopyDigits(filename string) []byte {
b, _ := ioutil.ReadFile(filename)
b = digitRegexp.Find(b)
c := make([]byte, len(b))
copy(c, b)
return c
}</pre>
{{code "/doc/progs/slices.go" `/CopyDigits/` `/STOP/`}}
<p>
A more concise version of this function could be constructed by using
......
This diff is collapsed.
<!--{
"Title": "Effective Go"
"Title": "Effective Go",
"Template": true
}-->
<!--
DO NOT EDIT: created by
tmpltohtml effective_go.tmpl
-->
<h2 id="introduction">Introduction</h2>
......@@ -1693,47 +1689,13 @@ enumerator. Since <code>iota</code> can be part of an expression and
expressions can be implicitly repeated, it is easy to build intricate
sets of values.
</p>
<pre><!--{{code "progs/eff_bytesize.go" `/^type ByteSize/` `/^\)/`}}
-->type ByteSize float64
const (
_ = iota // ignore first value by assigning to blank identifier
KB ByteSize = 1 &lt;&lt; (10 * iota)
MB
GB
TB
PB
EB
ZB
YB
)</pre>
{{code "/doc/progs/eff_bytesize.go" `/^type ByteSize/` `/^\)/`}}
<p>
The ability to attach a method such as <code>String</code> to a
type makes it possible for such values to format themselves
automatically for printing, even as part of a general type.
</p>
<pre><!--{{code "progs/eff_bytesize.go" `/^func.*ByteSize.*String/` `/^}/`}}
-->func (b ByteSize) String() string {
switch {
case b &gt;= YB:
return fmt.Sprintf(&#34;%.2fYB&#34;, float64(b/YB))
case b &gt;= ZB:
return fmt.Sprintf(&#34;%.2fZB&#34;, float64(b/ZB))
case b &gt;= EB:
return fmt.Sprintf(&#34;%.2fEB&#34;, float64(b/EB))
case b &gt;= PB:
return fmt.Sprintf(&#34;%.2fPB&#34;, float64(b/PB))
case b &gt;= TB:
return fmt.Sprintf(&#34;%.2fTB&#34;, float64(b/TB))
case b &gt;= GB:
return fmt.Sprintf(&#34;%.2fGB&#34;, float64(b/GB))
case b &gt;= MB:
return fmt.Sprintf(&#34;%.2fMB&#34;, float64(b/MB))
case b &gt;= KB:
return fmt.Sprintf(&#34;%.2fKB&#34;, float64(b/KB))
}
return fmt.Sprintf(&#34;%.2fB&#34;, float64(b))
}</pre>
{{code "/doc/progs/eff_bytesize.go" `/^func.*ByteSize.*String/` `/^}/`}}
<p>
(The <code>float64</code> conversions prevent <code>Sprintf</code>
from recurring back through the <code>String</code> method for
......@@ -1879,32 +1841,7 @@ by the routines in package <code>sort</code> if it implements
and it could also have a custom formatter.
In this contrived example <code>Sequence</code> satisfies both.
</p>
<pre><!--{{code "progs/eff_sequence.go" `/^type/` "$"}}
-->type Sequence []int
// Methods required by sort.Interface.
func (s Sequence) Len() int {
return len(s)
}
func (s Sequence) Less(i, j int) bool {
return s[i] &lt; s[j]
}
func (s Sequence) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Method for printing - sorts the elements before printing.
func (s Sequence) String() string {
sort.Sort(s)
str := &#34;[&#34;
for i, elem := range s {
if i &gt; 0 {
str += &#34; &#34;
}
str += fmt.Sprint(elem)
}
return str + &#34;]&#34;
}</pre>
{{code "/doc/progs/eff_sequence.go" `/^type/` "$"}}
<h3 id="conversions">Conversions</h3>
......@@ -3010,53 +2947,7 @@ for instance, a URL, saving you typing the URL into the phone's tiny keyboard.
Here's the complete program.
An explanation follows.
</p>
<pre><!--{{code "progs/eff_qr.go"}}
-->package main
import (
&#34;flag&#34;
&#34;log&#34;
&#34;net/http&#34;
&#34;text/template&#34;
)
var addr = flag.String(&#34;addr&#34;, &#34;:1718&#34;, &#34;http service address&#34;) // Q=17, R=18
var templ = template.Must(template.New(&#34;qr&#34;).Parse(templateStr))
func main() {
flag.Parse()
http.Handle(&#34;/&#34;, http.HandlerFunc(QR))
err := http.ListenAndServe(*addr, nil)
if err != nil {
log.Fatal(&#34;ListenAndServe:&#34;, err)
}
}
func QR(w http.ResponseWriter, req *http.Request) {
templ.Execute(w, req.FormValue(&#34;s&#34;))
}
const templateStr = `
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;QR Link Generator&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
{{if .}}
&lt;img src=&#34;http://chart.apis.google.com/chart?chs=300x300&amp;cht=qr&amp;choe=UTF-8&amp;chl={{urlquery .}}&#34; /&gt;
&lt;br&gt;
{{html .}}
&lt;br&gt;
&lt;br&gt;
{{end}}
&lt;form action=&#34;/&#34; name=f method=&#34;GET&#34;&gt;&lt;input maxLength=1024 size=70
name=s value=&#34;&#34; title=&#34;Text to QR Encode&#34;&gt;&lt;input type=submit
value=&#34;Show QR&#34; name=qr&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
`</pre>
{{code "/doc/progs/eff_qr.go"}}
<p>
The pieces up to <code>main</code> should be easy to follow.
The one flag sets a default HTTP port for our server. The template
......@@ -3082,13 +2973,13 @@ from data items passed to <code>templ.Execute</code>, in this case the
form value.
Within the template text (<code>templateStr</code>),
double-brace-delimited pieces denote template actions.
The piece from <code>{{if .}}</code>
to <code>{{end}}</code> executes only if the value of the current data item, called <code>.</code> (dot),
The piece from <code>{{html "{{if .}}"}}</code>
to <code>{{html "{{end}}"}}</code> executes only if the value of the current data item, called <code>.</code> (dot),
is non-empty.
That is, when the string is empty, this piece of the template is suppressed.
</p>
<p>
The snippet <code>{{urlquery .}}</code> says to process the data with the function
The snippet <code>{{html "{{urlquery .}}"}}</code> says to process the data with the function
<code>urlquery</code>, which sanitizes the query string
for safe display on the web page.
</p>
......
This diff is collapsed.
<!--{
"Title": "Go 1 Release Notes"
"Title": "Go 1 Release Notes",
"Template": true
}-->
<!--
DO NOT EDIT: created by
tmpltohtml go1.tmpl
-->
<h2 id="introduction">Introduction to Go 1</h2>
......@@ -64,9 +60,7 @@ However, <code>append</code> did not provide a way to append a string to a <code
which is another common case.
</p>
<pre><!--{{code "progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
--> greeting := []byte{}
greeting = append(greeting, []byte(&#34;hello &#34;)...)</pre>
{{code "/doc/progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
<p>
By analogy with the similar property of <code>copy</code>, Go 1
......@@ -75,8 +69,7 @@ slice, reducing the friction between strings and byte slices.
The conversion is no longer necessary:
</p>
<pre><!--{{code "progs/go1.go" `/append.*world/`}}
--> greeting = append(greeting, &#34;world&#34;...)</pre>
{{code "/doc/progs/go1.go" `/append.*world/`}}
<p>
<em>Updating</em>:
......@@ -126,35 +119,7 @@ type specification for the elements' initializers if they are of pointer type.
All four of the initializations in this example are legal; the last one was illegal before Go 1.
</p>
<pre><!--{{code "progs/go1.go" `/type Date struct/` `/STOP/`}}
--> type Date struct {
month string
day int
}
// Struct values, fully qualified; always legal.
holiday1 := []Date{
Date{&#34;Feb&#34;, 14},
Date{&#34;Nov&#34;, 11},
Date{&#34;Dec&#34;, 25},
}
// Struct values, type name elided; always legal.
holiday2 := []Date{
{&#34;Feb&#34;, 14},
{&#34;Nov&#34;, 11},
{&#34;Dec&#34;, 25},
}
// Pointers, fully qualified, always legal.
holiday3 := []*Date{
&amp;Date{&#34;Feb&#34;, 14},
&amp;Date{&#34;Nov&#34;, 11},
&amp;Date{&#34;Dec&#34;, 25},
}
// Pointers, type name elided; legal in Go 1.
holiday4 := []*Date{
{&#34;Feb&#34;, 14},
{&#34;Nov&#34;, 11},
{&#34;Dec&#34;, 25},
}</pre>
{{code "/doc/progs/go1.go" `/type Date struct/` `/STOP/`}}
<p>
<em>Updating</em>:
......@@ -183,14 +148,7 @@ In Go 1, code that uses goroutines can be called from
without introducing a deadlock.
</p>
<pre><!--{{code "progs/go1.go" `/PackageGlobal/` `/^}/`}}
-->var PackageGlobal int
func init() {
c := make(chan int)
go initializationFunction(c)
PackageGlobal = &lt;-c
}</pre>
{{code "/doc/progs/go1.go" `/PackageGlobal/` `/^}/`}}
<p>
<em>Updating</em>:
......@@ -231,14 +189,7 @@ when appropriate. For instance, the functions <code>unicode.ToLower</code> and
relatives now take and return a <code>rune</code>.
</p>
<pre><!--{{code "progs/go1.go" `/STARTRUNE/` `/ENDRUNE/`}}
--> delta := &#39;δ&#39; // delta has type rune.
var DELTA rune
DELTA = unicode.ToUpper(delta)
epsilon := unicode.ToLower(DELTA + 1)
if epsilon != &#39;δ&#39;+1 {
log.Fatal(&#34;inconsistent casing for Greek&#34;)
}</pre>
{{code "/doc/progs/go1.go" `/STARTRUNE/` `/ENDRUNE/`}}
<p>
<em>Updating</em>:
......@@ -287,8 +238,7 @@ In Go 1, that syntax has gone; instead there is a new built-in
function, <code>delete</code>. The call
</p>
<pre><!--{{code "progs/go1.go" `/delete\(m, k\)/`}}
--> delete(m, k)</pre>
{{code "/doc/progs/go1.go" `/delete\(m, k\)/`}}
<p>
will delete the map entry retrieved by the expression <code>m[k]</code>.
......@@ -327,12 +277,7 @@ This change means that code that depends on iteration order is very likely to br
Just as important, it allows the map implementation to ensure better map balancing even when programs are using range loops to select an element from a map.
</p>
<pre><!--{{code "progs/go1.go" `/Sunday/` `/^ }/`}}
--> m := map[string]int{&#34;Sunday&#34;: 0, &#34;Monday&#34;: 1}
for name, value := range m {
// This loop should not assume Sunday will be visited first.
f(name, value)
}</pre>
{{code "/doc/progs/go1.go" `/Sunday/` `/^ }/`}}
<p>
<em>Updating</em>:
......@@ -367,17 +312,7 @@ proceed in left-to-right order.
These examples illustrate the behavior.
</p>
<pre><!--{{code "progs/go1.go" `/sa :=/` `/then sc.0. = 2/`}}
--> sa := []int{1, 2, 3}
i := 0
i, sa[i] = 1, 2 // sets i = 1, sa[0] = 2
sb := []int{1, 2, 3}
j := 0
sb[j], j = 2, 1 // sets sb[0] = 2, j = 1
sc := []int{1, 2, 3}
sc[0], sc[0] = 1, 2 // sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)</pre>
{{code "/doc/progs/go1.go" `/sa :=/` `/then sc.0. = 2/`}}
<p>
<em>Updating</em>:
......@@ -504,18 +439,7 @@ provided they are composed from elements for which equality is also defined,
using element-wise comparison.
</p>
<pre><!--{{code "progs/go1.go" `/type Day struct/` `/Printf/`}}
--> type Day struct {
long string
short string
}
Christmas := Day{&#34;Christmas&#34;, &#34;XMas&#34;}
Thanksgiving := Day{&#34;Thanksgiving&#34;, &#34;Turkey&#34;}
holiday := map[Day]bool{
Christmas: true,
Thanksgiving: true,
}
fmt.Printf(&#34;Christmas is a holiday: %t\n&#34;, holiday[Christmas])</pre>
{{code "/doc/progs/go1.go" `/type Day struct/` `/Printf/`}}
<p>
Second, Go 1 removes the definition of equality for function values,
......@@ -831,16 +755,7 @@ The <code>fmt</code> library automatically invokes <code>Error</code>, as it alr
does for <code>String</code>, for easy printing of error values.
</p>
<pre><!--{{code "progs/go1.go" `/START ERROR EXAMPLE/` `/END ERROR EXAMPLE/`}}
-->type SyntaxError struct {
File string
Line int
Message string
}
func (se *SyntaxError) Error() string {
return fmt.Sprintf(&#34;%s:%d: %s&#34;, se.File, se.Line, se.Message)
}</pre>
{{code "/doc/progs/go1.go" `/START ERROR EXAMPLE/` `/END ERROR EXAMPLE/`}}
<p>
All standard packages have been updated to use the new interface; the old <code>os.Error</code> is gone.
......@@ -858,8 +773,7 @@ func New(text string) error
to turn a string into an error. It replaces the old <code>os.NewError</code>.
</p>
<pre><!--{{code "progs/go1.go" `/ErrSyntax/`}}
--> var ErrSyntax = errors.New(&#34;syntax error&#34;)</pre>
{{code "/doc/progs/go1.go" `/ErrSyntax/`}}
<p>
<em>Updating</em>:
......@@ -949,17 +863,7 @@ returns a <code>time.Time</code> value rather than, in the old
API, an integer nanosecond count since the Unix epoch.
</p>
<pre><!--{{code "progs/go1.go" `/sleepUntil/` `/^}/`}}
-->// sleepUntil sleeps until the specified time. It returns immediately if it&#39;s too late.
func sleepUntil(wakeup time.Time) {
now := time.Now() // A Time.
if !wakeup.After(now) {
return
}
delta := wakeup.Sub(now) // A Duration.
fmt.Printf(&#34;Sleeping for %.3fs\n&#34;, delta.Seconds())
time.Sleep(delta)
}</pre>
{{code "/doc/progs/go1.go" `/sleepUntil/` `/^}/`}}
<p>
The new types, methods, and constants have been propagated through
......@@ -1196,8 +1100,7 @@ Values for such flags must be given units, just as <code>time.Duration</code>
formats them: <code>10s</code>, <code>1h30m</code>, etc.
</p>
<pre><!--{{code "progs/go1.go" `/timeout/`}}
-->var timeout = flag.Duration(&#34;timeout&#34;, 30*time.Second, &#34;how long to wait for completion&#34;)</pre>
{{code "/doc/progs/go1.go" `/timeout/`}}
<p>
<em>Updating</em>:
......@@ -1711,11 +1614,7 @@ and
<a href="/pkg/os/#IsPermission"><code>IsPermission</code></a>.
</p>
<pre><!--{{code "progs/go1.go" `/os\.Open/` `/}/`}}
--> f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
if os.IsExist(err) {
log.Printf(&#34;%s already exists&#34;, name)
}</pre>
{{code "/doc/progs/go1.go" `/os\.Open/` `/}/`}}
<p>
<em>Updating</em>:
......@@ -1781,21 +1680,7 @@ If a directory's contents are to be skipped,
the function should return the value <a href="/pkg/path/filepath/#variables"><code>filepath.SkipDir</code></a>
</p>
<pre><!--{{code "progs/go1.go" `/STARTWALK/` `/ENDWALK/`}}
--> markFn := func(path string, info os.FileInfo, err error) error {
if path == &#34;pictures&#34; { // Will skip walking of directory pictures and its contents.
return filepath.SkipDir
}
if err != nil {
return err
}
log.Println(path)
return nil
}
err := filepath.Walk(&#34;.&#34;, markFn)
if err != nil {
log.Fatal(err)
}</pre>
{{code "/doc/progs/go1.go" `/STARTWALK/` `/ENDWALK/`}}
<p>
<em>Updating</em>:
......@@ -1993,20 +1878,7 @@ In Go 1, <code>B</code> has new methods, analogous to those of <code>T</code>, e
logging and failure reporting.
</p>
<pre><!--{{code "progs/go1.go" `/func.*Benchmark/` `/^}/`}}
-->func BenchmarkSprintf(b *testing.B) {
// Verify correctness before running benchmark.
b.StopTimer()
got := fmt.Sprintf(&#34;%x&#34;, 23)
const expect = &#34;17&#34;
if expect != got {
b.Fatalf(&#34;expected %q; got %q&#34;, expect, got)
}
b.StartTimer()
for i := 0; i &lt; b.N; i++ {
fmt.Sprintf(&#34;%x&#34;, 23)
}
}</pre>
{{code "/doc/progs/go1.go" `/func.*Benchmark/` `/^}/`}}
<p>
<em>Updating</em>:
......
This diff is collapsed.
......@@ -87,6 +87,9 @@ The flags are:
directory containing alternate template files; if set,
the directory may provide alternative template files
for the files in $GOROOT/lib/godoc
-url=path
print to standard output the data that would be served by
an HTTP request for path
-zip=""
zip file providing the file system to serve; disabled if empty
......
......@@ -605,6 +605,23 @@ func serveHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath strin
log.Printf("decoding metadata %s: %v", relpath, err)
}
// evaluate as template if indicated
if meta.Template {
tmpl, err := template.New("main").Funcs(templateFuncs).Parse(string(src))
if err != nil {
log.Printf("parsing template %s: %v", relpath, err)
serveError(w, r, relpath, err)
return
}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, nil); err != nil {
log.Printf("executing template %s: %v", relpath, err)
serveError(w, r, relpath, err)
return
}
src = buf.Bytes()
}
// if it's the language spec, add tags to EBNF productions
if strings.HasSuffix(abspath, "go_spec.html") {
var buf bytes.Buffer
......@@ -1177,6 +1194,7 @@ func search(w http.ResponseWriter, r *http.Request) {
type Metadata struct {
Title string
Subtitle string
Template bool // execute as template
Path string // canonical path for this page
filePath string // filesystem path relative to goroot
}
......
......@@ -38,6 +38,7 @@ import (
"log"
"net/http"
_ "net/http/pprof" // to serve /debug/pprof/*
"net/url"
"os"
pathpkg "path"
"path/filepath"
......@@ -69,6 +70,7 @@ var (
// layout control
html = flag.Bool("html", false, "print HTML in command-line mode")
srcMode = flag.Bool("src", false, "print (exported) source in command-line mode")
urlFlag = flag.String("url", "", "print HTML for named URL")
// command-line searches
query = flag.Bool("q", false, "arguments are considered search queries")
......@@ -225,7 +227,7 @@ func main() {
flag.Parse()
// Check usage: either server and no args, command line and args, or index creation mode
if (*httpAddr != "") != (flag.NArg() == 0) && !*writeIndex {
if (*httpAddr != "" || *urlFlag != "") != (flag.NArg() == 0) && !*writeIndex {
usage()
}
......@@ -286,6 +288,44 @@ func main() {
return
}
// Print content that would be served at the URL *urlFlag.
if *urlFlag != "" {
registerPublicHandlers(http.DefaultServeMux)
// Try up to 10 fetches, following redirects.
urlstr := *urlFlag
for i := 0; i < 10; i++ {
// Prepare request.
u, err := url.Parse(urlstr)
if err != nil {
log.Fatal(err)
}
req := &http.Request{
URL: u,
}
// Invoke default HTTP handler to serve request
// to our buffering httpWriter.
w := &httpWriter{h: http.Header{}, code: 200}
http.DefaultServeMux.ServeHTTP(w, req)
// Return data, error, or follow redirect.
switch w.code {
case 200: // ok
os.Stdout.Write(w.Bytes())
return
case 301, 302, 303, 307: // redirect
redirect := w.h.Get("Location")
if redirect == "" {
log.Fatalf("HTTP %d without Location header", w.code)
}
urlstr = redirect
default:
log.Fatalf("HTTP error %d", w.code)
}
}
log.Fatalf("too many redirects")
}
if *httpAddr != "" {
// HTTP server mode.
var handler http.Handler = http.DefaultServeMux
......@@ -494,3 +534,13 @@ func main() {
log.Printf("packageText.Execute: %s", err)
}
}
// An httpWriter is an http.ResponseWriter writing to a bytes.Buffer.
type httpWriter struct {
bytes.Buffer
h http.Header
code int
}
func (w *httpWriter) Header() http.Header { return w.h }
func (w *httpWriter) WriteHeader(code int) { w.code = code }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment