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 @@ ...@@ -2,21 +2,18 @@
# Use of this source code is governed by a BSD-style # Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file. # license that can be found in the LICENSE file.
HTML=\ RAWHTML=\
articles/defer_panic_recover.html\ articles/defer_panic_recover.rawhtml\
articles/error_handling.html\ articles/error_handling.rawhtml\
articles/slices_usage_and_internals.html\ articles/slices_usage_and_internals.rawhtml\
articles/laws_of_reflection.html\ articles/laws_of_reflection.rawhtml\
effective_go.html\ effective_go.rawhtml\
go1.html\ go1.rawhtml\
all: tmpltohtml $(HTML) all: $(RAWHTML)
tmpltohtml: tmpltohtml.go %.rawhtml: %.html
go build tmpltohtml.go godoc -url /doc/$* >$@
%.html: %.tmpl tmpltohtml
./tmpltohtml $*.tmpl > $@
clean: 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> <p>
Go has the usual mechanisms for control flow: if, for, switch, goto. It also 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 ...@@ -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: contents of one file to the other:
</p> </p>
<pre><!--{{code "progs/defer.go" `/func CopyFile/` `/STOP/`}} {{code "/doc/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>
<p> <p>
This works, but there is a bug. If the call to os.Create fails, the 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 ...@@ -50,22 +31,7 @@ noticed and resolved. By introducing defer statements we can ensure that the
files are always closed: files are always closed:
</p> </p>
<pre><!--{{code "progs/defer2.go" `/func CopyFile/` `/STOP/`}} {{code "/doc/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>
<p> <p>
Defer statements allow us to think about closing each file right after opening 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 ...@@ -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. deferred. The deferred call will print "0" after the function returns.
</p> </p>
<pre><!--{{code "progs/defer.go" `/func a/` `/STOP/`}} {{code "/doc/progs/defer.go" `/func a/` `/STOP/`}}
-->func a() {
i := 0
defer fmt.Println(i)
i++
return
}</pre>
<p> <p>
2. <i>Deferred function calls are executed in Last In First Out order 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. ...@@ -105,12 +65,7 @@ deferred. The deferred call will print "0" after the function returns.
This function prints "3210": This function prints "3210":
</p> </p>
<pre><!--{{code "progs/defer.go" `/func b/` `/STOP/`}} {{code "/doc/progs/defer.go" `/func b/` `/STOP/`}}
-->func b() {
for i := 0; i &lt; 4; i++ {
defer fmt.Print(i)
}
}</pre>
<p> <p>
3. <i>Deferred functions may read and assign to the returning function's named 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> ...@@ -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: the surrounding function returns. Thus, this function returns 2:
</p> </p>
<pre><!--{{code "progs/defer.go" `/func c/` `/STOP/`}} {{code "/doc/progs/defer.go" `/func c/` `/STOP/`}}
-->func c() (i int) {
defer func() { i++ }()
return 1
}</pre>
<p> <p>
This is convenient for modifying the error return value of a function; we will This is convenient for modifying the error return value of a function; we will
...@@ -156,36 +107,7 @@ to panic and resume normal execution. ...@@ -156,36 +107,7 @@ to panic and resume normal execution.
Here's an example program that demonstrates the mechanics of panic and defer: Here's an example program that demonstrates the mechanics of panic and defer:
</p> </p>
<pre><!--{{code "progs/defer2.go" `/package main/` `/STOP/`}} {{code "/doc/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>
<p> <p>
The function g takes the int i, and panics if i is greater than 3, or else it 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> <p>
Reflection in computing is the Reflection in computing is the
...@@ -36,11 +32,7 @@ exactly one type known and fixed at compile time: <code>int</code>, ...@@ -36,11 +32,7 @@ exactly one type known and fixed at compile time: <code>int</code>,
and so on. If we declare and so on. If we declare
</p> </p>
<pre><!--{{code "progs/interface.go" `/type MyInt/` `/STOP/`}} {{code "/doc/progs/interface.go" `/type MyInt/` `/STOP/`}}
-->type MyInt int
var i int
var j MyInt</pre>
<p> <p>
then <code>i</code> has type <code>int</code> and <code>j</code> 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 ...@@ -60,16 +52,7 @@ interface's methods. A well-known pair of examples is
"http://golang.org/pkg/io/">io package</a>: "http://golang.org/pkg/io/">io package</a>:
</p> </p>
<pre><!--{{code "progs/interface.go" `/// Reader/` `/STOP/`}} {{code "/doc/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>
<p> <p>
Any type that implements a <code>Read</code> (or Any type that implements a <code>Read</code> (or
...@@ -80,12 +63,7 @@ purposes of this discussion, that means that a variable of type ...@@ -80,12 +63,7 @@ purposes of this discussion, that means that a variable of type
<code>Read</code> method: <code>Read</code> method:
</p> </p>
<pre><!--{{code "progs/interface.go" `/func readers/` `/STOP/`}} {{code "/doc/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>
<p> <p>
It's important to be clear that whatever concrete value 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 ...@@ -138,13 +116,7 @@ that implements the interface and the type describes the full type
of that item. For instance, after of that item. For instance, after
</p> </p>
<pre><!--{{code "progs/interface.go" `/func typeAssertions/` `/STOP/`}} {{code "/doc/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>
<p> <p>
<code>r</code> contains, schematically, the (value, type) pair, <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 ...@@ -156,9 +128,7 @@ the type information about that value. That's why we can do things
like this: like this:
</p> </p>
<pre><!--{{code "progs/interface.go" `/var w io.Writer/` `/STOP/`}} {{code "/doc/progs/interface.go" `/var w io.Writer/` `/STOP/`}}
--> var w io.Writer
w = r.(io.Writer)</pre>
<p> <p>
The expression in this assignment is a type assertion; what it The expression in this assignment is a type assertion; what it
...@@ -176,9 +146,7 @@ methods. ...@@ -176,9 +146,7 @@ methods.
Continuing, we can do this: Continuing, we can do this:
</p> </p>
<pre><!--{{code "progs/interface.go" `/var empty interface{}/` `/STOP/`}} {{code "/doc/progs/interface.go" `/var empty interface{}/` `/STOP/`}}
--> var empty interface{}
empty = w</pre>
<p> <p>
and our empty interface value <code>e</code> will again contain and our empty interface value <code>e</code> will again contain
...@@ -232,18 +200,7 @@ now.) ...@@ -232,18 +200,7 @@ now.)
Let's start with <code>TypeOf</code>: Let's start with <code>TypeOf</code>:
</p> </p>
<pre><!--{{code "progs/interface2.go" `/package main/` `/STOP main/`}} {{code "/doc/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>
<p> <p>
This program prints This program prints
...@@ -281,9 +238,7 @@ value (from here on we'll elide the boilerplate and focus just on ...@@ -281,9 +238,7 @@ value (from here on we'll elide the boilerplate and focus just on
the executable code): the executable code):
</p> </p>
<pre><!--{{code "progs/interface2.go" `/var x/` `/STOP/`}} {{code "/doc/progs/interface2.go" `/var x/` `/STOP/`}}
--> var x float64 = 3.4
fmt.Println(&#34;type:&#34;, reflect.TypeOf(x))</pre>
<p> <p>
prints prints
...@@ -307,12 +262,7 @@ on. Also methods on <code>Value</code> with names like ...@@ -307,12 +262,7 @@ on. Also methods on <code>Value</code> with names like
<code>int64</code> and <code>float64</code>) stored inside: <code>int64</code> and <code>float64</code>) stored inside:
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f1/` `/STOP/`}} {{code "/doc/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>
<p> <p>
prints prints
...@@ -342,12 +292,7 @@ instance. That is, the <code>Int</code> method of ...@@ -342,12 +292,7 @@ instance. That is, the <code>Int</code> method of
necessary to convert to the actual type involved: necessary to convert to the actual type involved:
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f2/` `/STOP/`}} {{code "/doc/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>
<p> <p>
The second property is that the <code>Kind</code> of a reflection 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, ...@@ -356,10 +301,7 @@ reflection object contains a value of a user-defined integer type,
as in as in
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f3/` `/STOP/`}} {{code "/doc/progs/interface2.go" `/START f3/` `/STOP/`}}
--> type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)</pre>
<p> <p>
the <code>Kind</code> of <code>v</code> is still the <code>Kind</code> of <code>v</code> is still
...@@ -395,9 +337,7 @@ func (v Value) Interface() interface{} ...@@ -395,9 +337,7 @@ func (v Value) Interface() interface{}
As a consequence we can say As a consequence we can say
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f3b/` `/STOP/`}} {{code "/doc/progs/interface2.go" `/START f3b/` `/STOP/`}}
--> y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)</pre>
<p> <p>
to print the <code>float64</code> value represented by the to print the <code>float64</code> value represented by the
...@@ -415,8 +355,7 @@ the <code>Interface</code> method to the formatted print ...@@ -415,8 +355,7 @@ the <code>Interface</code> method to the formatted print
routine: routine:
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f3c/` `/STOP/`}} {{code "/doc/progs/interface2.go" `/START f3c/` `/STOP/`}}
--> fmt.Println(v.Interface())</pre>
<p> <p>
(Why not <code>fmt.Println(v)</code>? Because <code>v</code> is a (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 ...@@ -425,8 +364,7 @@ Since our value is a <code>float64</code>, we can even use a
floating-point format if we want: floating-point format if we want:
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f3d/` `/STOP/`}} {{code "/doc/progs/interface2.go" `/START f3d/` `/STOP/`}}
--> fmt.Printf(&#34;value is %7.1e\n&#34;, v.Interface())</pre>
<p> <p>
and get in this case and get in this case
...@@ -467,10 +405,7 @@ enough to understand if we start from first principles. ...@@ -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. Here is some code that does not work, but is worth studying.
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f4/` `/STOP/`}} {{code "/doc/progs/interface2.go" `/START f4/` `/STOP/`}}
--> var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1) // Error: will panic.</pre>
<p> <p>
If you run this code, it will panic with the cryptic message 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 ...@@ -492,10 +427,7 @@ The <code>CanSet</code> method of <code>Value</code> reports the
settability of a <code>Value</code>; in our case, settability of a <code>Value</code>; in our case,
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f5/` `/STOP/`}} {{code "/doc/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>
<p> <p>
prints prints
...@@ -518,9 +450,7 @@ determined by whether the reflection object holds the original ...@@ -518,9 +450,7 @@ determined by whether the reflection object holds the original
item. When we say item. When we say
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f6/` `/STOP/`}} {{code "/doc/progs/interface2.go" `/START f6/` `/STOP/`}}
--> var x float64 = 3.4
v := reflect.ValueOf(x)</pre>
<p> <p>
we pass a <em>copy</em> of <code>x</code> to 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 ...@@ -530,8 +460,7 @@ argument to <code>reflect.ValueOf</code> is a <em>copy</em> of
statement statement
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f6b/` `/STOP/`}} {{code "/doc/progs/interface2.go" `/START f6b/` `/STOP/`}}
--> v.SetFloat(7.1)</pre>
<p> <p>
were allowed to succeed, it would not update <code>x</code>, even 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 ...@@ -577,11 +506,7 @@ and then create a reflection value that points to it, called
<code>p</code>. <code>p</code>.
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f7/` `/STOP/`}} {{code "/doc/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>
<p> <p>
The output so far is The output so far is
...@@ -601,9 +526,7 @@ and save the result in a reflection <code>Value</code> called ...@@ -601,9 +526,7 @@ and save the result in a reflection <code>Value</code> called
<code>v</code>: <code>v</code>:
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f7b/` `/STOP/`}} {{code "/doc/progs/interface2.go" `/START f7b/` `/STOP/`}}
--> v := p.Elem()
fmt.Println(&#34;settability of v:&#34;, v.CanSet())</pre>
<p> <p>
Now <code>v</code> is a settable reflection object, as the output 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 ...@@ -620,10 +543,7 @@ and since it represents <code>x</code>, we are finally able to use
<code>x</code>: <code>x</code>:
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f7c/` `/STOP/`}} {{code "/doc/progs/interface2.go" `/START f7c/` `/STOP/`}}
--> v.SetFloat(7.1)
fmt.Println(v.Interface())
fmt.Println(x)</pre>
<p> <p>
The output, as expected, is The output, as expected, is
...@@ -664,19 +584,7 @@ but the fields themselves are regular <code>reflect.Value</code> ...@@ -664,19 +584,7 @@ but the fields themselves are regular <code>reflect.Value</code>
objects. objects.
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f8/` `/STOP/`}} {{code "/doc/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>
<p> <p>
The output of this program is The output of this program is
...@@ -699,10 +607,7 @@ Because <code>s</code> contains a settable reflection object, we ...@@ -699,10 +607,7 @@ Because <code>s</code> contains a settable reflection object, we
can modify the fields of the structure. can modify the fields of the structure.
</p> </p>
<pre><!--{{code "progs/interface2.go" `/START f8b/` `/STOP/`}} {{code "/doc/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>
<p> <p>
And here's the result: 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> <p>
Go's slice type provides a convenient and efficient means of working with 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 ...@@ -326,20 +322,7 @@ appends byte elements to a slice of bytes, growing the slice if necessary, and
returns the updated slice value: returns the updated slice value:
</p> </p>
<pre><!--{{code "progs/slices.go" `/AppendByte/` `/STOP/`}} {{code "/doc/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>
<p> <p>
One could use <code>AppendByte</code> like this: 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 ...@@ -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: slice, you can declare a slice variable and then append to it in a loop:
</p> </p>
<pre><!--{{code "progs/slices.go" `/Filter/` `/STOP/`}} {{code "/doc/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>
<p> <p>
<b>A possible "gotcha"</b> <b>A possible "gotcha"</b>
...@@ -428,13 +400,7 @@ searches it for the first group of consecutive numeric digits, returning them ...@@ -428,13 +400,7 @@ searches it for the first group of consecutive numeric digits, returning them
as a new slice. as a new slice.
</p> </p>
<pre><!--{{code "progs/slices.go" `/digit/` `/STOP/`}} {{code "/doc/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>
<p> <p>
This code behaves as advertised, but the returned <code>[]byte</code> points 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 ...@@ -449,14 +415,7 @@ To fix this problem one can copy the interesting data to a new slice before
returning it: returning it:
</p> </p>
<pre><!--{{code "progs/slices.go" `/CopyDigits/` `/STOP/`}} {{code "/doc/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>
<p> <p>
A more concise version of this function could be constructed by using 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> <h2 id="introduction">Introduction</h2>
...@@ -1693,47 +1689,13 @@ enumerator. Since <code>iota</code> can be part of an expression and ...@@ -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 expressions can be implicitly repeated, it is easy to build intricate
sets of values. sets of values.
</p> </p>
<pre><!--{{code "progs/eff_bytesize.go" `/^type ByteSize/` `/^\)/`}} {{code "/doc/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>
<p> <p>
The ability to attach a method such as <code>String</code> to a The ability to attach a method such as <code>String</code> to a
type makes it possible for such values to format themselves type makes it possible for such values to format themselves
automatically for printing, even as part of a general type. automatically for printing, even as part of a general type.
</p> </p>
<pre><!--{{code "progs/eff_bytesize.go" `/^func.*ByteSize.*String/` `/^}/`}} {{code "/doc/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>
<p> <p>
(The <code>float64</code> conversions prevent <code>Sprintf</code> (The <code>float64</code> conversions prevent <code>Sprintf</code>
from recurring back through the <code>String</code> method for 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 ...@@ -1879,32 +1841,7 @@ by the routines in package <code>sort</code> if it implements
and it could also have a custom formatter. and it could also have a custom formatter.
In this contrived example <code>Sequence</code> satisfies both. In this contrived example <code>Sequence</code> satisfies both.
</p> </p>
<pre><!--{{code "progs/eff_sequence.go" `/^type/` "$"}} {{code "/doc/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>
<h3 id="conversions">Conversions</h3> <h3 id="conversions">Conversions</h3>
...@@ -3010,53 +2947,7 @@ for instance, a URL, saving you typing the URL into the phone's tiny keyboard. ...@@ -3010,53 +2947,7 @@ for instance, a URL, saving you typing the URL into the phone's tiny keyboard.
Here's the complete program. Here's the complete program.
An explanation follows. An explanation follows.
</p> </p>
<pre><!--{{code "progs/eff_qr.go"}} {{code "/doc/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>
<p> <p>
The pieces up to <code>main</code> should be easy to follow. 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 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 ...@@ -3082,13 +2973,13 @@ from data items passed to <code>templ.Execute</code>, in this case the
form value. form value.
Within the template text (<code>templateStr</code>), Within the template text (<code>templateStr</code>),
double-brace-delimited pieces denote template actions. double-brace-delimited pieces denote template actions.
The piece from <code>{{if .}}</code> The piece from <code>{{html "{{if .}}"}}</code>
to <code>{{end}}</code> executes only if the value of the current data item, called <code>.</code> (dot), to <code>{{html "{{end}}"}}</code> executes only if the value of the current data item, called <code>.</code> (dot),
is non-empty. is non-empty.
That is, when the string is empty, this piece of the template is suppressed. That is, when the string is empty, this piece of the template is suppressed.
</p> </p>
<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 <code>urlquery</code>, which sanitizes the query string
for safe display on the web page. for safe display on the web page.
</p> </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> <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 ...@@ -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. which is another common case.
</p> </p>
<pre><!--{{code "progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}} {{code "/doc/progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
--> greeting := []byte{}
greeting = append(greeting, []byte(&#34;hello &#34;)...)</pre>
<p> <p>
By analogy with the similar property of <code>copy</code>, Go 1 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. ...@@ -75,8 +69,7 @@ slice, reducing the friction between strings and byte slices.
The conversion is no longer necessary: The conversion is no longer necessary:
</p> </p>
<pre><!--{{code "progs/go1.go" `/append.*world/`}} {{code "/doc/progs/go1.go" `/append.*world/`}}
--> greeting = append(greeting, &#34;world&#34;...)</pre>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
...@@ -126,35 +119,7 @@ type specification for the elements' initializers if they are of pointer type. ...@@ -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. All four of the initializations in this example are legal; the last one was illegal before Go 1.
</p> </p>
<pre><!--{{code "progs/go1.go" `/type Date struct/` `/STOP/`}} {{code "/doc/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>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
...@@ -183,14 +148,7 @@ In Go 1, code that uses goroutines can be called from ...@@ -183,14 +148,7 @@ In Go 1, code that uses goroutines can be called from
without introducing a deadlock. without introducing a deadlock.
</p> </p>
<pre><!--{{code "progs/go1.go" `/PackageGlobal/` `/^}/`}} {{code "/doc/progs/go1.go" `/PackageGlobal/` `/^}/`}}
-->var PackageGlobal int
func init() {
c := make(chan int)
go initializationFunction(c)
PackageGlobal = &lt;-c
}</pre>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
...@@ -231,14 +189,7 @@ when appropriate. For instance, the functions <code>unicode.ToLower</code> and ...@@ -231,14 +189,7 @@ when appropriate. For instance, the functions <code>unicode.ToLower</code> and
relatives now take and return a <code>rune</code>. relatives now take and return a <code>rune</code>.
</p> </p>
<pre><!--{{code "progs/go1.go" `/STARTRUNE/` `/ENDRUNE/`}} {{code "/doc/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>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
...@@ -287,8 +238,7 @@ In Go 1, that syntax has gone; instead there is a new built-in ...@@ -287,8 +238,7 @@ In Go 1, that syntax has gone; instead there is a new built-in
function, <code>delete</code>. The call function, <code>delete</code>. The call
</p> </p>
<pre><!--{{code "progs/go1.go" `/delete\(m, k\)/`}} {{code "/doc/progs/go1.go" `/delete\(m, k\)/`}}
--> delete(m, k)</pre>
<p> <p>
will delete the map entry retrieved by the expression <code>m[k]</code>. 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 ...@@ -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. 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> </p>
<pre><!--{{code "progs/go1.go" `/Sunday/` `/^ }/`}} {{code "/doc/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>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
...@@ -367,17 +312,7 @@ proceed in left-to-right order. ...@@ -367,17 +312,7 @@ proceed in left-to-right order.
These examples illustrate the behavior. These examples illustrate the behavior.
</p> </p>
<pre><!--{{code "progs/go1.go" `/sa :=/` `/then sc.0. = 2/`}} {{code "/doc/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>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
...@@ -504,18 +439,7 @@ provided they are composed from elements for which equality is also defined, ...@@ -504,18 +439,7 @@ provided they are composed from elements for which equality is also defined,
using element-wise comparison. using element-wise comparison.
</p> </p>
<pre><!--{{code "progs/go1.go" `/type Day struct/` `/Printf/`}} {{code "/doc/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>
<p> <p>
Second, Go 1 removes the definition of equality for function values, 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 ...@@ -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. does for <code>String</code>, for easy printing of error values.
</p> </p>
<pre><!--{{code "progs/go1.go" `/START ERROR EXAMPLE/` `/END ERROR EXAMPLE/`}} {{code "/doc/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>
<p> <p>
All standard packages have been updated to use the new interface; the old <code>os.Error</code> is gone. 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 ...@@ -858,8 +773,7 @@ func New(text string) error
to turn a string into an error. It replaces the old <code>os.NewError</code>. to turn a string into an error. It replaces the old <code>os.NewError</code>.
</p> </p>
<pre><!--{{code "progs/go1.go" `/ErrSyntax/`}} {{code "/doc/progs/go1.go" `/ErrSyntax/`}}
--> var ErrSyntax = errors.New(&#34;syntax error&#34;)</pre>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
...@@ -949,17 +863,7 @@ returns a <code>time.Time</code> value rather than, in the old ...@@ -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. API, an integer nanosecond count since the Unix epoch.
</p> </p>
<pre><!--{{code "progs/go1.go" `/sleepUntil/` `/^}/`}} {{code "/doc/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>
<p> <p>
The new types, methods, and constants have been propagated through 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> ...@@ -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. formats them: <code>10s</code>, <code>1h30m</code>, etc.
</p> </p>
<pre><!--{{code "progs/go1.go" `/timeout/`}} {{code "/doc/progs/go1.go" `/timeout/`}}
-->var timeout = flag.Duration(&#34;timeout&#34;, 30*time.Second, &#34;how long to wait for completion&#34;)</pre>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
...@@ -1711,11 +1614,7 @@ and ...@@ -1711,11 +1614,7 @@ and
<a href="/pkg/os/#IsPermission"><code>IsPermission</code></a>. <a href="/pkg/os/#IsPermission"><code>IsPermission</code></a>.
</p> </p>
<pre><!--{{code "progs/go1.go" `/os\.Open/` `/}/`}} {{code "/doc/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>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
...@@ -1781,21 +1680,7 @@ If a directory's contents are to be skipped, ...@@ -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> the function should return the value <a href="/pkg/path/filepath/#variables"><code>filepath.SkipDir</code></a>
</p> </p>
<pre><!--{{code "progs/go1.go" `/STARTWALK/` `/ENDWALK/`}} {{code "/doc/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>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
...@@ -1993,20 +1878,7 @@ In Go 1, <code>B</code> has new methods, analogous to those of <code>T</code>, e ...@@ -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. logging and failure reporting.
</p> </p>
<pre><!--{{code "progs/go1.go" `/func.*Benchmark/` `/^}/`}} {{code "/doc/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>
<p> <p>
<em>Updating</em>: <em>Updating</em>:
......
This diff is collapsed.
...@@ -87,6 +87,9 @@ The flags are: ...@@ -87,6 +87,9 @@ The flags are:
directory containing alternate template files; if set, directory containing alternate template files; if set,
the directory may provide alternative template files the directory may provide alternative template files
for the files in $GOROOT/lib/godoc 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=""
zip file providing the file system to serve; disabled if empty 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 ...@@ -605,6 +605,23 @@ func serveHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath strin
log.Printf("decoding metadata %s: %v", relpath, err) 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 it's the language spec, add tags to EBNF productions
if strings.HasSuffix(abspath, "go_spec.html") { if strings.HasSuffix(abspath, "go_spec.html") {
var buf bytes.Buffer var buf bytes.Buffer
...@@ -1177,6 +1194,7 @@ func search(w http.ResponseWriter, r *http.Request) { ...@@ -1177,6 +1194,7 @@ func search(w http.ResponseWriter, r *http.Request) {
type Metadata struct { type Metadata struct {
Title string Title string
Subtitle string Subtitle string
Template bool // execute as template
Path string // canonical path for this page Path string // canonical path for this page
filePath string // filesystem path relative to goroot filePath string // filesystem path relative to goroot
} }
......
...@@ -38,6 +38,7 @@ import ( ...@@ -38,6 +38,7 @@ import (
"log" "log"
"net/http" "net/http"
_ "net/http/pprof" // to serve /debug/pprof/* _ "net/http/pprof" // to serve /debug/pprof/*
"net/url"
"os" "os"
pathpkg "path" pathpkg "path"
"path/filepath" "path/filepath"
...@@ -69,6 +70,7 @@ var ( ...@@ -69,6 +70,7 @@ var (
// layout control // layout control
html = flag.Bool("html", false, "print HTML in command-line mode") html = flag.Bool("html", false, "print HTML in command-line mode")
srcMode = flag.Bool("src", false, "print (exported) source 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 // command-line searches
query = flag.Bool("q", false, "arguments are considered search queries") query = flag.Bool("q", false, "arguments are considered search queries")
...@@ -225,7 +227,7 @@ func main() { ...@@ -225,7 +227,7 @@ func main() {
flag.Parse() flag.Parse()
// Check usage: either server and no args, command line and args, or index creation mode // 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() usage()
} }
...@@ -286,6 +288,44 @@ func main() { ...@@ -286,6 +288,44 @@ func main() {
return 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 != "" { if *httpAddr != "" {
// HTTP server mode. // HTTP server mode.
var handler http.Handler = http.DefaultServeMux var handler http.Handler = http.DefaultServeMux
...@@ -494,3 +534,13 @@ func main() { ...@@ -494,3 +534,13 @@ func main() {
log.Printf("packageText.Execute: %s", err) 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