diff options
author | Michael Stapelberg <stapelberg@debian.org> | 2013-03-04 21:27:36 +0100 |
---|---|---|
committer | Michael Stapelberg <michael@stapelberg.de> | 2013-03-04 21:27:36 +0100 |
commit | 04b08da9af0c450d645ab7389d1467308cfc2db8 (patch) | |
tree | db247935fa4f2f94408edc3acd5d0d4f997aa0d8 /doc | |
parent | 917c5fb8ec48e22459d77e3849e6d388f93d3260 (diff) | |
download | golang-upstream/1.1_hg20130304.tar.gz |
Imported Upstream version 1.1~hg20130304upstream/1.1_hg20130304
Diffstat (limited to 'doc')
121 files changed, 2665 insertions, 6235 deletions
diff --git a/doc/ExpressivenessOfGo.pdf b/doc/ExpressivenessOfGo.pdf Binary files differdeleted file mode 100644 index f1931d081..000000000 --- a/doc/ExpressivenessOfGo.pdf +++ /dev/null diff --git a/doc/Makefile b/doc/Makefile index b6e475b84..23262da94 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -25,3 +25,8 @@ all: $(RAWHTML) clean: rm -f $(RAWHTML) + +compare: + for i in $(RAWHTML); do \ + godoc -url /doc/$${i/.rawhtml/.html} | diff -u $$i -; \ + done diff --git a/doc/articles/c_go_cgo.html b/doc/articles/c_go_cgo.html index ac6bb29a2..b37a6ba65 100644 --- a/doc/articles/c_go_cgo.html +++ b/doc/articles/c_go_cgo.html @@ -149,9 +149,9 @@ is more complex than a single function call), as in this rewrite of </p> <p> -To build cgo packages, just use <a href="/cmd/go/#Compile_packages_and_dependencies">" +To build cgo packages, just use <a href="/cmd/go/#hdr-Compile_packages_and_dependencies">" <code>go build</code>"</a> or -<a href="/cmd/go/#Compile_and_install_packages_and_dependencies">"<code>go install</code> +<a href="/cmd/go/#hdr-Compile_and_install_packages_and_dependencies">"<code>go install</code> "</a> as usual. The go tool recognizes the special <code>"C"</code> import and automatically uses cgo for those files. </p> @@ -169,9 +169,8 @@ in the Go tree demonstrate more advanced concepts. <p> For a simple, idiomatic example of a cgo-based package, see Russ Cox's <a href="http://code.google.com/p/gosqlite/source/browse/sqlite/sqlite.go">gosqlite</a>. -Also, the Go Project Dashboard lists <a -href="https://godashboard.appspot.com/project?tag=cgo">several other -cgo packages</a>. +Also, the <a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Community Wiki</a> +lists many packages, some of which use cgo. </p> <p> diff --git a/doc/articles/concurrency_patterns.html b/doc/articles/concurrency_patterns.html index 63c8cd59e..62168b840 100644 --- a/doc/articles/concurrency_patterns.html +++ b/doc/articles/concurrency_patterns.html @@ -17,7 +17,7 @@ and launching a goroutine that sleeps before sending on the channel: We can then use a <code>select</code> statement to receive from either <code>ch</code> or <code>timeout</code>. If nothing arrives on <code>ch</code> after one second, the timeout case is selected and the attempt to read from -<cde>ch</cde> is abandoned. +<code>ch</code> is abandoned. </p> {{code "/doc/progs/timeout1.go" `/select {/` `/STOP/`}} @@ -64,7 +64,7 @@ could fail since no one is ready. </p> <p> -This problem is a textbook of example of what is known as a +This problem is a textbook example of what is known as a <a href="https://en.wikipedia.org/wiki/Race_condition">race condition</a>, but the fix is trivial. We just make sure to buffer the channel <code>ch</code> (by adding the buffer length as the second argument to <a href="/pkg/builtin/#make">make</a>), diff --git a/doc/articles/error_handling.html b/doc/articles/error_handling.html index 8f4fffb48..6ba05ac1d 100644 --- a/doc/articles/error_handling.html +++ b/doc/articles/error_handling.html @@ -137,7 +137,7 @@ messages: <p> (This is a slightly simplified version of some -<a href="http://camlistore.org/code/?p=camlistore.git;a=blob;f=lib/go/camli/jsonconfig/eval.go#l68">actual code</a> +<a href="http://golang.org/s/camjsondecode">actual code</a> from the <a href="http://camlistore.org">Camlistore</a> project.) </p> diff --git a/doc/articles/go_command.html b/doc/articles/go_command.html index 1e9e70fd8..fddca41e2 100644 --- a/doc/articles/go_command.html +++ b/doc/articles/go_command.html @@ -48,9 +48,9 @@ had to be installed in certain places, under certain names, using certain build tools, in order to be used. That's understandable: that's the way it works in most other languages. Over the last few years we consistently reminded people about the <code>goinstall</code> command -(now replaced by <a href="/cmd/go/#Download_and_install_packages_and_dependencies"><code>go get</code></a>) +(now replaced by <a href="/cmd/go/#hdr-Download_and_install_packages_and_dependencies"><code>go get</code></a>) and its conventions: first, that the import path is derived in a known way from -the URL of the source code; second, that that the place to store the sources in +the URL of the source code; second, that the place to store the sources in the local file system is derived in a known way from the import path; third, that each directory in a source tree corresponds to a single package; and fourth, that the package is built using only information in the source code. diff --git a/doc/articles/godoc_documenting_go_code.html b/doc/articles/godoc_documenting_go_code.html index ca66076ad..18a3ee953 100644 --- a/doc/articles/godoc_documenting_go_code.html +++ b/doc/articles/godoc_documenting_go_code.html @@ -65,8 +65,8 @@ package's brief description: {{code "/src/pkg/sort/sort.go" `/Package sort provides/` `/package sort/`}} <p> -They can also be detailed like the <a href="/pkg/encoding/gob/">gob package</a>'s -overview. That package uses another convention for packages +They can also be detailed like the <a href="/pkg/encoding/gob/"><code>gob</code></a> +package's overview. That package uses another convention for packages that need large amounts of introductory documentation: the package comment is placed in its own file, <a href="/src/pkg/encoding/gob/doc.go">doc.go</a>, which contains only those comments and a package clause. @@ -80,10 +80,10 @@ sentence will appear in godoc's <a href="/pkg/">package list</a>. <p> Comments that are not adjacent to a top-level declaration are omitted from godoc's output, with one notable exception. Top-level comments that begin with -the word <code>"BUG(who)”</code> are recognized as known bugs, and included in -the "Bugs” section of the package documentation. The "who” part should be the +the word <code>"BUG(who)"</code> are recognized as known bugs, and included in +the "Bugs" section of the package documentation. The "who" part should be the user name of someone who could provide more information. For example, this is a -known issue from the <a href="/pkg/bytes/#bugs">bytes package</a>: +known issue from the <a href="/pkg/bytes/#pkg-bugs"><code>bytes</code></a> package: </p> <pre> @@ -93,7 +93,7 @@ known issue from the <a href="/pkg/bytes/#bugs">bytes package</a>: <p> Godoc treats executable commands somewhat differently. Instead of inspecting the command source code, it looks for a Go source file belonging to the special -package "documentation”. The comment on the "package documentation” clause is +package "documentation". The comment on the "package documentation" clause is used as the command's documentation. For example, see the <a href="/cmd/godoc/">godoc documentation</a> and its corresponding <a href="/src/cmd/godoc/doc.go">doc.go</a> file. @@ -137,3 +137,9 @@ indexing via the <code>-path</code> flag or just by running <code>"godoc ."</cod in the source directory. See the <a href="/cmd/godoc/">godoc documentation</a> for more details. </p> + +<p> +Godoc recognizes example functions written according to the +<a href="/pkg/testing/#pkg-overview"><code>testing</code></a> package's naming +conventions and presents them appropriately. +</p> diff --git a/doc/articles/image_package.html b/doc/articles/image_package.html index a9d2f3581..ebe92a1ca 100644 --- a/doc/articles/image_package.html +++ b/doc/articles/image_package.html @@ -45,7 +45,7 @@ classic algebra: dstr, dstg, dstb, dsta := dst.RGBA() srcr, srcg, srcb, srca := src.RGBA() _, _, _, m := mask.RGBA() -const M = 1<<16 - 1 +const M = 1<<16 - 1 // The resultant red value is a blend of dstr and srcr, and ranges in [0, M]. // The calculation for green, blue and alpha is similar. dstr = (dstr*(M-m) + srcr*m) / M @@ -130,7 +130,7 @@ much easier to type. A <code>Rectangle</code> is inclusive at the top-left and exclusive at the bottom-right. For a <code>Point p</code> and a <code>Rectangle r</code>, <code>p.In(r)</code> if and only if -<code>r.Min.X <= p.X && p.X < r.Max.X</code>, and similarly for <code>Y</code>. This is analagous to how +<code>r.Min.X <= p.X && p.X < r.Max.X</code>, and similarly for <code>Y</code>. This is analagous to how a slice <code>s[i0:i1]</code> is inclusive at the low end and exclusive at the high end. (Unlike arrays and slices, a <code>Rectangle</code> often has a non-zero origin.) @@ -193,8 +193,8 @@ way to iterate over an <code>Image</code> m's pixels looks like: <pre> b := m.Bounds() -for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; y < b.Max.X; x++ { +for y := b.Min.Y; y < b.Max.Y; y++ { + for x := b.Min.X; x < b.Max.X; x++ { doStuffWith(m.At(x, y)) } } diff --git a/doc/articles/json_and_go.html b/doc/articles/json_and_go.html index af7776c0a..8c4ef33a4 100644 --- a/doc/articles/json_and_go.html +++ b/doc/articles/json_and_go.html @@ -43,7 +43,7 @@ and an instance of <code>Message</code> {{code "/doc/progs/json1.go" `/m :=/`}} <p> -we can marshal a JSON-encoded version of m using <code>json.Marshal</code>: +we can marshal a JSON-encoded version of <code>m</code> using <code>json.Marshal</code>: </p> {{code "/doc/progs/json1.go" `/b, err :=/`}} @@ -82,8 +82,8 @@ is <code>nil</code>). <p> The json package only accesses the exported fields of struct types (those that -begin with an uppercase letter). Therefore only the the exported fields of a -struct will be present in the JSON output. +begin with an uppercase letter). Therefore only the exported fields of a struct +will be present in the JSON output. </p> <p> @@ -130,7 +130,7 @@ preference): <ul> <li> -An exported field with a tag of <code>"Foo"</code> (see the +An exported field with a tag of <code>`json:"Foo"`</code> (see the <a href="/ref/spec#Struct_types">Go spec</a> for more on struct tags), </li> <li> @@ -151,11 +151,11 @@ type? <p> <code>Unmarshal</code> will decode only the fields that it can find in the -destination type. In this case, only the Name field of m will be populated, -and the Food field will be ignored. This behavior is particularly useful when -you wish to pick only a few specific fields out of a large JSON blob. It also -means that any unexported fields in the destination struct will be unaffected -by <code>Unmarshal</code>. +destination type. In this case, only the <code>Name</code> field of m will be +populated, and the <code>Food</code> field will be ignored. This behavior is +particularly useful when you wish to pick only a few specific fields out of a +large JSON blob. It also means that any unexported fields in the destination +struct will be unaffected by <code>Unmarshal</code>. </p> <p> @@ -163,7 +163,7 @@ But what if you don't know the structure of your JSON data beforehand? </p> <p> -<b>Generic JSON with interface{}</b> +<b>Generic JSON with <code>interface{}</code></b> </p> <p> @@ -190,11 +190,12 @@ Or, if the underlying type is unknown, a type switch determines the type: {{code "/doc/progs/json2.go" `/switch v/` `/STOP/`}} - +<p> The json package uses <code>map[string]interface{}</code> and <code>[]interface{}</code> values to store arbitrary JSON objects and arrays; it will happily unmarshal any valid JSON blob into a plain <code>interface{}</code> value. The default concrete Go types are: +</p> <ul> <li> diff --git a/doc/articles/json_rpc_tale_of_interfaces.html b/doc/articles/json_rpc_tale_of_interfaces.html index a545f55f6..0db366f33 100644 --- a/doc/articles/json_rpc_tale_of_interfaces.html +++ b/doc/articles/json_rpc_tale_of_interfaces.html @@ -57,7 +57,7 @@ original functionality. From there it is simple to build a After some similar changes to the client side, this was the full extent of the work we needed to do on the RPC package. This whole exercise took about 20 minutes! After tidying up and testing the new code, the -<a href="http://code.google.com/p/go/source/diff?spec=svn9daf796ebf1cae97b2fcf760a4ab682f1f063f29&r=9daf796ebf1cae97b2fcf760a4ab682f1f063f29&format=side&path=/src/pkg/rpc/server.go">final changeset</a> +<a href="http://code.google.com/p/go/source/diff?spec=svn9daf796ebf1cae97b2fcf760a4ab682f1f063f29&r=9daf796ebf1cae97b2fcf760a4ab682f1f063f29&format=side&path=/src/pkg/rpc/server.go">final changeset</a> was submitted. </p> diff --git a/doc/articles/laws_of_reflection.html b/doc/articles/laws_of_reflection.html index 826a054f2..81f6697ce 100644 --- a/doc/articles/laws_of_reflection.html +++ b/doc/articles/laws_of_reflection.html @@ -213,7 +213,7 @@ type: float64 You might be wondering where the interface is here, since the program looks like it's passing the <code>float64</code> variable <code>x</code>, not an interface value, to <code>reflect.TypeOf</code>. But it's there; as -<a href="/pkg/reflect/#Type.TypeOf">godoc reports</a>, the signature of +<a href="/pkg/reflect/#TypeOf">godoc reports</a>, the signature of <code>reflect.TypeOf</code> includes an empty interface: </p> diff --git a/doc/articles/race_detector.html b/doc/articles/race_detector.html new file mode 100644 index 000000000..400d96b19 --- /dev/null +++ b/doc/articles/race_detector.html @@ -0,0 +1,369 @@ +<!--{ + "Title": "Data Race Detector", + "Template": true +}--> + +<h2 id="Introduction">Introduction</h2> + +<p> +Data races are one of the most common and hardest to debug types of bugs in concurrent systems. A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write. See the <a href="/ref/mem/">The Go Memory Model</a> for details. +</p> + +<p> +Here is an example of a data race that can lead to crashes and memory corruption: +</p> + +<pre> +func main() { + c := make(chan bool) + m := make(map[string]string) + go func() { + m["1"] = "a" // First conflicting access. + c <- true + }() + m["2"] = "b" // Second conflicting access. + <-c + for k, v := range m { + fmt.Println(k, v) + } +} +</pre> + +<h2 id="Usage">Usage</h2> + +<p> +Fortunately, Go includes a built-in data race detector. To use it, add the <code>-race</code> flag to the go command: +</p> + +<pre> +$ go test -race mypkg // to test the package +$ go run -race mysrc.go // to run the source file +$ go build -race mycmd // to build the command +$ go install -race mypkg // to install the package +</pre> + +<h2 id="Report_Format">Report Format</h2> + +<p> +When the race detector finds a data race in the program, it prints a report. The report contains stack traces for conflicting accesses, as well as stacks where the involved goroutines were created. For example: +</p> + +<pre> +WARNING: DATA RACE +Read by goroutine 185: + net.(*pollServer).AddFD() + src/pkg/net/fd_unix.go:89 +0x398 + net.(*pollServer).WaitWrite() + src/pkg/net/fd_unix.go:247 +0x45 + net.(*netFD).Write() + src/pkg/net/fd_unix.go:540 +0x4d4 + net.(*conn).Write() + src/pkg/net/net.go:129 +0x101 + net.func·060() + src/pkg/net/timeout_test.go:603 +0xaf + +Previous write by goroutine 184: + net.setWriteDeadline() + src/pkg/net/sockopt_posix.go:135 +0xdf + net.setDeadline() + src/pkg/net/sockopt_posix.go:144 +0x9c + net.(*conn).SetDeadline() + src/pkg/net/net.go:161 +0xe3 + net.func·061() + src/pkg/net/timeout_test.go:616 +0x3ed + +Goroutine 185 (running) created at: + net.func·061() + src/pkg/net/timeout_test.go:609 +0x288 + +Goroutine 184 (running) created at: + net.TestProlongTimeout() + src/pkg/net/timeout_test.go:618 +0x298 + testing.tRunner() + src/pkg/testing/testing.go:301 +0xe8 +</pre> + +<h2 id="Options">Options</h2> + +<p> +The <code>GORACE</code> environment variable sets race detector options. The format is: +</p> + +<pre> +GORACE="option1=val1 option2=val2" +</pre> + +<p> +The options are: +</p> + +<ul> +<li> +<code>log_path</code> (default <code>stderr</code>): The race detector writes +its report to a file named log_path.pid. The special names <code>stdout</code> +and <code>stderr</code> cause reports to be written to standard output and +standard error, respectively. +</li> + +<li> +<code>exitcode</code> (default <code>66</code>): The exit status to use when +exiting after a detected race. +</li> + +<li> +<code>strip_path_prefix</code> (default <code>""</code>): Strip this prefix +from all reported file paths, to make reports more concise. +</li> + +<li> +<code>history_size</code> (default <code>1</code>): The per-goroutine memory +access history is <code>32K * 2**history_size elements</code>. Increasing this +value can avoid a "failed to restore the stack" error in reports, but at the +cost of increased memory usage. +</li> +</ul> + +<p> +Example: +</p> + +<pre> +$ GORACE="log_path=/tmp/race/report strip_path_prefix=/my/go/sources/" go test -race +</pre> + +<h2 id="Excluding_Tests">Excluding Tests</h2> + +<p> +When you build with <code>-race</code> flag, go command defines additional +<a href="/pkg/go/build/#Build_Constraints">build tag</a> <code>race</code>. +You can use it to exclude some code/tests under the race detector. For example: +</p> + +<pre> +// +build !race + +package foo + +// The test contains a data race. See issue 123. +func TestFoo(t *testing.T) { + // ... +} + +// The test fails under the race detector due to timeouts. +func TestBar(t *testing.T) { + // ... +} + +// The test takes too long under the race detector. +func TestBaz(t *testing.T) { + // ... +} +</pre> + +<h2 id="How_To_Use">How To Use</h2> + +<p> +To start, run your tests using the race detector (<code>go test -race</code>). +The race detector only finds races that happen at runtime, so it can't find +races in code paths that are not executed. If your tests have incomplete coverage, +you may find more races by running a binary built with <code>-race</code> under a realistic +workload. +</p> + +<h2 id="Typical_Data_Races">Typical Data Races</h2> + +<p> +Here are some typical data races. All of them can be detected with the race detector. +</p> + +<h3 id="Race_on_loop_counter">Race on loop counter</h3> + +<pre> +func main() { + var wg sync.WaitGroup + wg.Add(5) + for i := 0; i < 5; i++ { + go func() { + fmt.Println(i) // Not the 'i' you are looking for. + wg.Done() + }() + } + wg.Wait() +} +</pre> + +<p> +The variable <code>i</code> in the function literal is the same variable used by the loop, so +the read in the goroutine races with the loop increment. (This program typically +prints 55555, not 01234.) The program can be fixed by making a copy of the +variable: +</p> + +<pre> +func main() { + var wg sync.WaitGroup + wg.Add(5) + for i := 0; i < 5; i++ { + go func(j int) { + fmt.Println(j) // Good. Read local copy of the loop counter. + wg.Done() + }(i) + } + wg.Wait() +} +</pre> + +<h3 id="Accidentally_shared_variable">Accidentally shared variable</h3> + +<pre> +// ParallelWrite writes data to file1 and file2, returns the errors. +func ParallelWrite(data []byte) chan error { + res := make(chan error, 2) + f1, err := os.Create("file1") + if err != nil { + res <- err + } else { + go func() { + // This err is shared with the main goroutine, + // so the write races with the write below. + _, err = f1.Write(data) + res <- err + f1.Close() + }() + } + f2, err := os.Create("file2") // The second conflicting write to err. + if err != nil { + res <- err + } else { + go func() { + _, err = f2.Write(data) + res <- err + f2.Close() + }() + } + return res +} +</pre> + +<p> +The fix is to introduce new variables in the goroutines (note <code>:=</code>): +</p> + +<pre> + ... + _, err := f1.Write(data) + ... + _, err := f2.Write(data) + ... +</pre> + +<h3 id="Unprotected_global_variable">Unprotected global variable</h3> + +<p> +If the following code is called from several goroutines, it leads to bad races on the <code>service</code> map. +Concurrent reads and writes of a map are not safe: +</p> + +<pre> +var service map[string]net.Addr + +func RegisterService(name string, addr net.Addr) { + service[name] = addr +} + +func LookupService(name string) net.Addr { + return service[name] +} +</pre> + +<p> +To make the code safe, protect the accesses with a mutex: +</p> + +<pre> +var ( + service map[string]net.Addr + serviceMu sync.Mutex +) + +func RegisterService(name string, addr net.Addr) { + serviceMu.Lock() + defer serviceMu.Unlock() + service[name] = addr +} + +func LookupService(name string) net.Addr { + serviceMu.Lock() + defer serviceMu.Unlock() + return service[name] +} +</pre> + +<h3 id="Primitive_unprotected_variable">Primitive unprotected variable</h3> + +<p> +Data races can happen on variables of primitive types as well (<code>bool</code>, <code>int</code>, <code>int64</code>, etc.), like in the following example: +</p> + +<pre> +type Watchdog struct{ last int64 } + +func (w *Watchdog) KeepAlive() { + w.last = time.Now().UnixNano() // First conflicting access. +} + +func (w *Watchdog) Start() { + go func() { + for { + time.Sleep(time.Second) + // Second conflicting access. + if w.last < time.Now().Add(-10*time.Second).UnixNano() { + fmt.Println("No keepalives for 10 seconds. Dying.") + os.Exit(1) + } + } + }() +} +</pre> + +<p> +Even such “innocent” data races can lead to hard to debug problems caused by (1) non-atomicity of the memory accesses, (2) interference with compiler optimizations and (3) processor memory access reordering issues. +</p> + +<p> +A typical fix for this race is to use a channel or a mutex. +To preserve the lock-free behavior, one can also use the <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a> package. +</p> + +<pre> +type Watchdog struct{ last int64 } + +func (w *Watchdog) KeepAlive() { + atomic.StoreInt64(&w.last, time.Now().UnixNano()) +} + +func (w *Watchdog) Start() { + go func() { + for { + time.Sleep(time.Second) + if atomic.LoadInt64(&w.last) < time.Now().Add(-10*time.Second).UnixNano() { + fmt.Println("No keepalives for 10 seconds. Dying.") + os.Exit(1) + } + } + }() +} +</pre> + +<h2 id="Supported_Systems">Supported Systems</h2> + +<p> +The race detector runs on <code>darwin/amd64</code>, <code>linux/amd64</code>, and <code>windows/amd64</code>. +</p> + +<h2 id="Runtime_Overheads">Runtime Overhead</h2> + +<p> +The cost of race detection varies by program, but for a typical program, memory +usage may increase by 5-10x and execution time by 2-20x. +</p> diff --git a/doc/articles/slices_usage_and_internals.html b/doc/articles/slices_usage_and_internals.html index 810b0a41f..7eb751b45 100644 --- a/doc/articles/slices_usage_and_internals.html +++ b/doc/articles/slices_usage_and_internals.html @@ -243,7 +243,7 @@ slice itself) of a re-slice modifies the elements of the original slice: d := []byte{'r', 'o', 'a', 'd'} e := d[2:] // e == []byte{'a', 'd'} -e[1] == 'm' +e[1] = 'm' // e == []byte{'a', 'm'} // d == []byte{'r', 'o', 'a', 'm'} </pre> diff --git a/doc/articles/wiki/get.go b/doc/articles/wiki/get.go index c6e9bf28b..b3e464b34 100644 --- a/doc/articles/wiki/get.go +++ b/doc/articles/wiki/get.go @@ -13,11 +13,13 @@ import ( "net/http" "os" "strings" + "time" ) var ( post = flag.String("post", "", "urlencoded form data to POST") addr = flag.Bool("addr", false, "find open address and print to stdout") + wait = flag.Duration("wait_for_port", 0, "if non-zero, the amount of time to wait for the address to become available") ) func main() { @@ -37,11 +39,18 @@ func main() { } var r *http.Response var err error - if *post != "" { - b := strings.NewReader(*post) - r, err = http.Post(url, "application/x-www-form-urlencoded", b) - } else { - r, err = http.Get(url) + loopUntil := time.Now().Add(*wait) + for { + if *post != "" { + b := strings.NewReader(*post) + r, err = http.Post(url, "application/x-www-form-urlencoded", b) + } else { + r, err = http.Get(url) + } + if err == nil || *wait == 0 || time.Now().After(loopUntil) { + break + } + time.Sleep(100 * time.Millisecond) } if err != nil { log.Fatal(err) diff --git a/doc/articles/wiki/index.html b/doc/articles/wiki/index.html index 6c45d7178..ea3507f4d 100644 --- a/doc/articles/wiki/index.html +++ b/doc/articles/wiki/index.html @@ -46,7 +46,7 @@ $ cd gowiki </pre> <p> -Create a file named <code>wiki.go</code>, open it in your favorite editor, and +Create a file named <code>wiki.go</code>, open it in your favorite editor, and add the following lines: </p> @@ -60,8 +60,8 @@ import ( </pre> <p> -We import the <code>fmt</code> and <code>ioutil</code> packages from the Go -standard library. Later, as we implement additional functionality, we will +We import the <code>fmt</code> and <code>ioutil</code> packages from the Go +standard library. Later, as we implement additional functionality, we will add more packages to this <code>import</code> declaration. </p> @@ -77,7 +77,7 @@ the title and body. {{code "doc/articles/wiki/part1.go" `/^type Page/` `/}/`}} <p> -The type <code>[]byte</code> means "a <code>byte</code> slice". +The type <code>[]byte</code> means "a <code>byte</code> slice". (See <a href="/doc/articles/slices_usage_and_internals.html">Slices: usage and internals</a> for more on slices.) The <code>Body</code> element is a <code>[]byte</code> rather than @@ -86,8 +86,8 @@ libraries we will use, as you'll see below. </p> <p> -The <code>Page</code> struct describes how page data will be stored in memory. -But what about persistent storage? We can address that by creating a +The <code>Page</code> struct describes how page data will be stored in memory. +But what about persistent storage? We can address that by creating a <code>save</code> method on <code>Page</code>: </p> @@ -96,11 +96,11 @@ But what about persistent storage? We can address that by creating a <p> This method's signature reads: "This is a method named <code>save</code> that takes as its receiver <code>p</code>, a pointer to <code>Page</code> . It takes -no parameters, and returns a value of type <code>error</code>." +no parameters, and returns a value of type <code>error</code>." </p> <p> -This method will save the <code>Page</code>'s <code>Body</code> to a text +This method will save the <code>Page</code>'s <code>Body</code> to a text file. For simplicity, we will use the <code>Title</code> as the file name. </p> @@ -110,35 +110,37 @@ that is the return type of <code>WriteFile</code> (a standard library function that writes a byte slice to a file). The <code>save</code> method returns the error value, to let the application handle it should anything go wrong while writing the file. If all goes well, <code>Page.save()</code> will return -<code>nil</code> (the zero-value for pointers, interfaces, and some other +<code>nil</code> (the zero-value for pointers, interfaces, and some other types). </p> <p> -The octal integer constant <code>0600</code>, passed as the third parameter to +The octal integer literal <code>0600</code>, passed as the third parameter to <code>WriteFile</code>, indicates that the file should be created with read-write permissions for the current user only. (See the Unix man page <code>open(2)</code> for details.) </p> <p> -We will want to load pages, too: +In addition to saving pages, we will want to load pages, too: </p> {{code "doc/articles/wiki/part1-noerror.go" `/^func loadPage/` `/^}/`}} <p> The function <code>loadPage</code> constructs the file name from -<code>Title</code>, reads the file's contents into a new -<code>Page</code>, and returns a pointer to that new <code>page</code>. +the title parameter, reads the file's contents into a new +variable <code>body</code>, and returns two values: a pointer to a +<code>Page</code> literal constructed with the proper title and body +values and <code>nil</code> for the error value. </p> <p> -Functions can return multiple values. The standard library function -<code>io.ReadFile</code> returns <code>[]byte</code> and <code>error</code>. +Functions can return multiple values. The standard library function +<code>io.ReadFile</code> returns <code>[]byte</code> and <code>error</code>. In <code>loadPage</code>, error isn't being handled yet; the "blank identifier" represented by the underscore (<code>_</code>) symbol is used to throw away the -error return value (in essence, assigning the value to nothing). +error return value (in essence, assigning the value to nothing). </p> <p> @@ -152,7 +154,7 @@ function to return <code>*Page</code> and <code>error</code>. <p> Callers of this function can now check the second parameter; if it is <code>nil</code> then it has successfully loaded a Page. If not, it will be an -<code>error</code> that can be handled by the caller (see the +<code>error</code> that can be handled by the caller (see the <a href="/ref/spec#Errors">language specification</a> for details). </p> @@ -172,7 +174,7 @@ printed to the screen. </p> <p> -You can compile and run the program like this: +You can compile and run the program like this: </p> <pre> @@ -182,7 +184,7 @@ This is a sample page. </pre> <p> -(If you're using Windows you must type "<code>wiki</code>" without the +(If you're using Windows you must type "<code>wiki</code>" without the "<code>./</code>" to run the program.) </p> @@ -199,10 +201,10 @@ Here's a full working example of a simple web server: {{code "doc/articles/wiki/http-sample.go"}} <p> -The <code>main</code> function begins with a call to -<code>http.HandleFunc</code>, which tells the <code>http</code> package to -handle all requests to the web root (<code>"/"</code>) with -<code>handler</code>. +The <code>main</code> function begins with a call to +<code>http.HandleFunc</code>, which tells the <code>http</code> package to +handle all requests to the web root (<code>"/"</code>) with +<code>handler</code>. </p> <p> @@ -219,20 +221,20 @@ its arguments. </p> <p> -An <code>http.ResponseWriter</code> value assembles the HTTP server's response; by writing +An <code>http.ResponseWriter</code> value assembles the HTTP server's response; by writing to it, we send data to the HTTP client. </p> <p> An <code>http.Request</code> is a data structure that represents the client -HTTP request. The string <code>r.URL.Path</code> is the path component -of the request URL. The trailing <code>[1:]</code> means -"create a sub-slice of <code>Path</code> from the 1st character to the end." +HTTP request. <code>r.URL.Path</code> is the path component +of the request URL. The trailing <code>[1:]</code> means +"create a sub-slice of <code>Path</code> from the 1st character to the end." This drops the leading "/" from the path name. </p> <p> -If you run this program and access the URL: +If you run this program and access the URL: </p> <pre>http://localhost:8080/monkeys</pre> <p> @@ -249,13 +251,14 @@ To use the <code>net/http</code> package, it must be imported: <pre> import ( "fmt" - <b>"net/http"</b> "io/ioutil" + <b>"net/http"</b> ) </pre> <p> -Let's create a handler to view a wiki page: +Let's create a handler, <code>viewHandler</code> that will allow users to +view a wiki page. It will handle URLs prefixed with "/view/". </p> {{code "doc/articles/wiki/part2.go" `/^const lenPath/`}} @@ -264,28 +267,28 @@ Let's create a handler to view a wiki page: <p> First, this function extracts the page title from <code>r.URL.Path</code>, -the path component of the request URL. The global constant +the path component of the request URL. The global constant <code>lenPath</code> is the length of the leading <code>"/view/"</code> component of the request path. -The <code>Path</code> is re-sliced with <code>[lenPath:]</code> to drop the -first 6 characters of the string. This is because the path will invariably -begin with <code>"/view/"</code>, which is not part of the page title. +The <code>Path</code> is re-sliced with <code>[lenPath:]</code> to drop the +first 6 characters of the string. This is because the path will invariably +begin with <code>"/view/"</code>, which is not part of the page's title. </p> <p> -The function then loads the page data, formats the page with a string of simple -HTML, and writes it to <code>w</code>, the <code>http.ResponseWriter</code>. +The function then loads the page data, formats the page with a string of simple +HTML, and writes it to <code>w</code>, the <code>http.ResponseWriter</code>. </p> <p> -Again, note the use of <code>_</code> to ignore the <code>error</code> +Again, note the use of <code>_</code> to ignore the <code>error</code> return value from <code>loadPage</code>. This is done here for simplicity and generally considered bad practice. We will attend to this later. </p> <p> -To use this handler, we create a <code>main</code> function that -initializes <code>http</code> using the <code>viewHandler</code> to handle +To use this handler, we rewrite our <code>main</code> function to +initialize <code>http</code> using the <code>viewHandler</code> to handle any requests under the path <code>/view/</code>. </p> @@ -311,6 +314,11 @@ $ ./wiki </pre> <p> +(If you're using Windows you must type "<code>wiki</code>" without the +"<code>./</code>" to run the program.) +</p> + +<p> With this web server running, a visit to <code><a href="http://localhost:8080/view/test">http://localhost:8080/view/test</a></code> should show a page titled "test" containing the words "Hello world". @@ -326,14 +334,14 @@ form. </p> <p> -First, we add them to <code>main()</code>: +First, we add them to <code>main()</code>: </p> {{code "doc/articles/wiki/final-noclosure.go" `/^func main/` `/^}/`}} <p> -The function <code>editHandler</code> loads the page -(or, if it doesn't exist, create an empty <code>Page</code> struct), +The function <code>editHandler</code> loads the page +(or, if it doesn't exist, create an empty <code>Page</code> struct), and displays an HTML form. </p> @@ -343,7 +351,7 @@ and displays an HTML form. This function will work fine, but all that hard-coded HTML is ugly. Of course, there is a better way. </p> - + <h2>The <code>html/template</code> package</h2> <p> @@ -354,20 +362,20 @@ underlying Go code. </p> <p> -First, we must add <code>html/template</code> to the list of imports: +First, we must add <code>html/template</code> to the list of imports. We +also won't be using <code>fmt</code> anymore, so we have to remove that. </p> <pre> import ( <b>"html/template"</b> - "http" "io/ioutil" - "os" + "net/http" ) </pre> <p> -Let's create a template file containing the HTML form. +Let's create a template file containing the HTML form. Open a new file named <code>edit.html</code>, and add the following lines: </p> @@ -381,8 +389,8 @@ HTML: {{code "doc/articles/wiki/final-noerror.go" `/^func editHandler/` `/^}/`}} <p> -The function <code>template.ParseFiles</code> will read the contents of -<code>edit.html</code> and return a <code>*template.Template</code>. +The function <code>template.ParseFiles</code> will read the contents of +<code>edit.html</code> and return a <code>*template.Template</code>. </p> <p> @@ -405,12 +413,7 @@ HTML. </p> <p> -Now that we've removed the <code>fmt.Fprintf</code> statement, we can remove -<code>"fmt"</code> from the <code>import</code> list. -</p> - -<p> -While we're working with templates, let's create a template for our +Since we're working with templates now, let's create a template for our <code>viewHandler</code> called <code>view.html</code>: </p> @@ -428,28 +431,31 @@ handlers. Let's remove this duplication by moving the templating code to its own function: </p> +{{code "doc/articles/wiki/final-template.go" `/^func renderTemplate/` `/^}/`}} {{code "doc/articles/wiki/final-template.go" `/^func viewHandler/` `/^}/`}} {{code "doc/articles/wiki/final-template.go" `/^func editHandler/` `/^}/`}} -{{code "doc/articles/wiki/final-template.go" `/^func renderTemplate/` `/^}/`}} <p> -The handlers are now shorter and simpler. +If we comment out the registration of our unimplemented save handler in +<code>main</code>, we can once again build and test our program. +<a href="part3.go">Click here to view the code we've written so far.</a> </p> <h2>Handling non-existent pages</h2> <p> What if you visit <a href="http://localhost:8080/view/APageThatDoesntExist"> -<code>/view/APageThatDoesntExist</code></a>? The program will crash. This is -because it ignores the error return value from <code>loadPage</code>. Instead, -if the requested Page doesn't exist, it should redirect the client to the edit -Page so the content may be created: +<code>/view/APageThatDoesntExist</code></a>? You'll see a page containing +HTML. This is because it ignores the error return value from +<code>loadPage</code> and continues to try and fill out the template +with no data. Instead, if the requested Page doesn't exist, it should +redirect the client to the edit Page so the content may be created: </p> -{{code "doc/articles/wiki/final-noclosure.go" `/^func viewHandler/` `/^}/`}} +{{code "doc/articles/wiki/part3-errorhandling.go" `/^func viewHandler/` `/^}/`}} <p> -The <code>http.Redirect</code> function adds an HTTP status code of +The <code>http.Redirect</code> function adds an HTTP status code of <code>http.StatusFound</code> (302) and a <code>Location</code> header to the HTTP response. </p> @@ -457,22 +463,24 @@ header to the HTTP response. <h2>Saving Pages</h2> <p> -The function <code>saveHandler</code> will handle the form submission. +The function <code>saveHandler</code> will handle the submission of forms +located on the edit pages. After uncommenting the related line in +<code>main</code>, let's implement the the handler: </p> {{code "doc/articles/wiki/final-template.go" `/^func saveHandler/` `/^}/`}} <p> -The page title (provided in the URL) and the form's only field, -<code>Body</code>, are stored in a new <code>Page</code>. +The page title (provided in the URL) and the form's only field, +<code>Body</code>, are stored in a new <code>Page</code>. The <code>save()</code> method is then called to write the data to a file, and the client is redirected to the <code>/view/</code> page. </p> <p> The value returned by <code>FormValue</code> is of type <code>string</code>. -We must convert that value to <code>[]byte</code> before it will fit into -the <code>Page</code> struct. We use <code>[]byte(body)</code> to perform +We must convert that value to <code>[]byte</code> before it will fit into +the <code>Page</code> struct. We use <code>[]byte(body)</code> to perform the conversion. </p> @@ -481,9 +489,9 @@ the conversion. <p> There are several places in our program where errors are being ignored. This is bad practice, not least because when an error does occur the program will -crash. A better solution is to handle the errors and return an error message -to the user. That way if something does go wrong, the server will continue to -function and the user will be notified. +have unintended behavior. A better solution is to handle the errors and return +an error message to the user. That way if something does go wrong, the server +will function exactly how we want and the user can be notified. </p> <p> @@ -493,7 +501,7 @@ First, let's handle the errors in <code>renderTemplate</code>: {{code "doc/articles/wiki/final-parsetemplate.go" `/^func renderTemplate/` `/^}/`}} <p> -The <code>http.Error</code> function sends a specified HTTP response code +The <code>http.Error</code> function sends a specified HTTP response code (in this case "Internal Server Error") and error message. Already the decision to put this in a separate function is paying off. </p> @@ -502,18 +510,18 @@ Already the decision to put this in a separate function is paying off. Now let's fix up <code>saveHandler</code>: </p> -{{code "doc/articles/wiki/final-noclosure.go" `/^func saveHandler/` `/^}/`}} +{{code "doc/articles/wiki/part3-errorhandling.go" `/^func saveHandler/` `/^}/`}} <p> -Any errors that occur during <code>p.save()</code> will be reported +Any errors that occur during <code>p.save()</code> will be reported to the user. </p> <h2>Template caching</h2> <p> -There is an inefficiency in this code: <code>renderTemplate</code> calls -<code>ParseFiles</code> every time a page is rendered. +There is an inefficiency in this code: <code>renderTemplate</code> calls +<code>ParseFiles</code> every time a page is rendered. A better approach would be to call <code>ParseFiles</code> once at program initialization, parsing all templates into a single <code>*Template</code>. Then we can use the @@ -536,10 +544,11 @@ can't be loaded the only sensible thing to do is exit the program. </p> <p> -A <code>for</code> loop is used with a <code>range</code> statement to iterate -over an array constant containing the names of the templates we want parsed. -If we were to add more templates to our program, we would add their names to -that array. +The <code>ParseFiles</code> function takes any number of string arguments that +identify our template files, and parses those files into templates that are +named after the base file name. If we were to add more templates to our +program, we would add their names to the <code>ParseFiles</code> call's +arguments. </p> <p> @@ -571,25 +580,27 @@ Then we can create a global variable to store our validation regexp: {{code "doc/articles/wiki/final-noclosure.go" `/^var titleValidator/`}} <p> -The function <code>regexp.MustCompile</code> will parse and compile the -regular expression, and return a <code>regexp.Regexp</code>. +The function <code>regexp.MustCompile</code> will parse and compile the +regular expression, and return a <code>regexp.Regexp</code>. <code>MustCompile</code> is distinct from <code>Compile</code> in that it will panic if the expression compilation fails, while <code>Compile</code> returns -an <code>error</code> as a second parameter. +an <code>error</code> as a second parameter. </p> <p> -Now, let's write a function that extracts the title string from the request -URL, and tests it against our <code>TitleValidator</code> expression: +Now, let's write a function, <code>getTitle</code>, that extracts the title +string from the request URL, and tests it against our +<code>TitleValidator</code> expression: </p> {{code "doc/articles/wiki/final-noclosure.go" `/func getTitle/` `/^}/`}} <p> If the title is valid, it will be returned along with a <code>nil</code> -error value. If the title is invalid, the function will write a -"404 Not Found" error to the HTTP connection, and return an error to the -handler. +error value. If the title is invalid, the function will write a +"404 Not Found" error to the HTTP connection, and return an error to the +handler. To create a new error, we have to import the <code>errors</code> +package. </p> <p> @@ -604,10 +615,10 @@ Let's put a call to <code>getTitle</code> in each of the handlers: <p> Catching the error condition in each handler introduces a lot of repeated code. -What if we could wrap each of the handlers in a function that does this -validation and error checking? Go's -<a href="/ref/spec#Function_declarations">function -literals</a> provide a powerful means of abstracting functionality +What if we could wrap each of the handlers in a function that does this +validation and error checking? Go's +<a href="/ref/spec#Function_declarations">function +literals</a> provide a powerful means of abstracting functionality that can help us here. </p> @@ -654,19 +665,19 @@ Now we can take the code from <code>getTitle</code> and use it here <p> The closure returned by <code>makeHandler</code> is a function that takes an <code>http.ResponseWriter</code> and <code>http.Request</code> (in other -words, an <code>http.HandlerFunc</code>). +words, an <code>http.HandlerFunc</code>). The closure extracts the <code>title</code> from the request path, and validates it with the <code>TitleValidator</code> regexp. If the <code>title</code> is invalid, an error will be written to the -<code>ResponseWriter</code> using the <code>http.NotFound</code> function. +<code>ResponseWriter</code> using the <code>http.NotFound</code> function. If the <code>title</code> is valid, the enclosed handler function <code>fn</code> will be called with the <code>ResponseWriter</code>, <code>Request</code>, and <code>title</code> as arguments. </p> <p> -Now we can wrap the handler functions with <code>makeHandler</code> in -<code>main</code>, before they are registered with the <code>http</code> +Now we can wrap the handler functions with <code>makeHandler</code> in +<code>main</code>, before they are registered with the <code>http</code> package: </p> @@ -698,7 +709,7 @@ $ ./wiki <p> Visiting <a href="http://localhost:8080/view/ANewPage">http://localhost:8080/view/ANewPage</a> -should present you with the page edit form. You should then be able to +should present you with the page edit form. You should then be able to enter some text, click 'Save', and be redirected to the newly created page. </p> @@ -710,11 +721,11 @@ Here are some simple tasks you might want to tackle on your own: <ul> <li>Store templates in <code>tmpl/</code> and page data in <code>data/</code>. -<li>Add a handler to make the web root redirect to +<li>Add a handler to make the web root redirect to <code>/view/FrontPage</code>.</li> <li>Spruce up the page templates by making them valid HTML and adding some CSS rules.</li> -<li>Implement inter-page linking by converting instances of +<li>Implement inter-page linking by converting instances of <code>[PageName]</code> to <br> <code><a href="/view/PageName">PageName</a></code>. (hint: you could use <code>regexp.ReplaceAllFunc</code> to do this) diff --git a/doc/articles/wiki/part3-errorhandling.go b/doc/articles/wiki/part3-errorhandling.go new file mode 100644 index 000000000..945aa1e39 --- /dev/null +++ b/doc/articles/wiki/part3-errorhandling.go @@ -0,0 +1,75 @@ +// Copyright 2010 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. + +package main + +import ( + "html/template" + "io/ioutil" + "net/http" +) + +type Page struct { + Title string + Body []byte +} + +func (p *Page) save() error { + filename := p.Title + ".txt" + return ioutil.WriteFile(filename, p.Body, 0600) +} + +func loadPage(title string) (*Page, error) { + filename := title + ".txt" + body, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + return &Page{Title: title, Body: body}, nil +} + +const lenPath = len("/view/") + +func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) { + t, _ := template.ParseFiles(tmpl + ".html") + t.Execute(w, p) +} + +func viewHandler(w http.ResponseWriter, r *http.Request) { + title := r.URL.Path[lenPath:] + p, err := loadPage(title) + if err != nil { + http.Redirect(w, r, "/edit/"+title, http.StatusFound) + return + } + renderTemplate(w, "view", p) +} + +func editHandler(w http.ResponseWriter, r *http.Request) { + title := r.URL.Path[lenPath:] + p, err := loadPage(title) + if err != nil { + p = &Page{Title: title} + } + renderTemplate(w, "edit", p) +} + +func saveHandler(w http.ResponseWriter, r *http.Request) { + title := r.URL.Path[lenPath:] + body := r.FormValue("body") + p := &Page{Title: title, Body: []byte(body)} + err := p.save() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + http.Redirect(w, r, "/view/"+title, http.StatusFound) +} + +func main() { + http.HandleFunc("/view/", viewHandler) + http.HandleFunc("/edit/", editHandler) + http.HandleFunc("/save/", saveHandler) + http.ListenAndServe(":8080", nil) +} diff --git a/doc/articles/wiki/part3.go b/doc/articles/wiki/part3.go new file mode 100644 index 000000000..7fe4351af --- /dev/null +++ b/doc/articles/wiki/part3.go @@ -0,0 +1,59 @@ +// Copyright 2010 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. + +package main + +import ( + "html/template" + "io/ioutil" + "net/http" +) + +type Page struct { + Title string + Body []byte +} + +func (p *Page) save() error { + filename := p.Title + ".txt" + return ioutil.WriteFile(filename, p.Body, 0600) +} + +func loadPage(title string) (*Page, error) { + filename := title + ".txt" + body, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + return &Page{Title: title, Body: body}, nil +} + +const lenPath = len("/view/") + +func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) { + t, _ := template.ParseFiles(tmpl + ".html") + t.Execute(w, p) +} + +func viewHandler(w http.ResponseWriter, r *http.Request) { + title := r.URL.Path[lenPath:] + p, _ := loadPage(title) + renderTemplate(w, "view", p) +} + +func editHandler(w http.ResponseWriter, r *http.Request) { + title := r.URL.Path[lenPath:] + p, err := loadPage(title) + if err != nil { + p = &Page{Title: title} + } + renderTemplate(w, "edit", p) +} + +func main() { + http.HandleFunc("/view/", viewHandler) + http.HandleFunc("/edit/", editHandler) + //http.HandleFunc("/save/", saveHandler) + http.ListenAndServe(":8080", nil) +} diff --git a/doc/articles/wiki/test.bash b/doc/articles/wiki/test.bash index 5c2cb60dc..02ed1894a 100755 --- a/doc/articles/wiki/test.bash +++ b/doc/articles/wiki/test.bash @@ -18,11 +18,10 @@ go build -o final-test.bin final-test.go (./final-test.bin) & wiki_pid=$! -sleep 1 - -./get.bin http://$addr/edit/Test > test_edit.out +./get.bin --wait_for_port=5s http://$addr/edit/Test > test_edit.out diff -u test_edit.out test_edit.good -./get.bin -post=body=some%20content http://$addr/save/Test +./get.bin -post=body=some%20content http://$addr/save/Test > test_save.out +diff -u test_save.out test_view.good # should be the same as viewing diff -u Test.txt test_Test.txt.good ./get.bin http://$addr/view/Test > test_view.out diff -u test_view.out test_view.good diff --git a/doc/code.html b/doc/code.html index efbe7eed0..82b211870 100644 --- a/doc/code.html +++ b/doc/code.html @@ -10,6 +10,10 @@ introduces the <a href="/cmd/go/">go command</a>, the standard way to fetch, build, and install Go packages and commands. </p> +<p> +This content is also available as a <a href="http://www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>. +</p> + <h2 id="GOPATH">Code organization</h2> @@ -182,7 +186,7 @@ func Sqrt(x float64) float64 { // This is a terrible implementation. // Real code should import "math" and use math.Sqrt. z := 0.0 - for i := 0; i < 1000; i++ { + for i := 0; i < 1000; i++ { z -= (z*z - x) / (2 * x) } return z @@ -402,7 +406,7 @@ ok example/newmath 0.165s </pre> <p> -Run <code><a href="/cmd/go/#Test_packages">go help test</a></code> and see the +Run <code><a href="/cmd/go/#hdr-Test_packages">go help test</a></code> and see the <a href="/pkg/testing/">testing package documentation</a> for more detail. </p> @@ -476,13 +480,13 @@ import "code.google.com/p/go.example/newmath" <p> This convention is the easiest way to make your Go packages available for others to use. -The <a href="http://godashboard.appspot.com">Go Project Dashboard</a> -is a list of external Go projects including programs and libraries. +The <a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Community Wiki</a> +has a list of external Go projects including programs and libraries. </p> <p> For more information on using remote repositories with the <code>go</code> command, see -<code><a href="/cmd/go/#Remote_import_path_syntax">go help remote</a></code>. +<code><a href="/cmd/go/#hdr-Remote_import_path_syntax">go help remote</a></code>. </p> diff --git a/doc/codereview_with_mq.html b/doc/codereview_with_mq.html deleted file mode 100644 index 38ecbda6e..000000000 --- a/doc/codereview_with_mq.html +++ /dev/null @@ -1,115 +0,0 @@ -<!--{ - "Title": "Using Mercurial Queues with Codereview" -}--> - -<h2 id="Introduction">Introduction</h2> - -<p> -The Mercurial Queues extension (<code>mq</code>) provides a mechanism for -managing patches on top of a Mercurial repository and is described in detail -in Chapters -<a href="http://hgbook.red-bean.com/read/managing-change-with-mercurial-queues.html">12</a> -and <a href="http://hgbook.red-bean.com/read/advanced-uses-of-mercurial-queues.html">13</a> -of <a href="http://hgbook.red-bean.com/read/">Mercurial: The Definitive Guide</a>. -This document explains how to use <code>mq</code> in conjunction -with the <code>codereview</code> Mercurial extension described in the -instructions for <a href="contribute.html">contributing to the Go project</a>. -It assumes you have read those instructions. -</p> - -<h2>Configuration</h2> - -<p> -To enable <code>mq</code> edit either <code>$HOME/.hgrc</code> (to enable it -for all of your repositories) or <code>$GOROOT/.hg/hgrc</code> (to enable it for the -repository at <code>$GOROOT</code>) to add:</p> - -<pre> -[extensions] -mq= -</pre> - -<p> -Since pulling, pushing, updating and committing while <code>mq</code> patches -are applied can damage your repository or a remote one, add these lines to -prevent that case: -</p> - -<pre> -[hooks] -# Prevent "hg pull" if MQ patches are applied. -prechangegroup.mq-no-pull = ! hg qtop > /dev/null 2>&1 -# Prevent "hg push" if MQ patches are applied. -preoutgoing.mq-no-push = ! hg qtop > /dev/null 2>&1 -# Prevent "hg update" if MQ patches are applied. -preupdate.mq-no-update = ! hg qtop > /dev/null 2>&1 -</pre> - -<h2>Making a change</h2> - -<p> -The entire checked-out tree is writable and you can use <code>mq</code>, -as documented in Chapter -<a href="http://hgbook.red-bean.com/read/managing-change-with-mercurial-queues.html">12</a> -of "The Guide", -to implement your change as a single patch or a series of patches. - -</p> - -<p>When you are ready to send a change out for review, run</p> - -<pre> -$ hg change -</pre> - -<p>from any directory in your Go repository with all of the <code>mq</code> patches relevant to your -change applied and then proceed as instructed in <a href="contribute.html">contributing -to the Go project</a>. -</p> - -<p> -The change number reported by <code>hg change</code>, preceded by a <code>+</code>, -can be used as an <code>mq</code> patch guard to assist in controlling which patches -are applied as described in Chapter -<a href="http://hgbook.red-bean.com/read/advanced-uses-of-mercurial-queues.html">13</a> -of "The Guide". -For example, the command: -</p> - -<pre> -for p in $(hg qapplied); do hg qguard $p +99999; done -</pre> - -<p> -will apply the guard <code>+99999</code> guard to all currently applied <code>mq</code> -patches. -</p> - -<h2>Synchronizing your client</h2> - -<p>While you were working, others might have submitted changes -to the repository and, as explained in <a href="contribute.html">contributing -to the Go project</a>, it is necessary to synchronize your repository using -<code>hg sync</code>before sending your change list for review. -Because <code>hg sync</code> runs <code>hg pull -u</code>, -you should not run <code>hg sync</code> while <code>mq</code> patches are -applied. Instead -pop all your patches before running <code>hg sync</code> and reapply them after -it has completed. -</p> - -<p> -When reapplying the patches, you may need to resolve conflicts -as described in <a href="contribute.html">contributing to the Go project</a>. -</p> - -<h2>Mailing the change for review</h2> - -<p> -You should have all of the <code>mq</code> patches relevant to your -change applied when you run <code>hg mail</code>. - -<h2>Submitting the change after the review</h2> - -If you are a committer, you should have all of the <code>mq</code> patches relevant to your -change applied when you run <code>hg commit</code>. diff --git a/doc/codewalk/codewalk.js b/doc/codewalk/codewalk.js index f780bc7a5..eb4667ac0 100644 --- a/doc/codewalk/codewalk.js +++ b/doc/codewalk/codewalk.js @@ -297,7 +297,7 @@ CodewalkViewer.prototype.updateHeight = function() { }; jQuery(document).ready(function() { - var viewer = new CodewalkViewer(jQuery()); + var viewer = new CodewalkViewer(jQuery('#codewalk-main')); viewer.selectFirstComment(); viewer.targetCommentLinksAtBlank(); viewer.installEventHandlers(); diff --git a/doc/codewalk/markov.xml b/doc/codewalk/markov.xml index b7b711783..7f1281817 100644 --- a/doc/codewalk/markov.xml +++ b/doc/codewalk/markov.xml @@ -58,7 +58,7 @@ Prefix Map key this data. </step> -<step title="The NewChain constructor function" src="doc/codewalk/markov.go:/func New/,/}/"> +<step title="The NewChain constructor function" src="doc/codewalk/markov.go:/func New/,/\n}/"> The <code>Chain</code> struct has two unexported fields (those that do not begin with an upper case character), and so we write a <code>NewChain</code> constructor function that initializes the diff --git a/doc/codewalk/pig.go b/doc/codewalk/pig.go index 10963b4e4..941daaed1 100644 --- a/doc/codewalk/pig.go +++ b/doc/codewalk/pig.go @@ -23,7 +23,7 @@ type score struct { // An action transitions stochastically to a resulting score. type action func(current score) (result score, turnIsOver bool) -// roll returns the (result, turnIsOver) outcome of simulating a die roll. +// roll returns the (result, turnIsOver) outcome of simulating a die roll. // If the roll value is 1, then thisTurn score is abandoned, and the players' // roles swap. Otherwise, the roll value is added to thisTurn. func roll(s score) (score, bool) { diff --git a/doc/contrib.html b/doc/contrib.html index b4bd47e96..a9f12f93f 100644 --- a/doc/contrib.html +++ b/doc/contrib.html @@ -34,9 +34,6 @@ We encourage all Go users to subscribe to <h3 id="release"><a href="/doc/devel/release.html">Release History</a></h3> <p>A summary of the changes between Go releases.</p> -<h3 id="weekly"><a href="/doc/devel/weekly.html">Weekly Snapshot History</a></h3> -<p>A summary of the changes between weekly snapshots of Go.</p> - <h3 id="golang-dev"><a href="http://groups.google.com/group/golang-dev">Developer Mailing List</a></h3> <p>The <a href="http://groups.google.com/group/golang-dev">golang-dev</a> mailing list is for discussing and reviewing code for the Go project.</p> @@ -91,12 +88,15 @@ are particularly in need of outside help. <p>The <a href="http://groups.google.com/group/golang-nuts">golang-nuts</a> mailing list is for general Go discussion.</p> -<h3 id="projects"><a href="http://godashboard.appspot.com/project">Go Project Dashboard</a></h3> +<h3 id="projects"><a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Wiki Projects Page</a></h3> <p>A list of external Go projects including programs and libraries.</p> <h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3> <p><b>#go-nuts</b> on <b>irc.freenode.net</b> is the official Go IRC channel.</p> +<h3 id="pluscom"><a href="https://plus.google.com/communities/114112804251407510571">The Go+ community</a></h3> +<p>The Google+ community for Go enthusiasts.</p> + <h3 id="plus"><a href="https://plus.google.com/101406623878176903605/posts">The Go Programming Language at Google+</a></h3> <p>The Go project's Google+ page.</p> diff --git a/doc/contribute.html b/doc/contribute.html index e1f39ae7e..72c936472 100644 --- a/doc/contribute.html +++ b/doc/contribute.html @@ -7,7 +7,7 @@ <p> This document explains how to contribute changes to the Go project. It assumes you have installed Go using the -<a href="/doc/install">installation instructions</a> and +<a href="/doc/install/source">installation instructions</a> and have <a href="code.html">written and tested your code</a>. (Note that the <code>gccgo</code> frontend lives elsewhere; see <a href="gccgo_contribute.html">Contributing to gccgo</a>.) @@ -46,24 +46,13 @@ tree to make sure the changes don't break other packages or programs: <pre> cd $GOROOT/src -./all.bash +./all.bash # On Windows, run all.bat </pre> <p> -The final line printed by <code>make all</code> should be of the form: +After running for a while, the command should print "<code>ALL TESTS PASSED</code>". </p> -<pre> -<i>N</i> known bugs; 0 unexpected bugs -</pre> - -<p> -The value of <i>N</i> varies over time, but the line must -say “<code>0 unexpected bugs</code>” and must not -add “<code>test output differs</code>.” -</p> - - <h2 id="Code_review">Code review</h2> <p> @@ -104,41 +93,44 @@ the code review extension disables the standard <code>hg commit</code> command. </p> -<p> -Mercurial power users: if you prefer to use the Mercurial Queues extension, see -<a href="codereview_with_mq.html">Using Mercurial Queues with Codereview</a>. -</p> - <h3>Configure the extension</h3> <p>Edit <code>$GOROOT/.hg/hgrc</code> to add:</p> <pre> [extensions] -codereview = YOUR_GO_ROOT/lib/codereview/codereview.py +codereview = $GOROOT/lib/codereview/codereview.py [ui] username = Your Name <you@server.dom> </pre> -<p>Replace YOUR_GO_ROOT with the value of <code>$GOROOT</code>. -The Mercurial configuration file format does not allow environment variable substitution. +<p> The <code>username</code> information will not be used unless you are a committer (see below), but Mercurial complains if it is missing. </p> +<p> +After adding the extension, <code>hg help codereview</code> +will show documentation for its commands. As the codereview extension is only +enabled for your checkout in <code>$GOROOT</code>, the remainder of this +document assumes you are inside <code>$GOROOT</code> when issuing commands. +</p> + <h3>Log in to the code review site.</h3> <p> The code review server uses a Google Account to authenticate. (If you can use the account to <a href="https://www.google.com/accounts/Login?hl=en&continue=http://www.google.com/">sign in at google.com</a>, -you can use it to sign in to the code review server. +you can use it to sign in to the code review server.) The email address you use on the Code Review site will be recorded in the <a href="http://code.google.com/p/go/source/list">Mercurial change log</a> and in the <a href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file. You can <a href="https://www.google.com/accounts/NewAccount">create a Google Account</a> associated with any address where you receive email. +If you've enabled the two-step verification feature, don't forget to generate an +application-specific password and use that when prompted for a password. </p> <pre> @@ -163,6 +155,19 @@ can use that nickname as a shorthand for naming reviewers and the CC list. For example, <code>rsc</code> is an alias for <code>rsc@golang.org</code>. </p> +<h3>Switch to the default branch</h3> + +<p> +Most Go installations use a release branch, but new changes should +only be made to the default branch. (They may be applied later to a release +branch as part of the release process.) +Before making a change, make sure you use the default branch: +</p> + +<pre> +$ hg update default +</pre> + <h3>Make a change</h3> <p> @@ -263,6 +268,8 @@ The special sentence “Fixes issue 159.” associates the change with issue 159 in the <a href="http://code.google.com/p/go/issues/list">Go issue tracker</a>. When this change is eventually submitted, the issue tracker will automatically mark the issue as fixed. +(These conventions are described in detail by the +<a href="http://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control">Google Project Hosting Issue Tracker documentation</a>.) </p> <p> @@ -277,15 +284,37 @@ which <code>hg change</code> will print, something like: CL created: http://codereview.appspot.com/99999 </pre> +<h3>Adding or removing files from an existing change</h3> + <p> -If you need to re-edit the change description, +If you need to re-edit the change description, or change the files included in the CL, run <code>hg change 99999</code>. </p> <p> -You can see a list of your pending changes by running <code>hg pending</code> (<code>hg p</code> for short). +Alternatively, you can use </p> +<pre> +$ hg file 99999 somefile +</pre> + +<p> +to add <code>somefile</code> to CL 99999, and +</p> + +<pre> +$ hg file -d 99999 somefile +</pre> + +<p> +to remove <code>somefile</code> from the CL. +</p> + +<p> +A file may only belong to a single active CL at a time. <code>hg file</code> +will issue a warning if a file is moved between changes. +</p> <h3>Synchronize your client</h3> @@ -378,6 +407,12 @@ changes, but you may still need to run <h3>Mail the change for review</h3> +<p> +Creating or uploading the change uploads a copy of the diff to the code review server, +but it does not notify anyone about it. To do that, you need to run <code>hg mail</code> +(see below). +</p> + <p>To send out a change for review, run <code>hg mail</code> using the change list number assigned during <code>hg change</code>:</p> @@ -399,6 +434,10 @@ $ hg mail -r golang-dev@googlegroups.com --cc math-nuts@swtch.com 99999 <p>Note that <code>-r</code> and <code>--cc</code> cannot be spelled <code>--r</code> or <code>-cc</code>.</p> +<p> +If your change relates to an open issue, please add a comment to the issue +announcing your proposed fix, including a link to your CL. +</p> <h3>Reviewing code</h3> @@ -412,7 +451,18 @@ to send comments back. <h3>Revise and upload</h3> -<p>You will probably revise your code in response to the reviewer comments. +<p> +You will probably revise your code in response to the reviewer comments. When +you have done this, you can upload your change to the code review server +without sending a notification by running <code>hg upload</code> using the change +list number assigned during <code>hg change</code> +</p> + +<pre> +$ hg upload 99999 +</pre> + +<p> When you have revised the code and are ready for another round of review, run </p> @@ -433,39 +483,59 @@ The reviewer approves the change by replying with a mail that says <code>LGTM</code>: looks good to me. </p> -<h3>Submit the change after the review</h3> +<p> +You can see a list of your pending changes by running <code>hg pending</code> (<code>hg p</code> for short). +</p> + +<h3>Reviewing code by others</h3> <p> -After the code has been <code>LGTM</code>'ed, it is time to submit -it to the Mercurial repository. -If you are a committer, you can run: +You can import a CL proposed by someone else into your local Mercurial client +by using the <code>hg clpatch</code> command. Running </p> <pre> -$ hg submit 99999 +$ hg clpatch 99999 </pre> <p> -This checks the change into the repository. -The change description will include a link to the code review, -and the code review will be updated with a link to the change -in the repository. +will apply the latest diff for CL 99999 to your working copy. If any of the +files referenced in CL 99999 have local modifications, <code>clpatch</code> +will refuse to apply the whole diff. Once applied, CL 99999 will show up in +the output of <code>hg pending</code> and others. </p> <p> -If your local copy of the repository is out of date, -<code>hg submit</code> -will refuse the change: +To revert a CL you have applied locally, use the <code>hg revert</code> +command. Running </p> <pre> -$ hg submit 99999 -local repository out of date; must sync before submit +$ hg revert @99999 </pre> <p> +will revert any files mentioned on CL 99999 to their original state. This can +be an effective way of reverting one CL revision and applying another. +</p> + +<p> +Once the CL has been submitted, the next time you run <code>hg sync</code> +it will be removed from your local pending list. Occasionally the pending list +can get out of sync leaving stale references to closed or abandoned CLs. +You can use <code>hg change -D 99999</code> to remove the reference to CL 99999. +</p> + +<h3>Submit the change after the review</h3> + +<p> +After the code has been <code>LGTM</code>'ed, it is time to submit +it to the Mercurial repository. +</p> + +<p> If you are not a committer, you cannot submit the change directly. -Instead, a committer, usually the reviewer who said <code>LGTM</code>, +Instead a committer, usually the reviewer who said <code>LGTM</code>, will run: </p> @@ -474,19 +544,39 @@ $ hg clpatch 99999 $ hg submit 99999 </pre> -<p>The <code>clpatch</code> command imports your change 99999 into -the committer's local Mercurial client, at which point the committer -can check or test the code more. -(Anyone can run <code>clpatch</code> to try a change that -has been uploaded to the code review server.) +<p> The <code>submit</code> command submits the code. You will be listed as the author, but the change message will also indicate who the committer was. Your local client will notice that the change has been submitted when you next run <code>hg sync</code>. </p> +<p> +If you are a committer, you can run: +</p> + +<pre> +$ hg submit 99999 +</pre> + +<p> +This checks the change into the repository. +The change description will include a link to the code review, +and the code review will be updated with a link to the change +in the repository. +</p> -<h3 id="copyright">Copyright</h3> +<p> +If your local copy of the repository is out of date, +<code>hg submit</code> will refuse the change: +</p> + +<pre> +$ hg submit 99999 +local repository out of date; must sync before submit +</pre> + +<h2 id="copyright">Copyright</h2> <p>Files in the Go repository don't list author names, both to avoid clutter and to avoid having to keep the lists up to date. @@ -497,7 +587,7 @@ and perhaps the <a href="/AUTHORS"><code>AUTHORS</code></a> file. <p>The <a href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file defines who the Go contributors—the people—are; -the <a href="/AUTHORS"><code>AUTHORS</code></a> file, which defines +the <a href="/AUTHORS"><code>AUTHORS</code></a> file defines who “The Go Authors”—the copyright holders—are. The Go developers at Google will update these files when submitting your first change. @@ -525,7 +615,12 @@ This rigmarole needs to be done only for your first submission. <p>Code that you contribute should use the standard copyright header:</p> <pre> -// Copyright 2012 The Go Authors. All rights reserved. +// Copyright 2013 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. </pre> + +<p> +Files in the repository are copyright the year they are added. It is not +necessary to update the copyright year on files that you change. +</p> diff --git a/doc/debugging_with_gdb.html b/doc/debugging_with_gdb.html index b2683913f..b893f931a 100644 --- a/doc/debugging_with_gdb.html +++ b/doc/debugging_with_gdb.html @@ -13,7 +13,7 @@ Besides this overview you might want to consult the <p> When you compile and link your Go programs with the <code>gc</code> toolchain -on Linux, Mac OS X or FreeBSD, the resulting binaries contain DWARFv3 +on Linux, Mac OS X, FreeBSD or NetBSD, the resulting binaries contain DWARFv3 debugging information that recent versions (>7.1) of the GDB debugger can use to inspect a live process or a core dump. </p> @@ -23,13 +23,20 @@ Pass the <code>'-s'</code> flag to the linker to omit the debug information (for example, <code>go build -ldflags "-s" prog.go</code>). </p> +<p> +The code generated by the <code>gc</code> compiler includes inlining of +function invocations and registerization of variables. These optimizations +can sometimes make debugging with <code>gdb</code> harder. To disable them +when debugging, pass the flags <code>-gcflags "-N -l"</code> to the +<a href="/cmd/go"><code>go</code></a> command used to build the code being +debugged. +</p> <h3 id="Common_Operations">Common Operations</h3> <ul> <li> -Show file and line number for code -, set breakpoints and disassemble: +Show file and line number for code, set breakpoints and disassemble: <pre>(gdb) <b>list</b> (gdb) <b>list <i>line</i></b> (gdb) <b>list <i>file.go</i>:<i>line</i></b> @@ -172,7 +179,7 @@ $ <b>gdb regexp.test -d $GOROOT</b> If for some reason GDB still can't find that directory or that script, you can load it by hand by telling gdb (assuming you have the go sources in <code>~/go/</code>): -<p> +</p> <pre> (gdb) <b>source ~/go/src/pkg/runtime/runtime-gdb.py</b> diff --git a/doc/devel/release.html b/doc/devel/release.html index 986310610..3340d1e91 100644 --- a/doc/devel/release.html +++ b/doc/devel/release.html @@ -3,11 +3,8 @@ }--> <p>This page summarizes the changes between official stable releases of Go. -Between releases we issue less stable -<a href="http://blog.golang.org/2011/03/go-becomes-more-stable.html">weekly snapshots</a>. -The <a href="weekly.html">weekly snapshot history</a> contains more detail, -and the <a href="http://code.google.com/p/go/source/list">Mercurial change log</a> -has full details.</p> +The <a href="http://code.google.com/p/go/source/list">Mercurial change log</a> +has the full details.</p> <p>To update to a specific release, use:</p> @@ -54,6 +51,10 @@ It also includes many minor code and documentation fixes. </p> <p> +go1.0.3 (released 2012/09/21) includes minor code and documentation fixes. +</p> + +<p> See the <a href="http://code.google.com/p/go/source/list?name=release-branch.go1">go1 release branch history</a> for the complete list of changes. </p> diff --git a/doc/devel/weekly.html b/doc/devel/weekly.html index 46efe41ed..f8d3ec6dd 100644 --- a/doc/devel/weekly.html +++ b/doc/devel/weekly.html @@ -3,18 +3,9 @@ }--> <p>This page summarizes the changes between tagged weekly snapshots of Go. -For full details, see the <a href="http://code.google.com/p/go/source/list">Mercurial change log</a>.</p> +Such snapshots are no longer created. This page remains as a historical reference only.</p> -<p>Weekly snapshots occur often and may not be stable. -If stability of API and code is more important than having the -latest features, use the <a href="release.html">official releases</a> instead.</p> - -<p>To update to a specific snapshot, use:</p> - -<pre> -hg pull -hg update weekly.<i>YYYY-MM-DD</i> -</pre> +<p>For recent information, see the <a href="http://code.google.com/p/go/source/list">Mercurial change log</a> and <a href="http://groups.google.com/group/golang-dev/">development mailing list</a>.</p> <h2 id="2012-03-27">2012-03-27 (<a href="release.html#go1">Go 1</a>)</h2> diff --git a/doc/docs.html b/doc/docs.html index f88e930fb..3112381c2 100644 --- a/doc/docs.html +++ b/doc/docs.html @@ -45,8 +45,10 @@ learned. You can <a href="http://tour.golang.org/">take the tour online</a> or <h3 id="code"><a href="code.html">How to write Go code</a></h3> <p> -How to use the <a href="/cmd/go/">go command</a> to fetch, build, and install -packages, commands, and run tests. +Also available as a +<a href="http://www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>, this doc +explains how to use the <a href="/cmd/go/">go command</a> to fetch, build, and +install packages, commands, and run tests. </p> <h3 id="effective_go"><a href="effective_go.html">Effective Go</a></h3> @@ -56,10 +58,13 @@ A must read for any new Go programmer. It augments the tour and the language specification, both of which should be read first. </p> -<h3 id="appengine"><a href="http://code.google.com/appengine/docs/go/gettingstarted/">Getting Started with Go on App Engine</a></h3> +<h3 id="ref"><a href="/ref/">Go References</a></h3> +<p>Language specification, memory model, and detailed documentation for the commands and packages.</p> + +<h3 id="appengine"><a href="https://developers.google.com/appengine/docs/go/gettingstarted/">Getting Started with Go on App Engine</a></h3> <p> How to develop and deploy a simple Go project with -<a href="http://code.google.com/appengine/">Google App Engine</a>. +<a href="https://developers.google.com/appengine/">Google App Engine</a>. </p> <h3 id="go_faq"><a href="go_faq.html">Frequently Asked Questions (FAQ)</a></h3> @@ -127,6 +132,7 @@ Guided tours of Go programs. <li><a href="/doc/gdb">Debugging Go Code with GDB</a></li> <li><a href="/doc/articles/godoc_documenting_go_code.html">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li> <li><a href="http://blog.golang.org/2011/06/profiling-go-programs.html">Profiling Go Programs</a></li> +<li><a href="/doc/articles/race_detector.html">Data Race Detector</a> - testing Go programs for race conditions.</li> </ul> <h2 id="talks">Talks</h2> @@ -139,27 +145,29 @@ before Go 1 and contain some examples that are no longer correct, but they are still of value. </p> -<h3 id="writing_web_apps"><a href="http://www.youtube.com/watch?v=-i0hat7pdpk">Writing Web Apps in Go</a><font color="red">*</font></h3> +<h3 id="video_tour_of_go"><a href="http://research.swtch.com/gotour">A Video Tour of Go</a></h3> <p> -A talk by Rob Pike and Andrew Gerrand presented at Google I/O 2011. -It walks through the construction and deployment of a simple web application -and unveils the <a href="http://blog.golang.org/2011/05/go-and-google-app-engine.html">Go runtime for App Engine</a>. -See the <a href="/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf">presentation slides</a>. +Three things that make Go fast, fun, and productive: +interfaces, reflection, and concurrency. Builds a toy web crawler to +demonstrate these. </p> -<h3 id="real_world_go"><a href="http://www.youtube.com/watch?v=7QDVRowyUQA">Real World Go</a><font color="red">*</font></h3> +<h3 id="go_concurrency_patterns"><a href="http://www.youtube.com/watch?v=f6kdp27TYZs">Go Concurrency Patterns</a></h3> <p> -A talk by Andrew Gerrand presented at Google I/O Bootcamp 2011. -It gives a broad overview of Go's type system and concurrency model -and provides four examples of Go programs that solve real problems. -See the <a href="/doc/talks/io2011/Real_World_Go.pdf">presentation slides</a>. +Concurrency is the key to designing high performance network services. Go's concurrency primitives (goroutines and channels) provide a simple and efficient means of expressing concurrent execution. In this talk we see how tricky concurrency problems can be solved gracefully with simple Go code. </p> -<h3 id="integrated_apps"><a href="http://www.youtube.com/watch?v=Mo1YKpIF1PQ">Building Integrated Apps on Google's Cloud Platform</a></h3> +<h3 id="meet_the_go_team"><a href="http://www.youtube.com/watch?v=sln-gJaURzk">Meet the Go team</a></h3> <p> -A talk by Andrew Gerrand presented at Google Developer Day Japan 2011. -It discusses the development of a web application that runs on Google -App Engine and renders images that it stores on Google Cloud Storage. +A panel discussion with David Symonds, Robert Griesemer, Rob Pike, Ken Thompson, Andrew Gerrand, and Brad Fitzpatrick. +</p> + +<h3 id="writing_web_apps"><a href="http://www.youtube.com/watch?v=-i0hat7pdpk">Writing Web Apps in Go</a><font color="red">*</font></h3> +<p> +A talk by Rob Pike and Andrew Gerrand presented at Google I/O 2011. +It walks through the construction and deployment of a simple web application +and unveils the <a href="http://blog.golang.org/2011/05/go-and-google-app-engine.html">Go runtime for App Engine</a>. +See the <a href="http://talks.golang.org/2011/Writing_Web_Apps_in_Go.pdf">presentation slides</a>. </p> <h3 id="go_programming"><a href="http://www.youtube.com/watch?v=jgVhBThJdXc">Go Programming</a><font color="red">*</font></h3> @@ -170,14 +178,6 @@ examples demonstrating features particular to Go. These include concurrency, embedded types, methods on any type, and program construction using interfaces. </p> -<h3 id="practical_go_programming"><a href="http://www.youtube.com/watch?v=2-pPAvqyluI">Practical Go Programming</a><font color="red">*</font></h3> -<p> -This talk presents the development of a complete web application in Go. -It looks at design, storage, concurrency, and scaling issues in detail, using -the simple example of an URL shortening service. -See the <a href="http://wh3rd.net/practical-go/">presentation slides</a>. -</p> - <h4 id="talks_more">More</h4> <p> See the <a href="http://code.google.com/p/go-wiki/wiki/GoTalks">GoTalks @@ -201,7 +201,7 @@ documentation. <p>The <a href="http://groups.google.com/group/golang-nuts">golang-nuts</a> mailing list is for general Go discussion.</p> -<h3 id="projects"><a href="http://godashboard.appspot.com/project">Go Project Dashboard</a></h3> +<h3 id="projects"><a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Wiki Projects Page</a></h3> <p>A list of external Go projects including programs and libraries.</p> <h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3> diff --git a/doc/effective_go.html b/doc/effective_go.html index 6cacac630..e02694add 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -41,8 +41,14 @@ The <a href="/src/pkg/">Go package sources</a> are intended to serve not only as the core library but also as examples of how to use the language. +Moreover, many of the packages contain working, self-contained +executable examples you can run directly from the +<a href="http://golang.org">golang.org</a> web site, such as +<a href="http://golang.org/pkg/strings/#example_Map">this one</a> (click +on the word "Example" to open it up). If you have a question about how to approach a problem or how something -might be implemented, they can provide answers, ideas and +might be implemented, the documentation, code and examples in the +library can provide answers, ideas and background. </p> @@ -108,7 +114,7 @@ All Go code in the standard packages has been formatted with <code>gofmt</code>. <p> -Some formatting details remain. Very briefly, +Some formatting details remain. Very briefly: </p> <dl> @@ -123,14 +129,14 @@ Some formatting details remain. Very briefly, </dd> <dt>Parentheses</dt> <dd> - Go needs fewer parentheses: control structures (<code>if</code>, + Go needs fewer parentheses than C and Java: control structures (<code>if</code>, <code>for</code>, <code>switch</code>) do not have parentheses in their syntax. Also, the operator precedence hierarchy is shorter and clearer, so <pre> x<<8 + y<<16 </pre> - means what the spacing implies. + means what the spacing implies, unlike in the other languages. </dd> </dl> @@ -140,8 +146,8 @@ x<<8 + y<<16 Go provides C-style <code>/* */</code> block comments and C++-style <code>//</code> line comments. Line comments are the norm; -block comments appear mostly as package comments and -are also useful to disable large swaths of code. +block comments appear mostly as package comments, but +are useful within an expression or to disable large swaths of code. </p> <p> @@ -167,10 +173,9 @@ should set up the detailed documentation that follows. <pre> /* - Package regexp implements a simple library for - regular expressions. +Package regexp implements a simple library for regular expressions. - The syntax of the regular expressions accepted is: +The syntax of the regular expressions accepted is: regexp: concatenation { '|' concatenation } @@ -206,6 +211,13 @@ takes care of that. The comments are uninterpreted plain text, so HTML and other annotations such as <code>_this_</code> will reproduce <i>verbatim</i> and should not be used. +One adjustment <code>godoc</code> does do is to display indented +text in a fixed-width font, suitable for program snippets. +The package comment for the +<a href="http://golang.org/pkg/fmt/"><code>fmt</code> package</a> uses this to good effect. +</p> + +<p> Depending on the context, <code>godoc</code> might not even reformat comments, so make sure they look good straight up: use correct spelling, punctuation, and sentence structure, @@ -233,6 +245,33 @@ func Compile(str string) (regexp *Regexp, err error) { </pre> <p> +If the name always begins the comment, the output of <code>godoc</code> +can usefully be run through <code>grep</code>. +Imagine you couldn't remember the name "Compile" but were looking for +the parsing function for regular expressions, so you ran +the command, +</p> + +<pre> +$ godoc regexp | grep parse +</pre> + +<p> +If all the doc comments in the package began, "This function...", <code>grep</code> +wouldn't help you remember the name. But because the package starts each +doc comment with the name, you'd see something like this, +which recalls the word you're looking for. +</p> + +<pre> +$ godoc regexp | grep parse + Compile parses a regular expression and returns, if successful, a Regexp + parsed. It simplifies safe initialization of global variables holding + cannot be parsed. It simplifies safe initialization of global variables +$ +</pre> + +<p> Go's declaration syntax allows grouping of declarations. A single doc comment can introduce a group of related constants or variables. Since the whole declaration is presented, such a comment can often be perfunctory. @@ -266,7 +305,7 @@ var ( <p> Names are as important in Go as in any other language. -In some cases they even have semantic effect: for instance, +They even have semantic effect: the visibility of a name outside a package is determined by whether its first character is upper case. It's therefore worth spending a little time talking about naming conventions @@ -311,11 +350,11 @@ not <code>encoding_base64</code> and not <code>encodingBase64</code>. </p> <p> -The importer of a package will use the name to refer to its contents -(the <code>import .</code> notation is intended mostly for tests and other -unusual situations and should be avoided unless necessary), +The importer of a package will use the name to refer to its contents. so exported names in the package can use that fact to avoid stutter. +(Don't use the <code>import .</code> notation, which can simplify +tests that must run outside the package they are testing, but should otherwise be avoided.) For instance, the buffered reader type in the <code>bufio</code> package is called <code>Reader</code>, not <code>BufReader</code>, because users see it as <code>bufio.Reader</code>, which is a clear, concise name. @@ -336,9 +375,7 @@ Another short example is <code>once.Do</code>; <code>once.Do(setup)</code> reads well and would not be improved by writing <code>once.DoOrWaitUntilDone(setup)</code>. Long names don't automatically make things more readable. -If the name represents something intricate or subtle, it's usually better -to write a helpful doc comment than to attempt to put all the information -into the name. +A helpful doc comment can often be more valuable than an extra long name. </p> <h3 id="Getters">Getters</h3> @@ -395,8 +432,8 @@ multiword names. <h2 id="semicolons">Semicolons</h2> <p> -Like C, Go's formal grammar uses semicolons to terminate statements; -unlike C, those semicolons do not appear in the source. +Like C, Go's formal grammar uses semicolons to terminate statements, +but unlike in C, those semicolons do not appear in the source. Instead the lexer uses a simple rule to insert semicolons automatically as it scans, so the input text is mostly free of them. </p> @@ -432,7 +469,8 @@ statements on a line, should you write code that way. </p> <p> -One caveat. You should never put the opening brace of a +One consequence of the semicolon insertion rules +is that you cannot put the opening brace of a control structure (<code>if</code>, <code>for</code>, <code>switch</code>, or <code>select</code>) on the next line. If you do, a semicolon will be inserted before the brace, which could cause unwanted @@ -541,7 +579,7 @@ codeUsing(f, d) </pre> -<h3 id="redeclaration">Redeclaration</h3> +<h3 id="redeclaration">Redeclaration and reassignment</h3> <p> An aside: The last example in the previous section demonstrates a detail of how the @@ -578,7 +616,7 @@ if it has already been declared, provided: <ul> <li>this declaration is in the same scope as the existing declaration of <code>v</code> -(if <code>v</code> is already declared in an outer scope, the declaration will create a new variable),</li> +(if <code>v</code> is already declared in an outer scope, the declaration will create a new variable §),</li> <li>the corresponding value in the initialization is assignable to <code>v</code>, and</li> <li>there is at least one other variable in the declaration that is being declared anew.</li> </ul> @@ -590,6 +628,12 @@ in a long <code>if-else</code> chain. You'll see it used often. </p> +<p> +§ It's worth noting here that in Go the scope of function parameters and return values +is the same as the function body, even though they appear lexically outside the braces +that enclose the body. +</p> + <h3 id="for">For</h3> <p> @@ -635,7 +679,7 @@ If you only need the first item in the range (the key or index), drop the second </p> <pre> for key := range m { - if expired(key) { + if key.expired() { delete(m, key) } } @@ -653,29 +697,30 @@ for _, value := range array { <p> For strings, the <code>range</code> does more work for you, breaking out individual -Unicode characters by parsing the UTF-8. +Unicode code points by parsing the UTF-8. Erroneous encodings consume one byte and produce the replacement rune U+FFFD. The loop </p> <pre> -for pos, char := range "日本語" { - fmt.Printf("character %c starts at byte position %d\n", char, pos) +for pos, char := range "日本\x80語" { // \x80 is an illegal UTF-8 encoding + fmt.Printf("character %#U starts at byte position %d\n", char, pos) } </pre> <p> prints </p> <pre> -character 日 starts at byte position 0 -character 本 starts at byte position 3 -character 語 starts at byte position 6 +character U+65E5 '日' starts at byte position 0 +character U+672C '本' starts at byte position 3 +character U+FFFD '�' starts at byte position 6 +character U+8A9E '語' starts at byte position 7 </pre> <p> Finally, Go has no comma operator and <code>++</code> and <code>--</code> are statements not expressions. Thus if you want to run multiple variables in a <code>for</code> -you should use parallel assignment. +you should use parallel assignment (although that precludes <code>++</code> and <code>--</code>). </p> <pre> // Reverse a @@ -714,6 +759,7 @@ func unhex(c byte) byte { <p> There is no automatic fall through, but cases can be presented in comma-separated lists. +</p> <pre> func shouldEscape(c byte) bool { switch c { @@ -725,10 +771,11 @@ func shouldEscape(c byte) bool { </pre> <p> -Here's a comparison routine for byte arrays that uses two +Here's a comparison routine for byte slices that uses two <code>switch</code> statements: +</p> <pre> -// Compare returns an integer comparing the two byte arrays, +// Compare returns an integer comparing the two byte slices, // lexicographically. // The result will be 0 if a == b, -1 if a < b, and +1 if a > b func Compare(a, b []byte) int { @@ -756,19 +803,23 @@ variable. Such a <em>type switch</em> uses the syntax of a type assertion with the keyword <code>type</code> inside the parentheses. If the switch declares a variable in the expression, the variable will have the corresponding type in each clause. +It's also idiomatic to reuse the name in such cases, in effect declaring +a new variable with the same name but a different type in each case. </p> <pre> -switch t := interfaceValue.(type) { +var t interface{} +t = functionOfSomeType() +switch t := t.(type) { default: - fmt.Printf("unexpected type %T", t) // %T prints type + fmt.Printf("unexpected type %T", t) // %T prints whatever type t has case bool: - fmt.Printf("boolean %t\n", t) + fmt.Printf("boolean %t\n", t) // t has type bool case int: - fmt.Printf("integer %d\n", t) + fmt.Printf("integer %d\n", t) // t has type int case *bool: - fmt.Printf("pointer to boolean %t\n", *t) + fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool case *int: - fmt.Printf("pointer to integer %d\n", *t) + fmt.Printf("pointer to integer %d\n", *t) // t has type *int } </pre> @@ -808,7 +859,7 @@ This is a common style; see the section on error handling for more examples. A similar approach obviates the need to pass a pointer to a return value to simulate a reference parameter. Here's a simple-minded function to -grab a number from a position in a byte array, returning the number +grab a number from a position in a byte slice, returning the number and the next position. </p> @@ -825,12 +876,12 @@ func nextInt(b []byte, i int) (int, int) { </pre> <p> -You could use it to scan the numbers in an input array <code>a</code> like this: +You could use it to scan the numbers in an input slice <code>b</code> like this: </p> <pre> - for i := 0; i < len(a); { - x, i = nextInt(a, i) + for i := 0; i < len(b); { + x, i = nextInt(b, i) fmt.Println(x) } </pre> @@ -1180,6 +1231,7 @@ structure with length 10 and a capacity of 100 pointing at the first for more information.) In contrast, <code>new([]int)</code> returns a pointer to a newly allocated, zeroed slice structure, that is, a pointer to a <code>nil</code> slice value. +</p> <p> These examples illustrate the difference between <code>new</code> and @@ -1330,6 +1382,8 @@ func Append(slice, data[]byte) []byte { We must return the slice afterwards because, although <code>Append</code> can modify the elements of <code>slice</code>, the slice itself (the run-time data structure holding the pointer, length, and capacity) is passed by value. +</p> + <p> The idea of appending to a slice is so useful it's captured by the <code>append</code> built-in function. To understand that function's @@ -1369,8 +1423,8 @@ var timeZone = map[string] int { </pre> <p> Assigning and fetching map values looks syntactically just like -doing the same for arrays except that the index doesn't need to -be an integer. +doing the same for arrays and slices except that the index doesn't +need to be an integer. </p> <pre> offset := timeZone["EST"] @@ -1495,7 +1549,7 @@ prints If you just want the default conversion, such as decimal for integers, you can use the catchall format <code>%v</code> (for “value”); the result is exactly what <code>Print</code> and <code>Println</code> would produce. -Moreover, that format can print <em>any</em> value, even arrays, structs, and +Moreover, that format can print <em>any</em> value, even arrays, slices, structs, and maps. Here is a print statement for the time zone map defined in the previous section. </p> <pre> @@ -1539,12 +1593,13 @@ map[string] int{"CST":-21600, "PST":-28800, "EST":-18000, "UTC":0, "MST":-25200} That quoted string format is also available through <code>%q</code> when applied to a value of type <code>string</code> or <code>[]byte</code>; the alternate format <code>%#q</code> will use backquotes instead if possible. -Also, <code>%x</code> works on strings and arrays of bytes as well as on integers, -generating a long hexadecimal string, and with +Also, <code>%x</code> works on strings, byte arrays and byte slices as well as +on integers, generating a long hexadecimal string, and with a space in the format (<code>% x</code>) it puts spaces between the bytes. </p> <p> Another handy format is <code>%T</code>, which prints the <em>type</em> of a value. +</p> <pre> fmt.Printf("%T\n", timeZone) </pre> @@ -1606,6 +1661,7 @@ func Println(v ...interface{}) { We write <code>...</code> after <code>v</code> in the nested call to <code>Sprintln</code> to tell the compiler to treat <code>v</code> as a list of arguments; otherwise it would just pass <code>v</code> as a single slice argument. +</p> <p> There's even more to printing than we've covered here. See the <code>godoc</code> documentation for package <code>fmt</code> for the details. @@ -1738,9 +1794,9 @@ initializer can be a general expression computed at run time. </p> <pre> var ( - HOME = os.Getenv("HOME") - USER = os.Getenv("USER") - GOROOT = os.Getenv("GOROOT") + home = os.Getenv("HOME") + user = os.Getenv("USER") + goRoot = os.Getenv("GOROOT") ) </pre> @@ -1763,17 +1819,17 @@ correctness of the program state before real execution begins. <pre> func init() { - if USER == "" { + if user == "" { log.Fatal("$USER not set") } - if HOME == "" { - HOME = "/usr/" + USER + if home == "" { + home = "/home/" + user } - if GOROOT == "" { - GOROOT = HOME + "/go" + if goRoot == "" { + goRoot = home + "/go" } - // GOROOT may be overridden by --goroot flag on command line. - flag.StringVar(&GOROOT, "goroot", GOROOT, "Go root directory") + // goRoot may be overridden by --goroot flag on command line. + flag.StringVar(&goRoot, "goroot", goRoot, "Go root directory") } </pre> @@ -1783,6 +1839,7 @@ func init() { <p> Methods can be defined for any named type that is not a pointer or an interface; the receiver does not have to be a struct. +</p> <p> In the discussion of slices above, we wrote an <code>Append</code> function. We can define it as a method on slices instead. To do @@ -2012,6 +2069,7 @@ Those methods include the standard <code>Write</code> method, so an can be used. <code>Request</code> is a struct containing a parsed representation of the request from the client. +</p> <p> For brevity, let's ignore POSTs and assume HTTP requests are always GETs; that simplification does not affect the way the handlers are @@ -2034,6 +2092,7 @@ func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) { (Keeping with our theme, note how <code>Fprintf</code> can print to an <code>http.ResponseWriter</code>.) For reference, here's how to attach such a server to a node on the URL tree. +</p> <pre> import "net/http" ... @@ -2187,6 +2246,7 @@ what a <code>Reader</code> does <em>and</em> what a <code>Writer</code> does; it is a union of the embedded interfaces (which must be disjoint sets of methods). Only interfaces can be embedded within interfaces. +</p> <p> The same basic idea applies to structs, but with more far-reaching implications. The <code>bufio</code> package has two struct types, @@ -2378,10 +2438,11 @@ exits, silently. (The effect is similar to the Unix shell's background.) </p> <pre> -go list.Sort() // run list.Sort concurrently; don't wait for it. +go list.Sort() // run list.Sort concurrently; don't wait for it. </pre> <p> A function literal can be handy in a goroutine invocation. +</p> <pre> func Announce(message string, delay time.Duration) { go func() { @@ -2393,6 +2454,7 @@ func Announce(message string, delay time.Duration) { <p> In Go, function literals are closures: the implementation makes sure the variables referred to by the function survive as long as they are active. +</p> <p> These examples aren't too practical because the functions have no way of signaling completion. For that, we need channels. @@ -2425,7 +2487,7 @@ c := make(chan int) // Allocate a channel. // Start the sort in a goroutine; when it completes, signal on the channel. go func() { list.Sort() - c <- 1 // Send a signal; value does not matter. + c <- 1 // Send a signal; value does not matter. }() doSomethingForAWhile() <-c // Wait for sort to finish; discard sent value. @@ -2494,6 +2556,7 @@ One of the most important properties of Go is that a channel is a first-class value that can be allocated and passed around like any other. A common use of this property is to implement safe, parallel demultiplexing. +</p> <p> In the example in the previous section, <code>handle</code> was an idealized handler for a request but we didn't define the @@ -2822,7 +2885,7 @@ func init() { <p> When <code>panic</code> is called, including implicitly for run-time -errors such as indexing an array out of bounds or failing a type +errors such as indexing a slice out of bounds or failing a type assertion, it immediately stops execution of the current function and begins unwinding the stack of the goroutine, running any deferred functions along the way. If that unwinding reaches the top of the @@ -2923,7 +2986,7 @@ that it has the local type <code>Error</code>. If it does not, the type assertion will fail, causing a run-time error that continues the stack unwinding as though nothing had interrupted it. This check means that if something unexpected happens, such -as an array index out of bounds, the code will fail even though we +as an index out of bounds, the code will fail even though we are using <code>panic</code> and <code>recover</code> to handle user-triggered errors. </p> @@ -2952,6 +3015,155 @@ filter unexpected problems and re-panic with the original error. That's left as an exercise for the reader. </p> +<h2 id="blank">Blank identifier</h2> + +<p> +Go defines a special identifier <code>_</code>, called the <i>blank identifier</i>. +The blank identifier can be used in a declaration to avoid +declaring a name, and it can be used in an assignment to discard a value. +This definition makes it useful in a variety of contexts. +</p> + +<h3 id="blank_assign">Multiple assignment</h3> + +<p> +If an assignment requires multiple values on the left side, +but one of the values will not be used by the program, +using the blank identifier in the assignment avoids the need +to create a dummy variable. +We saw one example of this in the discussion of +<a href="#for">for loops</a> above. +</p> +<pre> +sum := 0 +for _, value := range array { + sum += value +} +</pre> + +<p> +Another common use is when calling a function that returns +a value and an error, but only the error is important. +</p> +<pre> +if _, err := os.Stat(path); os.IsNotExist(err) { + fmt.Printf("%s does not exist\n", path) +} +</pre> + +<p> +A final use that is more common than it should be is to +discard the error from a function that is not expected to fail. +This is usually a mistake: when the function does fail, the code +will continue on and probably panic dereferencing a nil pointer. +</p> +<pre> +// Always check errors: this program crashes if path does not exist. +fi, _ := os.Stat(path) +fmt.Printf("%s is %d bytes\n", path, fi.Size()) +</pre> + +<h3 id="blank_unused">Unused imports and variables</h3> + +<p> +Go defines that it is an error to import a package without using it, +or to declare a variable without using its value. +Unused imports bloat a program and lengthen compiles unnecessarily; +a variable that is initialized but not used is at least +a wasted computation and perhaps indicative of a +larger bug. +Of course, both of these situations also arise in programs +that are under active development, as you test and refine +your code. +</p> +<p> +For example, in this program, there are two unused imports +(<code>fmt</code> and <code>io</code>) +and an unused variable (<code>greeting</code>). +</p> +{{code "/doc/progs/unused1.go" `/package/` `$`}} +<p> +Top-level blank declarations referring to the packages +will silence the unused import errors. +By convention, these declarations should come immediately after +the imports, as a reminder to clean things up later. +Similarly, assigning <code>greeting</code> to a blank identifier +will silence the unused variable error. +</p> +{{code "/doc/progs/unused2.go" `/package/` `$`}} + +<h3 id="blank_import">Import for side effect</h3> + +<p> +An unused import like <code>fmt</code> or <code>io</code> in the last section +should eventually be used or removed: +blank assignments identify code as a work in progress. +But sometimes it is useful to import a package only for its +side effects, without any explicit use. +For example, during its <code>init</code> function, +the <code><a href="/pkg/net/http/pprof/">net/http/pprof</a></code> +package registers HTTP handlers that provide useful +debugging information. It has an exported API too, but +most clients need only the handler registration. +In this situation, it is conventional to rename the package +to the blank identifier: +</p> +<pre> +import _ "net/http/pprof" +</pre> +<p> +This form of import makes clear that the package is being +imported for its side effects, because there is no other possible +use of the package: in this file, it doesn't have a name. +</p> + +<h3 id="blank_implements">Interface checks</h3> + +<p> +As we saw in the discussion of <a href="#interfaces_and_types">interfaces</a> above, +Go does not require a type to declare explicitly that it implements an interface. +It implements the interface by simply implementing the required methods. +This makes Go programs more lightweight and flexible, and it can avoid +unnecessary dependencies between packages. +Most interface conversions are static, visible to the compiler, +and therefore checked at compile time. +For example, passing an <code>*os.File</code> to a function +expecting an <code>io.Reader</code> will not compile unless +<code>*os.File</code> implements the <code>io.Reader</code> interface. +</p> +<p> +However, some types that are used only to satisfy dynamic interface checks. +For example, the <code><a href="/pkg/encoding/json/">encoding/json</a></code> +package defines a <code><a href="/pkg/encoding/json/#Marshaler">Marshaler</a></code> +interface. If the JSON encoder encounters a type implementing that interface, +the encoder will let the type convert itself to JSON instead of using the standard +conversion. +This check is done only at runtime, with code like: +</p> +<pre> +m, ok := val.(json.Marshaler) +</pre> +<p> +If a type—for example, +<code><a href="/pkg/encoding/json/#RawMessage">json.RawMessage</a></code>—intends +to customize its JSON representation, it should implement +<code>json.Marshaler</code>, but there are no static conversions that would +cause the compiler to verify this automatically. +A declaration can be used to add such a check: +</p> +<pre> +var _ json.Marshaler = (*RawMessage)(nil) +</pre> +<p> +As part of type-checking this static assignment of a +<code>*RawMessage</code> to a <code>Marshaler</code>, +the Go compiler will require that <code>*RawMessage</code> implements <code>Marshaler</code>. +Using the blank identifier here indicates that +the declaration exists only for the type checking, +not to create a variable. +Conventionally, such declarations are used only when there are +no static conversions already present in the code. +</p> <h2 id="web_server">A web server</h2> @@ -2973,7 +3185,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> -{{code "/doc/progs/eff_qr.go"}} +{{code "/doc/progs/eff_qr.go" `/package/` `$`}} <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 @@ -2992,11 +3204,11 @@ server; it blocks while the server runs. executes the template on the data in the form value named <code>s</code>. </p> <p> -The template package is powerful; +The template package <code>html/template</code> is powerful; this program just touches on its capabilities. -In essence, it rewrites a piece of text on the fly by substituting elements derived +In essence, it rewrites a piece of HTML text on the fly by substituting elements derived from data items passed to <code>templ.Execute</code>, in this case the -form value. +form value. Within the template text (<code>templateStr</code>), double-brace-delimited pieces denote template actions. The piece from <code>{{html "{{if .}}"}}</code> @@ -3005,13 +3217,14 @@ is non-empty. That is, when the string is empty, this piece of the template is suppressed. </p> <p> -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. +The two snippets <code>{{html "{{.}}"}}</code> say to show the data presented to +the template—the query string—on the web page. +The HTML template package automatically provides appropriate escaping so the +text is safe to display. </p> <p> The rest of the template string is just the HTML to show when the page loads. -If this is too quick an explanation, see the <a href="/pkg/text/template/">documentation</a> +If this is too quick an explanation, see the <a href="/pkg/html/template/">documentation</a> for the template package for a more thorough discussion. </p> <p> @@ -3025,7 +3238,7 @@ TODO <pre> verifying implementation type Color uint32 - + // Check that Color implements image.Color and image.Image var _ image.Color = Black var _ image.Image = Black diff --git a/doc/gccgo_contribute.html b/doc/gccgo_contribute.html index 8ca13e4ef..4d268e02c 100644 --- a/doc/gccgo_contribute.html +++ b/doc/gccgo_contribute.html @@ -100,7 +100,9 @@ or <code>gcc/testsuite/go.dg</code> directories in the GCC repository. <p> Changes to the Go frontend should follow the same process as for the -main Go repository, only for the <code>gofrontend</code> project -rather than the <code>go</code> project. Those changes will then be -merged into the GCC sources. +main Go repository, only for the <code>gofrontend</code> project and +the<code>gofrontend-dev@googlegroups.com</code> mailing list +rather than the <code>go</code> project and the +<code>golang-dev@googlegroups.com</code> mailing list. Those changes +will then be merged into the GCC sources. </p> diff --git a/doc/go1.1.html b/doc/go1.1.html new file mode 100644 index 000000000..ae0a09939 --- /dev/null +++ b/doc/go1.1.html @@ -0,0 +1,207 @@ +<!--{ + "Title": "Go 1.1 Release Notes", + "Path": "/doc/go1.1", + "Template": true +}--> + +<h2 id="introduction">Introduction to Go 1.1</h2> + +TODO + - overview + - link back to Go 1 and also Go 1 Compatibility docs. + +<h2 id="language">Changes to the language</h2> + +TODO + +<h3 id="divzero">Integer division by zero</h3> + +<p> +In Go 1, integer division by a constant zero produced a runtime panic: +</p> + +<pre> +func f(x int) int { + return x/0 +} +</pre> + +<p> +In Go 1.1, an integer division by constant zero is not a legal program, so it is a compile-time error. +</p> + + +<h2 id="impl">Changes to the implementations and tools</h2> + +TODO: more + +<h3 id="gc-flag">Command-line flag parsing</h3> + +<p> +In the gc toolchain, the compilers and linkers now use the +same command-line flag parsing rules as the Go flag package, a departure +from the traditional Unix flag parsing. This may affect scripts that invoke +the tool directly. +For example, +<code>go tool 6c -Fw -Dfoo</code> must now be written +<code>go tool 6c -F -w -D foo</code>. +</p> + +<h3 id="int">Size of int on 64-bit platforms</h3> + +<p> +The language allows the implementation to choose whether the <code>int</code> type and <code>uint</code> types are 32 or 64 bits. Previous Go implementations made <code>int</code> and <code>uint</code> 32 bits on all systems. Both the gc and gccgo implementations (TODO: check that gccgo does) <a href="http://golang.org/issue/2188">now make <code>int</code> and <code>uint</code> 64 bits on 64-bit platforms such as AMD64/x86-64</a>. +Among other things, this enables the allocation of slices with +more than 2 billion elements on 64-bit platforms. +</p> + +<p> +<em>Updating</em>: +Most programs will be unaffected by this change. +Because Go does not allow implicit conversions between distinct +<a href="/ref/spec#Numeric_types">numeric types</a>, +no programs will stop compiling due to this change. +However, programs that contain implicit assumptions +that <code>int</code> is only 32 bits may change behavior. +For example, this code prints a positive number on 64-bit systems and +a negative one on 32-bit systems: + +<pre> +x := ^uint32(0) // x is 0xffffffff +i := int(x) // i is -1 on 32-bit systems, 0xffffffff on 64-bit +fmt.Println(i) +</pre> + +<p>Portable code intending 32-bit sign extension (yielding -1 on all systems) +would instead say: +</p> + +<pre> +i := int(int32(x)) +</pre> + +<h3 id="asm">Assembler</h3> + +<p> +Due to the <a href="#int">int</a> and TODO: OTHER changes, +the placement of function arguments on the stack has changed. +Functions written in assembly will need to be revised at least +to adjust frame pointer offsets. +</p> + +<h3 id="gotool">Changes to the go tool</h3> + +<p>The <code>go</code> tool has acquired several improvements which are intended to improve the experience for new Go users.</p> + +<p>Firstly, when compiling, testing, or running Go code, the <code>go</code> tool will now give more detailed errors messages, including a list of paths searched, when a package cannot be located. +</p> + +<pre> +$ go build foo/quxx +can't load package: package foo/quxx: cannot find package "foo/quxx" in any of: + /home/User/go/src/pkg/foo/quxx (from $GOROOT) + /home/User/src/foo/quxx (from $GOPATH) +</pre> + +<p> +Secondly, the <code>go get</code> command no longer allows <code>$GOROOT</code> as the default destination when downloading package source. To use <code>go get</code> command, a valid <code>$GOPATH</code> is now required. +</p> + +<pre> +$ GOPATH= go get code.google.com/p/foo/quxx +package code.google.com/p/foo/quxx: cannot download, $GOPATH not set. For more details see: go help gopath +</pre> + +<p>Finally, as a result of the previous change, the <code>go get</code> command will also fail when <code>$GOPATH</code> and <code>$GOROOT</code> are set to the same value. +</p> + +<pre> +$ GOPATH=$GOROOT go get code.google.com/p/foo/quxx +warning: GOPATH set to GOROOT (/home/User/go) has no effect +package code.google.com/p/foo/quxx: cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath +</pre> + +<h3 id="gofix">Changes to go fix</h3> + +<p> +The <code>go fix</code> command no longer applies fixes to update code from +before Go 1 to use Go 1 APIs. To update pre-Go 1 code to Go 1.1, use a Go 1.0 toolchain +to convert the code to Go 1.0 first. +</p> + +<h2 id="library">Changes to the standard library</h2> + +<h3 id="debug_elf">debug/elf</h3> +<p> +Previous versions of the debug/elf package intentionally skipped over the first +symbol in the ELF symbol table, since it is always an empty symbol. This symbol +is no longer skipped since indexes into the symbol table returned by debug/elf, +will be different to indexes into the original ELF symbol table. Any code that +calls the debug/elf functions Symbols or ImportedSymbols may need to be +adjusted to account for the additional symbol and the change in symbol offsets. +</p> + +<h3 id="html_template">html/template</h3> + +<p> +Templates using the undocumented and only partially implemented +"noescape" feature will break: that feature was removed. +</p> + +<h3 id="net">net</h3> + +<p> +The protocol-specific resolvers were formerly +lax about the network name passed in. For example, although the documentation was clear +that the only valid networks for <code>ResolveTCPAddr</code> are <code>"tcp"</code>, +<code>"tcp4"</code>, and <code>"tcp6"</code>, the Go 1.0 implementation silently accepted +any string. The Go 1.1 implementation returns an error if the network is not one of those strings. +The same is true of the other protocol-specific resolvers <code>ResolveIPAddr</code>, <code>ResolveUDPAddr</code>, and +<code>ResolveUnixAddr</code>. +</p> + +<p> +The previous <code>ListenUnixgram</code> returned <code>UDPConn</code> as +arepresentation of the connection endpoint. The Go 1.1 implementation +returns <code>UnixConn</code> to allow reading and writing +with <code>ReadFrom</code> and <code>WriteTo</code> methods on +the <code>UnixConn</code>. +</p> + +<h3 id="time">time</h3> +<p> +On FreeBSD, Linux, NetBSD, OS X and OpenBSD, previous versions of the time package +returned times with microsecond precision. The Go 1.1 implementation of time on these +systems now returns times with nanosecond precision. Code may exist that expects to be +able to store such a time in an external format with only microsecond precision, +read it back, and recover exactly the same time instant. +In Go 1.1 the same time will not be recovered, since the external storage +will have discarded nanoseconds. +To address this case, there are two new methods of time.Time, Round and Truncate, +that can be used to remove precision from a time before passing it to +external storage. +</p> + +<h3 id="exp_old">Exp and old subtrees moved to go.exp subrepo</h3> + +<p> +To make it easier for binary distributions to access them if desired, the <code>exp</code> +and <code>old</code> source subtrees, which are not included in binary distributions, +have been moved to the new <code>go.exp</code> subrepository at +<code>code.google.com/p/go.exp</code>. To access the <code>ssa</code> package, +for example, run +</p> + +<pre> +$ go get code.google.com/p/go.exp/ssa +</pre> + +<p> +and then in Go source, +</p> + +<pre> +import "code.google.com/p/go.exp/ssa" +</pre> + +<h3 id="TODO">TODO</h3> diff --git a/doc/go1.html b/doc/go1.html index e1afe479a..491fd7bf7 100644 --- a/doc/go1.html +++ b/doc/go1.html @@ -618,8 +618,6 @@ The packages in their new locations are: <ul> <li><code>old/netchan</code></li> -<li><code>old/regexp</code></li> -<li><code>old/template</code></li> </ul> <p> @@ -639,6 +637,8 @@ Go 1 deletes several packages outright: <li><code>container/vector</code></li> <li><code>exp/datafmt</code></li> <li><code>go/typechecker</code></li> +<li><code>old/regexp</code></li> +<li><code>old/template</code></li> <li><code>try</code></li> </ul> @@ -1676,7 +1676,7 @@ instead of a <code>Visitor</code> interface value. The <code>WalkFunc</code> function will be called even for files or directories that could not be opened; in such cases the error argument will describe the failure. 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/#pkg-variables"><code>filepath.SkipDir</code></a> </p> {{code "/doc/progs/go1.go" `/STARTWALK/` `/ENDWALK/`}} @@ -1865,7 +1865,7 @@ made easier with the new structure of the packages. The imports will be updated by fix tool. Single-template uses will be otherwise be largely unaffected. Code that uses multiple templates in concert will need to be updated by hand. -The <a href="/pkg/text/template/#examples">examples</a> in +The <a href="/pkg/text/template/#pkg-examples">examples</a> in the documentation for <code>text/template</code> can provide guidance. </p> diff --git a/doc/go_faq.html b/doc/go_faq.html index b5b7cc656..5c68aa7e5 100644 --- a/doc/go_faq.html +++ b/doc/go_faq.html @@ -1,5 +1,6 @@ <!--{ - "Title": "FAQ" + "Title": "FAQ", + "Path": "/doc/faq" }--> <h2 id="Origins">Origins</h2> @@ -54,6 +55,38 @@ By its design, Go proposes an approach for the construction of system software on multicore machines. </ul> +<h3 id="What_is_the_status_of_the_project"> +What is the status of the project?</h3> + +<p> +Go became a public open source project on November 10, 2009. +After a couple of years of very active design and development, stability was called for and +Go 1 was <a href="http://blog.golang.org/2012/03/go-version-1-is-released.html">released</a> +on March 28, 2012. +Go 1, which includes a <a href="/ref/spec">language specification</a>, +<a href="/pkg/">standard libraries</a>, +and <a href="/cmd/go/">custom tools</a>, +provides a stable foundation for creating reliable products, projects, and publications. +</p> + +<p> +With that stability established, we are using Go to develop programs, products, and tools rather than +actively changing the language and libraries. +In fact, the purpose of Go 1 is to provide <a href="/doc/go1compat.html">long-term stability</a>. +Backwards-incompatible changes will not be made to any Go 1 point release. +We want to use what we have to learn how a future version of Go might look, rather than to play with +the language underfoot. +</p> + +<p> +Of course, development will continue on Go itself, but the focus will be on performance, reliability, +portability and the addition of new functionality such as improved support for internationalization. +</p> + +<p> +There may well be a Go 2 one day, but not for a few years and it will be influenced by what we learn using Go 1 as it is today. +</p> + <h3 id="What_is_the_origin_of_the_name"> What is the origin of the name?</h3> @@ -175,12 +208,12 @@ easier to understand what happens when things combine. <h3 id="Is_Google_using_go_internally"> Is Google using Go internally?</h3> <p> -Yes. There are now several Go programs deployed in +Yes. There are now several Go programs deployed in production inside Google. A public example is the server behind <a href="http://golang.org">http://golang.org</a>. It's just the <a href="/cmd/godoc"><code>godoc</code></a> document server running in a production configuration on -<a href="http://code.google.com/appengine/">Google App Engine</a>. +<a href="https://developers.google.com/appengine/">Google App Engine</a>. </p> <h3 id="Do_Go_programs_link_with_Cpp_programs"> @@ -191,14 +224,14 @@ There are two Go compiler implementations, <code>gc</code> (the <code>6g</code> program and friends) and <code>gccgo</code>. <code>Gc</code> uses a different calling convention and linker and can therefore only be linked with C programs using the same convention. -There is such a C compiler but no C++ compiler. -<code>Gccgo</code> is a GCC front-end that can, with care, be linked with -GCC-compiled C or C++ programs. +There is such a C compiler but no C++ compiler. +<code>Gccgo</code> is a GCC front-end that can, with care, be linked with +GCC-compiled C or C++ programs. </p> <p> -The <a href="/cmd/cgo/">cgo</a> program provides the mechanism for a -“foreign function interface” to allow safe calling of +The <a href="/cmd/cgo/">cgo</a> program provides the mechanism for a +“foreign function interface” to allow safe calling of C libraries from Go code. SWIG extends this capability to C++ libraries. </p> @@ -509,7 +542,7 @@ Why doesn't Go have "implements" declarations?</h3> <p> A Go type satisfies an interface by implementing the methods of that interface, nothing more. This property allows interfaces to be defined and used without -having to modify existing code. It enables a kind of "duck typing" that +having to modify existing code. It enables a kind of structural typing that promotes separation of concerns and improves code re-use, and makes it easier to build on patterns that emerge as the code develops. The semantics of interfaces is one of the main reasons for Go's nimble, @@ -564,7 +597,7 @@ func (b Bar) Foo() {} </pre> <p> -Most code doesn't make use of such constraints, since they limit the utility of +Most code doesn't make use of such constraints, since they limit the utility of the interface idea. Sometimes, though, they're necessary to resolve ambiguities among similar interfaces. </p> @@ -890,6 +923,32 @@ See the document for more information about how to proceed. </p> +<h3 id="Why_does_the_project_use_Mercurial_and_not_git"> +Why does the project use Mercurial and not git?</h3> + +<p> +The Go project, hosted by Google Code at +<a href="http://code.google.com/p/go">code.google.com/p/go</a>, +uses Mercurial as its version control system. +When the project launched, +Google Code supported only Subversion and Mercurial. +Mercurial was a better choice because of its plugin mechanism +that allowed us to create the "codereview" plugin to connect +the project to the excellent code review tools at +<a href="http://codereview.appspot.com">codereview.appspot.com</a>. +</p> + +<p> +Programmers who work +with the Go project's source rather than release downloads sometimes +ask for the project to switch to git. +That would be possible, but it would be a lot of work and +would also require reimplementing the codereview plugin. +Given that Mercurial works today, with code review support, +combined with the Go project's mostly linear, non-branching use of +version control, a switch to git doesn't seem worthwhile. +</p> + <h2 id="Pointers">Pointers and Allocation</h2> <h3 id="pass_by_value"> @@ -912,7 +971,7 @@ slice value doesn't copy the data it points to. Copying an interface value makes a copy of the thing stored in the interface value. If the interface value holds a struct, copying the interface value makes a copy of the struct. If the interface value holds a pointer, copying the interface value -makes a copy of the pointer, but again not the data it points to. +makes a copy of the pointer, but again not the data it points to. </p> <h3 id="methods_on_values_or_pointers"> @@ -994,9 +1053,11 @@ Why is <code>int</code> 32 bits on 64 bit machines?</h3> <p> The sizes of <code>int</code> and <code>uint</code> are implementation-specific but the same as each other on a given platform. -The 64 bit Go compilers (both gc and gccgo) use a 32 bit representation for -<code>int</code>. Code that relies on a particular +For portability, code that relies on a particular size of value should use an explicitly sized type, like <code>int64</code>. +Prior to Go 1.1, the 64-bit Go compilers (both gc and gccgo) used +a 32-bit representation for <code>int</code>. As of Go 1.1 they use +a 64-bit representation. On the other hand, floating-point scalars and complex numbers are always sized: <code>float32</code>, <code>complex64</code>, etc., because programmers should be aware of precision when using @@ -1038,6 +1099,22 @@ analysis</em> recognizes some cases when such variables will not live past the return from the function and can reside on the stack. </p> +<h3 id="Why_does_my_Go_process_use_so_much_virtual_memory"> +Why does my Go process use so much virtual memory?</h3> + +<p> +The Go memory allocator reserves a large region of virtual memory as an arena +for allocations. This virtual memory is local to the specific Go process; the +reservation does not deprive other processes of memory. +</p> + +<p> +To find the amount of actual memory allocated to a Go process, use the Unix +<code>top</code> command and consult the <code>RES</code> (Linux) or +<code>RSIZE</code> (Mac OS X) columns. +<!-- TODO(adg): find out how this works on Windows --> +</p> + <h2 id="Concurrency">Concurrency</h2> <h3 id="What_operations_are_atomic_What_about_mutexes"> @@ -1071,7 +1148,7 @@ Why doesn't my multi-goroutine program use multiple CPUs?</h3> You must set the <code>GOMAXPROCS</code> shell environment variable or use the similarly-named <a href="/pkg/runtime/#GOMAXPROCS"><code>function</code></a> of the runtime package to allow the -run-time support to utilize more than one OS thread. +run-time support to utilize more than one OS thread. </p> <p> @@ -1084,7 +1161,7 @@ Why does using <code>GOMAXPROCS</code> > 1 sometimes make my program slower?</h3> <p> -It depends on the nature of your program. +It depends on the nature of your program. Problems that are intrinsically sequential cannot be sped up by adding more goroutines. Concurrency only becomes parallelism when the problem is @@ -1173,23 +1250,26 @@ func main() { // wait for all goroutines to complete before exiting for _ = range values { - <-done + <-done } } </pre> <p> -One might mistakenly expect to see <code>a, b, c</code> as the output. -What you'll probably see instead is <code>c, c, c</code>. This is because +One might mistakenly expect to see <code>a, b, c</code> as the output. +What you'll probably see instead is <code>c, c, c</code>. This is because each iteration of the loop uses the same instance of the variable <code>v</code>, so -each closure shares that single variable. When the closure runs, it prints the +each closure shares that single variable. When the closure runs, it prints the value of <code>v</code> at the time <code>fmt.Println</code> is executed, -but <code>v</code> may have been modified since the goroutine was launched. +but <code>v</code> may have been modified since the goroutine was launched. +To help detect this and other problems before they happen, run +<a href="http://golang.org/cmd/go/#hdr-Run_go_tool_vet_on_packages"><code>go vet</code></a>. </p> <p> -To bind the value of <code>v</code> to each closure as they are launched, one -could modify the inner loop to read: +To bind the current value of <code>v</code> to each closure as it is launched, one +must modify the inner loop to create a new variable each iteration. +One way is to pass the variable as an argument to the closure: </p> <pre> @@ -1202,11 +1282,26 @@ could modify the inner loop to read: </pre> <p> -In this example, the value of <code>v</code> is passed as an argument to the +In this example, the value of <code>v</code> is passed as an argument to the anonymous function. That value is then accessible inside the function as the variable <code>u</code>. </p> +<p> +Even easier is just to create a new variable, using a declaration style that may +seem odd but works fine in Go: +</p> + +<pre> + for _, v := range values { + <b>v := v</b> // create a new 'v'. + go func() { + fmt.Println(<b>v</b>) + done <- true + }() + } +</pre> + <h2 id="Control_flow">Control flow</h2> <h3 id="Does_Go_have_a_ternary_form"> @@ -1264,7 +1359,7 @@ builds a test binary, and runs it. <p>See the <a href="/doc/code.html">How to Write Go Code</a> document, the <a href="/pkg/testing/"><code>testing</code></a> package -and the <a href="/cmd/go/#Test_packages"><code>go test</code></a> subcommand for more details. +and the <a href="/cmd/go/#hdr-Test_packages"><code>go test</code></a> subcommand for more details. </p> <h3 id="testing_framework"> @@ -1383,7 +1478,7 @@ For these reasons, Go allows neither. <p> When developing code, it's common to create these situations temporarily and it can be annoying to have to edit them out before the -program will compile. +program will compile. </p> <p> @@ -1430,13 +1525,13 @@ Why does Go perform badly on benchmark X?</h3> <p> One of Go's design goals is to approach the performance of C for comparable -programs, yet on some benchmarks it does quite poorly, including several -in <a href="/test/bench/shootout/">test/bench/shootout</a>. The slowest depend on libraries -for which versions of comparable performance are not available in Go. +programs, yet on some benchmarks it does quite poorly, including several +in <a href="/test/bench/shootout/">test/bench/shootout</a>. The slowest depend on libraries +for which versions of comparable performance are not available in Go. For instance, <a href="/test/bench/shootout/pidigits.go">pidigits.go</a> depends on a multi-precision math package, and the C versions, unlike Go's, use <a href="http://gmplib.org/">GMP</a> (which is -written in optimized assembler). +written in optimized assembler). Benchmarks that depend on regular expressions (<a href="/test/bench/shootout/regex-dna.go">regex-dna.go</a>, for instance) are essentially comparing Go's native <a href="/pkg/regexp">regexp package</a> to @@ -1455,7 +1550,7 @@ indicate. <p> Still, there is room for improvement. The compilers are good but could be better, many libraries need major performance work, and the garbage collector -isn't fast enough yet. (Even if it were, taking care not to generate unnecessary +isn't fast enough yet. (Even if it were, taking care not to generate unnecessary garbage can have a huge effect.) </p> diff --git a/doc/go_mem.html b/doc/go_mem.html index ece230638..0b73e43c4 100644 --- a/doc/go_mem.html +++ b/doc/go_mem.html @@ -270,8 +270,8 @@ before the <code>print</code>. <p> If the channel were buffered (e.g., <code>c = make(chan int, 1)</code>) then the program would not be guaranteed to print -<code>"hello, world"</code>. (It might print the empty string; -it cannot print <code>"goodbye, universe"</code>, nor can it crash.) +<code>"hello, world"</code>. (It might print the empty string, +crash, or do something else.) </p> <h3>Locks</h3> diff --git a/doc/go_spec.html b/doc/go_spec.html index 90acc1704..0cb9f54b1 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ <!--{ "Title": "The Go Programming Language Specification", - "Subtitle": "Version of June 4, 2012", + "Subtitle": "Version of March 1, 2013", "Path": "/ref/spec" }--> @@ -15,7 +15,6 @@ TODO [ ] need explicit language about the result type of operations [ ] should probably write something about evaluation order of statements even though obvious -[ ] review language on implicit dereferencing --> @@ -89,7 +88,8 @@ Source code is Unicode text encoded in canonicalized, so a single accented code point is distinct from the same character constructed from combining an accent and a letter; those are treated as two code points. For simplicity, this document -will use the term <i>character</i> to refer to a Unicode code point. +will use the unqualified term <i>character</i> to refer to a Unicode code point +in the source text. </p> <p> Each code point is distinct; for instance, upper and lower case letters @@ -99,6 +99,11 @@ are different characters. Implementation restriction: For compatibility with other tools, a compiler may disallow the NUL character (U+0000) in the source text. </p> +<p> +Implementation restriction: For compatibility with other tools, a +compiler may ignore a UTF-8-encoded byte order mark +(U+FEFF) if it is the first Unicode code point in the source text. +</p> <h3 id="Characters">Characters</h3> @@ -113,7 +118,7 @@ unicode_digit = /* a Unicode code point classified as "Decimal Digit" */ . </pre> <p> -In <a href="http://www.unicode.org/versions/Unicode6.0.0/">The Unicode Standard 6.0</a>, +In <a href="http://www.unicode.org/versions/Unicode6.2.0/">The Unicode Standard 6.2</a>, Section 4.5 "General Category" defines a set of character categories. Go treats those characters in category Lu, Ll, Lt, Lm, or Lo as Unicode letters, @@ -198,7 +203,7 @@ token is <a href="#Integer_literals">integer</a>, <a href="#Floating-point_literals">floating-point</a>, <a href="#Imaginary_literals">imaginary</a>, - <a href="#Character_literals">character</a>, or + <a href="#Rune_literals">rune</a>, or <a href="#String_literals">string</a> literal </li> @@ -360,13 +365,15 @@ imaginary_lit = (decimals | float_lit) "i" . </pre> -<h3 id="Character_literals">Character literals</h3> +<h3 id="Rune_literals">Rune literals</h3> <p> -A character literal represents a <a href="#Constants">character constant</a>, -typically a Unicode code point, as one or more characters enclosed in single -quotes. Within the quotes, any character may appear except single -quote and newline. A single quoted character represents itself, +A rune literal represents a <a href="#Constants">rune constant</a>, +an integer value identifying a Unicode code point. +A rune literal is expressed as one or more characters enclosed in single quotes. +Within the quotes, any character may appear except single +quote and newline. A single quoted character represents the Unicode value +of the character itself, while multi-character sequences beginning with a backslash encode values in various formats. </p> @@ -380,8 +387,8 @@ a literal <code>a</code>, Unicode U+0061, value <code>0x61</code>, while a literal <code>a</code>-dieresis, U+00E4, value <code>0xe4</code>. </p> <p> -Several backslash escapes allow arbitrary values to be represented -as ASCII text. There are four ways to represent the integer value +Several backslash escapes allow arbitrary values to be encoded as +ASCII text. There are four ways to represent the integer value as a numeric constant: <code>\x</code> followed by exactly two hexadecimal digits; <code>\u</code> followed by exactly four hexadecimal digits; <code>\U</code> followed by exactly eight hexadecimal digits, and a @@ -409,14 +416,14 @@ After a backslash, certain single-character escapes represent special values: \t U+0009 horizontal tab \v U+000b vertical tab \\ U+005c backslash -\' U+0027 single quote (valid escape only within character literals) +\' U+0027 single quote (valid escape only within rune literals) \" U+0022 double quote (valid escape only within string literals) </pre> <p> -All other sequences starting with a backslash are illegal inside character literals. +All other sequences starting with a backslash are illegal inside rune literals. </p> <pre class="ebnf"> -char_lit = "'" ( unicode_value | byte_value ) "'" . +rune_lit = "'" ( unicode_value | byte_value ) "'" . unicode_value = unicode_char | little_u_value | big_u_value | escaped_char . byte_value = octal_byte_value | hex_byte_value . octal_byte_value = `\` octal_digit octal_digit octal_digit . @@ -439,6 +446,11 @@ escaped_char = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | ` '\xff' '\u12e4' '\U00101234' +'aa' // illegal: too many characters +'\xa' // illegal: too few hexadecimal digits +'\0' // illegal: too few octal digits +'\uDFFF' // illegal: surrogate half +'\U00110000' // illegal: invalid Unicode code point </pre> @@ -453,7 +465,8 @@ raw string literals and interpreted string literals. Raw string literals are character sequences between back quotes <code>``</code>. Within the quotes, any character is legal except back quote. The value of a raw string literal is the -string composed of the uninterpreted characters between the quotes; +string composed of the uninterpreted (implicitly UTF-8-encoded) characters +between the quotes; in particular, backslashes have no special meaning and the string may contain newlines. Carriage returns inside raw string literals @@ -464,8 +477,9 @@ Interpreted string literals are character sequences between double quotes <code>""</code>. The text between the quotes, which may not contain newlines, forms the value of the literal, with backslash escapes interpreted as they -are in character literals (except that <code>\'</code> is illegal and -<code>\"</code> is legal). The three-digit octal (<code>\</code><i>nnn</i>) +are in rune literals (except that <code>\'</code> is illegal and +<code>\"</code> is legal), with the same restrictions. +The three-digit octal (<code>\</code><i>nnn</i>) and two-digit hexadecimal (<code>\x</code><i>nn</i>) escapes represent individual <i>bytes</i> of the resulting string; all other escapes represent the (possibly multi-byte) UTF-8 encoding of individual <i>characters</i>. @@ -492,6 +506,8 @@ interpreted_string_lit = `"` { unicode_value | byte_value } `"` . "日本語" "\u65e5本\U00008a9e" "\xff\u00FF" +"\uD800" // illegal: surrogate half +"\U00110000" // illegal: invalid Unicode code point </pre> <p> @@ -501,15 +517,15 @@ These examples all represent the same string: <pre> "日本語" // UTF-8 input text `日本語` // UTF-8 input text as a raw literal -"\u65e5\u672c\u8a9e" // The explicit Unicode code points -"\U000065e5\U0000672c\U00008a9e" // The explicit Unicode code points -"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" // The explicit UTF-8 bytes +"\u65e5\u672c\u8a9e" // the explicit Unicode code points +"\U000065e5\U0000672c\U00008a9e" // the explicit Unicode code points +"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" // the explicit UTF-8 bytes </pre> <p> If the source code represents a character as two code points, such as a combining form involving an accent and a letter, the result will be -an error if placed in a character literal (it is not a single code +an error if placed in a rune literal (it is not a single code point), and will appear as two code points if placed in a string literal. </p> @@ -518,7 +534,7 @@ literal. <h2 id="Constants">Constants</h2> <p>There are <i>boolean constants</i>, -<i>character constants</i>, +<i>rune constants</i>, <i>integer constants</i>, <i>floating-point constants</i>, <i>complex constants</i>, and <i>string constants</i>. Character, integer, floating-point, @@ -528,7 +544,7 @@ collectively called <i>numeric constants</i>. <p> A constant value is represented by a -<a href="#Character_literals">character</a>, +<a href="#Rune_literals">rune</a>, <a href="#Integer_literals">integer</a>, <a href="#Floating-point_literals">floating-point</a>, <a href="#Imaginary_literals">imaginary</a>, @@ -622,14 +638,15 @@ expressions</a>. <p> A type determines the set of values and operations specific to values of that -type. A type may be specified by a (possibly qualified) <i>type name</i> -(§<a href="#Qualified_identifiers">Qualified identifier</a>, §<a href="#Type_declarations">Type declarations</a>) or a <i>type literal</i>, +type. A type may be specified by a +(possibly <a href="#Qualified_identifiers">qualified</a>) <i>type name</i> +(§<a href="#Type_declarations">Type declarations</a>) or a <i>type literal</i>, which composes a new type from previously declared types. </p> <pre class="ebnf"> Type = TypeName | TypeLit | "(" Type ")" . -TypeName = QualifiedIdent . +TypeName = identifier | QualifiedIdent . TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | SliceType | MapType | ChannelType . </pre> @@ -646,7 +663,7 @@ type literals. The <i>static type</i> (or just <i>type</i>) of a variable is the type defined by its declaration. Variables of interface type also have a distinct <i>dynamic type</i>, which -is the actual type of the value stored in the variable at run-time. +is the actual type of the value stored in the variable at run time. The dynamic type may vary during execution but is always <a href="#Assignability">assignable</a> to the static type of the interface variable. For non-interface @@ -764,19 +781,21 @@ particular architecture. <p> A <i>string type</i> represents the set of string values. -Strings behave like slices of bytes but are immutable: once created, +A string value is a (possibly empty) sequence of bytes. +Strings are immutable: once created, it is impossible to change the contents of a string. The predeclared string type is <code>string</code>. +</p> <p> -The elements of strings have type <code>byte</code> and may be -accessed using the usual <a href="#Indexes">indexing operations</a>. It is -illegal to take the address of such an element; if -<code>s[i]</code> is the <i>i</i>th byte of a -string, <code>&s[i]</code> is invalid. The length of string -<code>s</code> can be discovered using the built-in function -<code>len</code>. The length is a compile-time constant if <code>s</code> -is a string literal. +The length of a string <code>s</code> (its size in bytes) can be discovered using +the built-in function <a href="#Length_and_capacity"><code>len</code></a>. +The length is a compile-time constant if the string is a constant. +A string's bytes can be accessed by integer <a href="#Index_expressions">indices</a> +0 through <code>len(s)-1</code>. +It is illegal to take the address of such an element; if +<code>s[i]</code> is the <code>i</code>'th byte of a +string, <code>&s[i]</code> is invalid. </p> @@ -796,12 +815,13 @@ ElementType = Type . </pre> <p> -The length is part of the array's type and must be a -<a href="#Constant_expressions">constant expression</a> that evaluates to a non-negative -integer value. The length of array <code>a</code> can be discovered -using the built-in function <a href="#Length_and_capacity"><code>len(a)</code></a>. -The elements can be indexed by integer -indices 0 through <code>len(a)-1</code> (§<a href="#Indexes">Indexes</a>). +The length is part of the array's type; it must evaluate to a non- +negative <a href="#Constants">constant</a> representable by a value +of type <code>int</code>. +The length of array <code>a</code> can be discovered +using the built-in function <a href="#Length_and_capacity"><code>len</code></a>. +The elements can be addressed by integer <a href="#Index_expressions">indices</a> +0 through <code>len(a)-1</code>. Array types are always one-dimensional but may be composed to form multi-dimensional types. </p> @@ -830,9 +850,9 @@ SliceType = "[" "]" ElementType . <p> Like arrays, slices are indexable and have a length. The length of a slice <code>s</code> can be discovered by the built-in function -<a href="#Length_and_capacity"><code>len(s)</code></a>; unlike with arrays it may change during -execution. The elements can be addressed by integer indices 0 -through <code>len(s)-1</code> (§<a href="#Indexes">Indexes</a>). The slice index of a +<a href="#Length_and_capacity"><code>len</code></a>; unlike with arrays it may change during +execution. The elements can be addressed by integer <a href="#Index_expressions">indices</a> +0 through <code>len(s)-1</code>. The slice index of a given element may be less than the index of the same element in the underlying array. </p> @@ -981,7 +1001,7 @@ promoted methods are included in the method set of the struct as follows: <code>T</code>. The method set of <code>*S</code> also includes promoted methods with receiver <code>*T</code>. </li> - + <li> If <code>S</code> contains an anonymous field <code>*T</code>, the method sets of <code>S</code> and <code>*S</code> both @@ -994,7 +1014,7 @@ promoted methods are included in the method set of the struct as follows: A field declaration may be followed by an optional string literal <i>tag</i>, which becomes an attribute for all the fields in the corresponding field declaration. The tags are made -visible through a <a href="#Package_unsafe">reflection interface</a> +visible through a <a href="/pkg/reflect/#StructTag">reflection interface</a> but are otherwise ignored. </p> @@ -1046,8 +1066,11 @@ ParameterDecl = [ IdentifierList ] [ "..." ] Type . <p> Within a list of parameters or results, the names (IdentifierList) must either all be present or all be absent. If present, each name -stands for one item (parameter or result) of the specified type; if absent, each -type stands for one item of that type. Parameter and result +stands for one item (parameter or result) of the specified type and +all non-<a href="#Blank_identifier">blank</a> names in the signature +must be <a href="#Uniqueness_of_identifiers">unique</a>. +If absent, each type stands for one item of that type. +Parameter and result lists are always parenthesized except that if there is exactly one unnamed result it may be written as an unparenthesized type. </p> @@ -1232,10 +1255,10 @@ map[string]interface{} <p> The number of map elements is called its length. For a map <code>m</code>, it can be discovered using the -built-in function <a href="#Length_and_capacity"><code>len(m)</code></a> +built-in function <a href="#Length_and_capacity"><code>len</code></a> and may change during execution. Elements may be added during execution using <a href="#Assignments">assignments</a> and retrieved with -<a href="#Indexes">index</a> expressions; they may be removed with the +<a href="#Index_expressions">index expressions</a>; they may be removed with the <a href="#Deletion_of_map_elements"><code>delete</code></a> built-in function. </p> <p> @@ -1510,11 +1533,11 @@ Go is lexically scoped using blocks: or function (but not method) declared at top level (outside any function) is the package block.</li> - <li>The scope of an imported package identifier is the file block + <li>The scope of the package name of an imported package is the file block of the file containing the import declaration.</li> - <li>The scope of an identifier denoting a function parameter or - result variable is the function body.</li> + <li>The scope of an identifier denoting a method receiver, function parameter, + or result variable is the function body.</li> <li>The scope of a constant or variable identifier declared inside a function begins at the end of the ConstSpec or VarSpec @@ -1897,7 +1920,7 @@ _, y, _ := coord(p) // coord() returns three values; only interested in y coord <p> Unlike regular variable declarations, a short variable declaration may redeclare variables provided they -were originally declared in the same block with the same type, and at +were originally declared earlier in the same block with the same type, and at least one of the non-<a href="#Blank_identifier">blank</a> variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new @@ -1907,6 +1930,7 @@ variable; it just assigns a new value to the original. <pre> field1, offset := nextField(str, 0) field2, offset := nextField(str, offset) // redeclares offset +a, a := 1, 2 // illegal: double declaration of a or no new variable if a was declared elsewhere </pre> <p> @@ -1969,8 +1993,15 @@ is visible only within selectors for that type. </p> <p> -For a base type, the non-<a href="#Blank_identifier">blank</a> names of -methods bound to it must be <a href="#Uniqueness_of_identifiers">unique</a>. +A non-<a href="#Blank_identifier">blank</a> receiver identifier must be +<a href="#Uniqueness_of_identifiers">unique</a> in the method signature. +If the receiver's value is not referenced inside the body of the method, +its identifier may be omitted in the declaration. The same applies in +general to parameters of functions and methods. +</p> + +<p> +For a base type, the non-blank names of methods bound to it must be unique. If the base type is a <a href="#Struct_types">struct type</a>, the non-blank method and field names must be distinct. </p> @@ -1997,12 +2028,6 @@ to the base type <code>Point</code>. </p> <p> -If the receiver's value is not referenced inside the body of the method, -its identifier may be omitted in the declaration. The same applies in -general to parameters of functions and methods. -</p> - -<p> The type of a method is the type of a function with the receiver as first argument. For instance, the method <code>Scale</code> has type </p> @@ -2026,25 +2051,33 @@ operators and functions to operands. <h3 id="Operands">Operands</h3> <p> -Operands denote the elementary values in an expression. +Operands denote the elementary values in an expression. An operand may be a +literal, a (possibly <a href="#Qualified_identifiers">qualified</a>) identifier +denoting a +<a href="#Constant_declarations">constant</a>, +<a href="#Variable_declarations">variable</a>, or +<a href="#Function_declarations">function</a>, +a <a href="#Method_expressions">method expression</a> yielding a function, +or a parenthesized expression. </p> <pre class="ebnf"> -Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" . +Operand = Literal | OperandName | MethodExpr | "(" Expression ")" . Literal = BasicLit | CompositeLit | FunctionLit . -BasicLit = int_lit | float_lit | imaginary_lit | char_lit | string_lit . +BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit . +OperandName = identifier | QualifiedIdent. </pre> - <h3 id="Qualified_identifiers">Qualified identifiers</h3> <p> -A qualified identifier is a non-<a href="#Blank_identifier">blank</a> identifier -qualified by a package name prefix. +A qualified identifier is an identifier qualified with a package name prefix. +Both the package name and the identifier must not be +<a href="#Blank_identifier">blank</a>. </p> <pre class="ebnf"> -QualifiedIdent = [ PackageName "." ] identifier . +QualifiedIdent = PackageName "." identifier . </pre> <p> @@ -2089,7 +2122,7 @@ The types of the expressions must be <a href="#Assignability">assignable</a> to the respective field, element, and key types of the LiteralType; there is no additional conversion. The key is interpreted as a field name for struct literals, -an index expression for array and slice literals, and a key for map literals. +an index for array and slice literals, and a key for map literals. For map literals, all elements must have a key. It is an error to specify multiple elements with the same field name or constant key value. @@ -2101,18 +2134,18 @@ For struct literals the following rules apply: <ul> <li>A key must be a field name declared in the LiteralType. </li> - <li>A literal that does not contain any keys must + <li>An element list that does not contain any keys must list an element for each struct field in the order in which the fields are declared. </li> <li>If any element has a key, every element must have a key. </li> - <li>A literal that contains keys does not need to + <li>An element list that contains keys does not need to have an element for each struct field. Omitted fields get the zero value for that field. </li> <li>A literal may omit the element list; such a literal evaluates - to the zero value for its type. + to the zero value for its type. </li> <li>It is an error to specify an element for a non-exported field of a struct belonging to a different package. @@ -2198,7 +2231,7 @@ Within a composite literal of array, slice, or map type <code>T</code>, elements that are themselves composite literals may elide the respective literal type if it is identical to the element type of <code>T</code>. Similarly, elements that are addresses of composite literals may elide -the <code>&T</code> when the the element type is <code>*T</code>. +the <code>&T</code> when the element type is <code>*T</code>. </p> @@ -2315,7 +2348,6 @@ Point{1, 2} m["foo"] s[i : j + 1] obj.color -math.Sin f.p[i].x() </pre> @@ -2323,7 +2355,9 @@ f.p[i].x() <h3 id="Selectors">Selectors</h3> <p> -A primary expression of the form +For a <a href="#Primary_expressions">primary expression</a> <code>x</code> +that is not a <a href="#Package_clause">package name</a>, the +<i>selector expression</i> </p> <pre> @@ -2331,17 +2365,20 @@ x.f </pre> <p> -denotes the field or method <code>f</code> of the value denoted by <code>x</code> -(or sometimes <code>*x</code>; see below). The identifier <code>f</code> -is called the (field or method) -<i>selector</i>; it must not be the <a href="#Blank_identifier">blank identifier</a>. -The type of the expression is the type of <code>f</code>. +denotes the field or method <code>f</code> of the value <code>x</code> +(or sometimes <code>*x</code>; see below). +The identifier <code>f</code> is called the (field or method) <i>selector</i>; +it must not be the <a href="#Blank_identifier">blank identifier</a>. +The type of the selector expression is the type of <code>f</code>. +If <code>x</code> is a package name, see the section on +<a href="#Qualified_identifiers">qualified identifiers</a>. </p> + <p> A selector <code>f</code> may denote a field or method <code>f</code> of a type <code>T</code>, or it may refer -to a field or method <code>f</code> of a nested anonymous field of -<code>T</code>. +to a field or method <code>f</code> of a nested +<a href="#Struct_types">anonymous field</a> of <code>T</code>. The number of anonymous fields traversed to reach <code>f</code> is called its <i>depth</i> in <code>T</code>. The depth of a field or method <code>f</code> @@ -2350,9 +2387,11 @@ The depth of a field or method <code>f</code> declared in an anonymous field <code>A</code> in <code>T</code> is the depth of <code>f</code> in <code>A</code> plus one. </p> + <p> The following rules apply to selectors: </p> + <ol> <li> For a value <code>x</code> of type <code>T</code> or <code>*T</code> @@ -2364,18 +2403,26 @@ If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code>< with shallowest depth, the selector expression is illegal. </li> <li> -For a variable <code>x</code> of type <code>I</code> -where <code>I</code> is an interface type, -<code>x.f</code> denotes the actual method with name <code>f</code> of the value assigned -to <code>x</code> if there is such a method. -If no value or <code>nil</code> was assigned to <code>x</code>, <code>x.f</code> is illegal. +For a variable <code>x</code> of type <code>I</code> where <code>I</code> +is an interface type, <code>x.f</code> denotes the actual method with name +<code>f</code> of the value assigned to <code>x</code>. +If there is no method with name <code>f</code> in the +<a href="#Method_sets">method set</a> of <code>I</code>, the selector +expression is illegal. </li> <li> In all other cases, <code>x.f</code> is illegal. </li> +<li> +If <code>x</code> is of pointer or interface type and has the value +<code>nil</code>, assigning to, evaluating, or calling <code>x.f</code> +causes a <a href="#Run_time_panics">run-time panic</a>. +</li> </ol> + <p> -Selectors automatically dereference pointers to structs. +Selectors automatically <a href="#Address_operators">dereference</a> +pointers to structs. If <code>x</code> is a pointer to a struct, <code>x.y</code> is shorthand for <code>(*x).y</code>; if the field <code>y</code> is also a pointer to a struct, <code>x.y.z</code> is shorthand @@ -2384,6 +2431,7 @@ If <code>x</code> contains an anonymous field of type <code>*A</code>, where <code>A</code> is also a struct type, <code>x.f</code> is a shortcut for <code>(*x.A).f</code>. </p> + <p> For example, given the declarations: </p> @@ -2421,9 +2469,9 @@ p.z // (*p).z p.y // ((*p).T1).y p.x // (*(*p).T0).x -p.M2 // (*p).M2 -p.M1 // ((*p).T1).M1 -p.M0 // ((*p).T0).M0 +p.M2() // (*p).M2() +p.M1() // ((*p).T1).M1() +p.M0() // ((*p).T0).M0() </pre> @@ -2434,7 +2482,7 @@ TODO: Specify what happens to receivers. --> -<h3 id="Indexes">Indexes</h3> +<h3 id="Index_expressions">Index expressions</h3> <p> A primary expression of the form @@ -2452,16 +2500,35 @@ rules apply: </p> <p> +If <code>a</code> is not a map: +</p> +<ul> + <li>the index <code>x</code> must be an integer value; it is <i>in range</i> if <code>0 <= x < len(a)</code>, + otherwise it is <i>out of range</i></li> + <li>a <a href="#Constants">constant</a> index must be non-negative + and representable by a value of type <code>int</code> +</ul> + +<p> For <code>a</code> of type <code>A</code> or <code>*A</code> -where <code>A</code> is an <a href="#Array_types">array type</a>, -or for <code>a</code> of type <code>S</code> where <code>S</code> is a <a href="#Slice_types">slice type</a>: +where <code>A</code> is an <a href="#Array_types">array type</a>: </p> <ul> - <li><code>x</code> must be an integer value and <code>0 <= x < len(a)</code></li> + <li>a <a href="#Constants">constant</a> index must be in range</li> + <li>if <code>a</code> is <code>nil</code> or if <code>x</code> is out of range at run time, + a <a href="#Run_time_panics">run-time panic</a> occurs</li> <li><code>a[x]</code> is the array element at index <code>x</code> and the type of - <code>a[x]</code> is the element type of <code>A</code></li> - <li>if <code>a</code> is <code>nil</code> or if the index <code>x</code> is out of range, - a <a href="#Run_time_panics">run-time panic</a> occurs</li> + <code>a[x]</code> is the element type of <code>A</code></li> +</ul> + +<p> +For <code>a</code> of type <code>S</code> where <code>S</code> is a <a href="#Slice_types">slice type</a>: +</p> +<ul> + <li>if the slice is <code>nil</code> or if <code>x</code> is out of range at run time, + a <a href="#Run_time_panics">run-time panic</a> occurs</li> + <li><code>a[x]</code> is the slice element at index <code>x</code> and the type of + <code>a[x]</code> is the element type of <code>S</code></li> </ul> <p> @@ -2469,12 +2536,13 @@ For <code>a</code> of type <code>T</code> where <code>T</code> is a <a href="#String_types">string type</a>: </p> <ul> - <li><code>x</code> must be an integer value and <code>0 <= x < len(a)</code></li> + <li>a <a href="#Constants">constant</a> index must be in range + if the string <code>a</code> is also constant</li> + <li>if <code>x</code> is out of range at run time, + a <a href="#Run_time_panics">run-time panic</a> occurs</li> <li><code>a[x]</code> is the byte at index <code>x</code> and the type of - <code>a[x]</code> is <code>byte</code></li> + <code>a[x]</code> is <code>byte</code></li> <li><code>a[x]</code> may not be assigned to</li> - <li>if the index <code>x</code> is out of range, - a <a href="#Run_time_panics">run-time panic</a> occurs</li> </ul> <p> @@ -2483,14 +2551,14 @@ where <code>M</code> is a <a href="#Map_types">map type</a>: </p> <ul> <li><code>x</code>'s type must be - <a href="#Assignability">assignable</a> - to the key type of <code>M</code></li> + <a href="#Assignability">assignable</a> + to the key type of <code>M</code></li> <li>if the map contains an entry with key <code>x</code>, - <code>a[x]</code> is the map value with key <code>x</code> - and the type of <code>a[x]</code> is the value type of <code>M</code></li> + <code>a[x]</code> is the map value with key <code>x</code> + and the type of <code>a[x]</code> is the value type of <code>M</code></li> <li>if the map is <code>nil</code> or does not contain such an entry, - <code>a[x]</code> is the <a href="#The_zero_value">zero value</a> - for the value type of <code>M</code></li> + <code>a[x]</code> is the <a href="#The_zero_value">zero value</a> + for the value type of <code>M</code></li> </ul> <p> @@ -2533,9 +2601,9 @@ a[low : high] </pre> <p> -constructs a substring or slice. The index expressions <code>low</code> and +constructs a substring or slice. The indices <code>low</code> and <code>high</code> select which elements appear in the result. The result has -indexes starting at 0 and length equal to +indices starting at 0 and length equal to <code>high</code> - <code>low</code>. After slicing the array <code>a</code> </p> @@ -2556,7 +2624,7 @@ s[2] == 4 </pre> <p> -For convenience, any of the index expressions may be omitted. A missing <code>low</code> +For convenience, any of the indices may be omitted. A missing <code>low</code> index defaults to zero; a missing <code>high</code> index defaults to the length of the sliced operand: </p> @@ -2568,9 +2636,15 @@ a[:] // same as a[0 : len(a)] </pre> <p> -For arrays or strings, the indexes <code>low</code> and <code>high</code> must -satisfy 0 <= <code>low</code> <= <code>high</code> <= length; for -slices, the upper bound is the capacity rather than the length. +For arrays or strings, the indices <code>low</code> and <code>high</code> are +<i>in range</i> if <code>0</code> <= <code>low</code> <= <code>high</code> <= <code>len(a)</code>, +otherwise they are <i>out of range</i>. +For slices, the upper index bound is the slice capacity <code>cap(a)</code> rather than the length. +A <a href="#Constants">constant</a> index must be non-negative and representable by a value of type +<code>int</code>. +If both indices +are constant, they must satisfy <code>low <= high</code>. If <code>a</code> is <code>nil</code> +or if the indices are out of range at run time, a <a href="#Run_time_panics">run-time panic</a> occurs. </p> <p> @@ -2601,19 +2675,33 @@ The notation <code>x.(T)</code> is called a <i>type assertion</i>. More precisely, if <code>T</code> is not an interface type, <code>x.(T)</code> asserts that the dynamic type of <code>x</code> is <a href="#Type_identity">identical</a> to the type <code>T</code>. +In this case, <code>T</code> must <a href="#Method_sets">implement</a> the (interface) type of <code>x</code>; +otherwise the type assertion is invalid since it is not possible for <code>x</code> +to store a value of type <code>T</code>. If <code>T</code> is an interface type, <code>x.(T)</code> asserts that the dynamic type -of <code>x</code> implements the interface <code>T</code> (§<a href="#Interface_types">Interface types</a>). +of <code>x</code> implements the interface <code>T</code>. </p> <p> If the type assertion holds, the value of the expression is the value stored in <code>x</code> and its type is <code>T</code>. If the type assertion is false, a <a href="#Run_time_panics">run-time panic</a> occurs. In other words, even though the dynamic type of <code>x</code> -is known only at run-time, the type of <code>x.(T)</code> is +is known only at run time, the type of <code>x.(T)</code> is known to be <code>T</code> in a correct program. </p> + +<pre> +var x interface{} = 7 // x has dynamic type int and value 7 +i := x.(int) // i has type int and value 7 + +type I interface { m() } +var y I +s := y.(string) // illegal: string does not implement I (missing method m) +r := y.(io.Reader) // r has type io.Reader and y must implement both I and io.Reader +</pre> + <p> -If a type assertion is used in an assignment or initialization of the form +If a type assertion is used in an <a href="#Assignments">assignment</a> or initialization of the form </p> <pre> @@ -2629,7 +2717,7 @@ otherwise, the expression returns <code>(Z, false)</code> where <code>Z</code> is the <a href="#The_zero_value">zero value</a> for type <code>T</code>. No run-time panic occurs in this case. The type assertion in this construct thus acts like a function call -returning a value and a boolean indicating success. (§<a href="#Assignments">Assignments</a>) +returning a value and a boolean indicating success. </p> @@ -2677,13 +2765,14 @@ causes a <a href="#Run_time_panics">run-time panic</a>. </p> <p> -As a special case, if the return parameters of a function or method +As a special case, if the return values of a function or method <code>g</code> are equal in number and individually assignable to the parameters of another function or method <code>f</code>, then the call <code>f(g(<i>parameters_of_g</i>))</code> will invoke <code>f</code> after binding the return values of <code>g</code> to the parameters of <code>f</code> in order. The call -of <code>f</code> must contain no parameters other than the call of <code>g</code>. +of <code>f</code> must contain no parameters other than the call of <code>g</code>, +and <code>g</code> must have at least one return value. If <code>f</code> has a final <code>...</code> parameter, it is assigned the return values of <code>g</code> that remain after assignment of regular parameters. @@ -2834,8 +2923,8 @@ As a consequence, statement <code>*p++</code> is the same as <code>(*p)++</code> <p> There are five precedence levels for binary operators. Multiplication operators bind strongest, followed by addition -operators, comparison operators, <code>&&</code> (logical and), -and finally <code>||</code> (logical or): +operators, comparison operators, <code>&&</code> (logical AND), +and finally <code>||</code> (logical OR): </p> <pre class="grammar"> @@ -2878,10 +2967,10 @@ to strings. All other arithmetic operators apply to integers only. / quotient integers, floats, complex values % remainder integers -& bitwise and integers -| bitwise or integers -^ bitwise xor integers -&^ bit clear (and not) integers +& bitwise AND integers +| bitwise OR integers +^ bitwise XOR integers +&^ bit clear (AND NOT) integers << left shift integer << unsigned integer >> right shift integer >> unsigned integer @@ -2938,10 +3027,11 @@ int64 -9223372036854775808 </pre> <p> -If the divisor is zero, a <a href="#Run_time_panics">run-time panic</a> occurs. -If the dividend is positive and the divisor is a constant power of 2, +If the divisor is a <a href="#Constants">constant</a>, it must not be zero. +If the divisor is zero at run time, a <a href="#Run_time_panics">run-time panic</a> occurs. +If the dividend is non-negative and the divisor is a constant power of 2, the division may be replaced by a right shift, and computing the remainder may -be replaced by a bitwise "and" operation: +be replaced by a bitwise AND operation: </p> <pre> @@ -2976,10 +3066,10 @@ follows: </pre> <p> -For floating-point numbers, +For floating-point and complex numbers, <code>+x</code> is the same as <code>x</code>, while <code>-x</code> is the negation of <code>x</code>. -The result of a floating-point division by zero is not specified beyond the +The result of a floating-point or complex division by zero is not specified beyond the IEEE-754 standard; whether a <a href="#Run_time_panics">run-time panic</a> occurs is implementation-specific. </p> @@ -3142,9 +3232,9 @@ The right operand is evaluated conditionally. </p> <pre class="grammar"> -&& conditional and p && q is "if p then q else false" -|| conditional or p || q is "if p then true else q" -! not !p is "not p" +&& conditional AND p && q is "if p then q else false" +|| conditional OR p || q is "if p then true else q" +! NOT !p is "not p" </pre> @@ -3158,6 +3248,7 @@ that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, <code>x</code> may also be a +(possibly parenthesized) <a href="#Composite_literals">composite literal</a>. </p> <p> @@ -3171,6 +3262,7 @@ will cause a <a href="#Run_time_panics">run-time panic</a>. <pre> &x &a[f(2)] +&Point{2, 3} *p *pf(x) </pre> @@ -3181,9 +3273,13 @@ will cause a <a href="#Run_time_panics">run-time panic</a>. <p> For an operand <code>ch</code> of <a href="#Channel_types">channel type</a>, the value of the receive operation <code><-ch</code> is the value received -from the channel <code>ch</code>. The type of the value is the element type of -the channel. The expression blocks until a value is available. +from the channel <code>ch</code>. The channel direction must permit receive operations, +and the type of the receive operation is the element type of the channel. +The expression blocks until a value is available. Receiving from a <code>nil</code> channel blocks forever. +Receiving from a <a href="#Close">closed</a> channel always succeeds, +immediately returning the element type's <a href="#The_zero_value">zero +value</a>. </p> <pre> @@ -3204,11 +3300,11 @@ var x, ok = <-ch </pre> <p> -yields an additional result. -The boolean variable <code>ok</code> indicates whether -the received value was sent on the channel (<code>true</code>) -or is a <a href="#The_zero_value">zero value</a> returned -because the channel is closed and empty (<code>false</code>). +yields an additional result of type <code>bool</code> reporting whether the +communication succeeded. The value of <code>ok</code> is <code>true</code> +if the value received was delivered by a successful send operation to the +channel, or <code>false</code> if it is a zero value generated because the +channel is closed and empty. </p> <!-- @@ -3230,7 +3326,7 @@ argument that is the receiver of the method. <pre class="ebnf"> MethodExpr = ReceiverType "." MethodName . -ReceiverType = TypeName | "(" "*" TypeName ")" . +ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" . </pre> <p> @@ -3267,13 +3363,15 @@ func(tv T, a int) int <p> That function may be called normally with an explicit receiver, so -these three invocations are equivalent: +these five invocations are equivalent: </p> <pre> t.Mv(7) T.Mv(t, 7) -f := T.Mv; f(t, 7) +(T).Mv(t, 7) +f1 := T.Mv; f1(t, 7) +f2 := (T).Mv; f2(t, 7) </pre> <p> @@ -3345,18 +3443,25 @@ that can be converted to type <code>T</code>. </p> <pre class="ebnf"> -Conversion = Type "(" Expression ")" . +Conversion = Type "(" Expression [ "," ] ")" . </pre> <p> -If the type starts with an operator it must be parenthesized: +If the type starts with the operator <code>*</code> or <code><-</code>, +or if the type starts with the keyword <code>func</code> +and has no result list, it must be parenthesized when +necessary to avoid ambiguity: </p> <pre> *Point(p) // same as *(Point(p)) -(*Point)(p) // p is converted to (*Point) +(*Point)(p) // p is converted to *Point <-chan int(c) // same as <-(chan int(c)) -(<-chan int)(c) // c is converted to (<-chan int) +(<-chan int)(c) // c is converted to <-chan int +func()(x) // function signature func() x +(func())(x) // x is converted to func() +(func() int)(x) // x is converted to func() int +func() int(x) // x is converted to func() int (unambiguous) </pre> <p> @@ -3369,6 +3474,14 @@ type <code>T</code> in any of these cases: <code>x</code> is representable by a value of type <code>T</code>. </li> <li> + <code>x</code> is a floating-point constant, + <code>T</code> is a floating-point type, + and <code>x</code> is representable by a value + of type <code>T</code> after rounding using + IEEE 754 round-to-even rules. + The constant <code>T(x)</code> is the rounded value. + </li> + <li> <code>x</code> is an integer constant and <code>T</code> is a <a href="#String_types">string type</a>. The same rule as for non-constant <code>x</code> applies in this case @@ -3384,6 +3497,7 @@ Converting a constant yields a typed constant as result. uint(iota) // iota value of type uint float32(2.718281828) // 2.718281828 of type float32 complex128(1) // 1.0 + 0.0i of type complex128 +float32(0.49999999) // 0.5 of type float32 string('x') // "x" of type string string(0x266c) // "♬" of type string MyString("foo" + "bar") // "foobar" of type MyString @@ -3419,12 +3533,11 @@ in any of these cases: <code>x</code>'s type and <code>T</code> are both complex types. </li> <li> - <code>x</code> is an integer or has type <code>[]byte</code> or - <code>[]rune</code> and <code>T</code> is a string type. + <code>x</code> is an integer or a slice of bytes or runes + and <code>T</code> is a string type. </li> <li> - <code>x</code> is a string and <code>T</code> is <code>[]byte</code> or - <code>[]rune</code>. + <code>x</code> is a string and <code>T</code> is a slice of bytes or runes. </li> </ul> @@ -3490,7 +3603,7 @@ the range of valid Unicode code points are converted to <code>"\uFFFD"</code>. <pre> string('a') // "a" -string(-1) // "\ufffd" == "\xef\xbf\xbd " +string(-1) // "\ufffd" == "\xef\xbf\xbd" string(0xf8) // "\u00f8" == "ø" == "\xc3\xb8" type MyString string MyString(0x65e5) // "\u65e5" == "日" == "\xe6\x97\xa5" @@ -3551,7 +3664,7 @@ MyRunes("白鵬翔") // []rune{0x767d, 0x9d6c, 0x7fd4} <p> Constant expressions may contain only <a href="#Constants">constant</a> -operands and are evaluated at compile-time. +operands and are evaluated at compile time. </p> <p> @@ -3560,7 +3673,7 @@ wherever it is legal to use an operand of boolean, numeric, or string type, respectively. Except for shift operations, if the operands of a binary operation are different kinds of untyped constants, the operation and, for non-boolean operations, the result use -the kind that appears later in this list: integer, character, floating-point, complex. +the kind that appears later in this list: integer, rune, floating-point, complex. For example, an untyped integer constant divided by an untyped complex constant yields an untyped complex constant. </p> @@ -3581,14 +3694,15 @@ complex, or string constant). const a = 2 + 3.0 // a == 5.0 (untyped floating-point constant) const b = 15 / 4 // b == 3 (untyped integer constant) const c = 15 / 4.0 // c == 3.75 (untyped floating-point constant) -const Θ float64 = 3/2 // Θ == 1.5 (type float64) +const Θ float64 = 3/2 // Θ == 1.0 (type float64, 3/2 is integer division) +const Π float64 = 3/2. // Π == 1.5 (type float64, 3/2. is float division) const d = 1 << 3.0 // d == 8 (untyped integer constant) const e = 1.0 << 3 // e == 8 (untyped integer constant) const f = int32(1) << 33 // f == 0 (type int32) const g = float64(2) >> 1 // illegal (float64(2) is a typed floating-point constant) const h = "foo" > "bar" // h == true (untyped boolean constant) const j = true // j == true (untyped boolean constant) -const k = 'w' + 1 // k == 'x' (untyped character constant) +const k = 'w' + 1 // k == 'x' (untyped rune constant) const l = "hi" // l == "hi" (untyped string constant) const m = string(k) // m == "x" (type string) const Σ = 1 - 0.707i // (untyped complex constant) @@ -3598,13 +3712,13 @@ const Φ = iota*1i - 1/1i // (untyped complex constant) <p> Applying the built-in function <code>complex</code> to untyped -integer, character, or floating-point constants yields +integer, rune, or floating-point constants yields an untyped complex constant. </p> <pre> -const ic = complex(0, c) // ic == 3.75i (untyped complex constant) -const iΘ = complex(0, Θ) // iΘ == 1.5i (type complex128) +const ic = complex(0, c) // ic == 3.75i (untyped complex constant) +const iΘ = complex(0, Θ) // iΘ == 1.5i (type complex128) </pre> <p> @@ -3614,8 +3728,16 @@ by any predeclared type in the language. The following are legal declarations: </p> <pre> -const Huge = 1 << 100 -const Four int8 = Huge >> 98 +const Huge = 1 << 100 // Huge == 1267650600228229401496703205376 (untyped integer constant) +const Four int8 = Huge >> 98 // Four == 4 (type int8) +</pre> + +<p> +The divisor of a constant division or remainder operation must not be zero: +</p> + +<pre> +3.14 / 0.0 // illegal: division by zero </pre> <p> @@ -3626,9 +3748,9 @@ of the constant type. The following constant expressions are illegal: <pre> uint(-1) // -1 cannot be represented as a uint int(3.14) // 3.14 cannot be represented as an int -int64(Huge) // 1<<100 cannot be represented as an int64 -Four * 300 // 300 cannot be represented as an int8 -Four * 100 // 400 cannot be represented as an int8 +int64(Huge) // 1267650600228229401496703205376 cannot be represented as an int64 +Four * 300 // operand 300 cannot be represented as an int8 (type of Four) +Four * 100 // product 400 cannot be represented as an int8 (type of Four) </pre> <p> @@ -3639,7 +3761,7 @@ and -1 for signed and untyped constants. <pre> ^1 // untyped integer constant, equal to -2 -uint8(^1) // error, same as uint8(-2), out of range +uint8(^1) // illegal: same as uint8(-2), -2 cannot be represented as a uint8 ^uint8(1) // typed uint8 constant, same as 0xFF ^ uint8(1) = uint8(0xFE) int8(^1) // same as int8(-2) ^int8(1) // same as -1 ^ int8(1) = -2 @@ -3668,8 +3790,10 @@ overflow etc. errors being caught. <h3 id="Order_of_evaluation">Order of evaluation</h3> <p> -When evaluating the elements of an assignment or expression, -all function calls, method calls and +When evaluating the <a href="#Operands">operands</a> of an expression, +<a href="#Assignments">assignment</a>, or +<a href="#Return_statements">return statement</a>, +all function calls, method calls, and communication operations are evaluated in lexical left-to-right order. </p> @@ -3689,6 +3813,12 @@ and indexing of <code>x</code> and the evaluation of <code>y</code> is not specified. </p> +<pre> +a := 1 +f := func() int { a = 2; return 3 } +x := []int{a, f()} // x may be [1, 3] or [2, 3]: evaluation order between a and f() is not specified +</pre> + <p> Floating-point operations within a single expression are evaluated according to the associativity of the operators. Explicit parentheses affect the evaluation @@ -3745,7 +3875,9 @@ Error: log.Panic("error encountered") <h3 id="Expression_statements">Expression statements</h3> <p> -Function calls, method calls, and receive operations +With the exception of specific built-in functions, +function and method <a href="#Calls">calls</a> and +<a href="#Receive_operator">receive operations</a> can appear in statement context. Such statements may be parenthesized. </p> @@ -3753,11 +3885,21 @@ can appear in statement context. Such statements may be parenthesized. ExpressionStmt = Expression . </pre> +<p> +The following built-in functions are not permitted in statement context: +</p> + +<pre> +append cap complex imag len make new real +unsafe.Alignof unsafe.Offsetof unsafe.Sizeof +</pre> + <pre> h(x+y) f.Close() <-ch (<-ch) +len("foo") // illegal if len is the built-in function </pre> @@ -3765,8 +3907,9 @@ f.Close() <p> A send statement sends a value on a channel. -The channel expression must be of <a href="#Channel_types">channel type</a> -and the type of the value must be <a href="#Assignability">assignable</a> +The channel expression must be of <a href="#Channel_types">channel type</a>, +the channel direction must permit send operations, +and the type of the value to be sent must be <a href="#Assignability">assignable</a> to the channel's element type. </p> @@ -3884,7 +4027,7 @@ operand on the left. <p> The assignment proceeds in two phases. -First, the operands of <a href="#Indexes">index expressions</a> +First, the operands of <a href="#Index_expressions">index expressions</a> and <a href="#Address_operators">pointer indirections</a> (including implicit pointer indirections in <a href="#Selectors">selectors</a>) on the left and the expressions on the right are all @@ -3926,7 +4069,7 @@ is assigned to a variable of interface type, the constant is <a href="#Conversio to type <code>bool</code>, <code>rune</code>, <code>int</code>, <code>float64</code>, <code>complex128</code> or <code>string</code> respectively, depending on whether the value is a -boolean, character, integer, floating-point, complex, or string constant. +boolean, rune, integer, floating-point, complex, or string constant. </p> @@ -4011,12 +4154,14 @@ ExprSwitchCase = "case" ExpressionList | "default" . </pre> <p> -In a case or default clause, -the last statement only may be a "fallthrough" statement -(§<a href="#Fallthrough_statements">Fallthrough statement</a>) to +In a case or default clause, the last non-empty statement +may be a (possibly <a href="#Labeled_statements">labeled</a>) +<a href="#Fallthrough_statements">"fallthrough" statement</a> to indicate that control should flow from the end of this clause to the first statement of the next clause. Otherwise control flows to the end of the "switch" statement. +A "fallthrough" statement may appear as the last statement of all +but the last clause of an expression switch. </p> <p> @@ -4049,9 +4194,20 @@ case x == 4: f3() A type switch compares types rather than values. It is otherwise similar to an expression switch. It is marked by a special switch expression that has the form of a <a href="#Type_assertions">type assertion</a> -using the reserved word <code>type</code> rather than an actual type. -Cases then match literal types against the dynamic type of the expression -in the type assertion. +using the reserved word <code>type</code> rather than an actual type: +</p> + +<pre> +switch x.(type) { +// cases +} +</pre> + +<p> +Cases then match actual types <code>T</code> against the dynamic type of the +expression <code>x</code>. As with type assertions, <code>x</code> must be of +<a href="#Interface_types">interface type</a>, and each non-interface type +<code>T</code> listed in a case must implement the type of <code>x</code>. </p> <pre class="ebnf"> @@ -4087,17 +4243,17 @@ the following type switch: <pre> switch i := x.(type) { case nil: - printString("x is nil") + printString("x is nil") // type of i is type of x (interface{}) case int: - printInt(i) // i is an int + printInt(i) // type of i is int case float64: - printFloat64(i) // i is a float64 + printFloat64(i) // type of i is float64 case func(int) float64: - printFunction(i) // i is a function + printFunction(i) // type of i is func(int) float64 case bool, string: - printString("type is bool or string") // i is an interface{} + printString("type is bool or string") // type of i is type of x (interface{}) default: - printString("don't know the type") + printString("don't know the type") // type of i is type of x (interface{}) } </pre> @@ -4108,22 +4264,23 @@ could be rewritten: <pre> v := x // x is evaluated exactly once if v == nil { + i := v // type of i is type of x (interface{}) printString("x is nil") } else if i, isInt := v.(int); isInt { - printInt(i) // i is an int + printInt(i) // type of i is int } else if i, isFloat64 := v.(float64); isFloat64 { - printFloat64(i) // i is a float64 + printFloat64(i) // type of i is float64 } else if i, isFunc := v.(func(int) float64); isFunc { - printFunction(i) // i is a function + printFunction(i) // type of i is func(int) float64 } else { - i1, isBool := v.(bool) - i2, isString := v.(string) + _, isBool := v.(bool) + _, isString := v.(string) if isBool || isString { - i := v - printString("type is bool or string") // i is an interface{} + i := v // type of i is type of x (interface{}) + printString("type is bool or string") } else { - i := v - printString("don't know the type") // i is an interface{} + i := v // type of i is type of x (interface{}) + printString("don't know the type") } } </pre> @@ -4206,24 +4363,31 @@ to corresponding <i>iteration variables</i> and then executes the block. </p> <pre class="ebnf"> -RangeClause = Expression [ "," Expression ] ( "=" | ":=" ) "range" Expression . +RangeClause = ( ExpressionList "=" | IdentifierList ":=" ) "range" Expression . </pre> <p> The expression on the right in the "range" clause is called the <i>range expression</i>, -which may be an array, pointer to an array, slice, string, map, or channel. +which may be an array, pointer to an array, slice, string, map, or channel permitting +<a href="#Receive_operator">receive operations</a>. As with an assignment, the operands on the left must be <a href="#Address_operators">addressable</a> or map index expressions; they denote the iteration variables. If the range expression is a channel, only -one iteration variable is permitted, otherwise there may be one or two. -If the second iteration variable is the <a href="#Blank_identifier">blank identifier</a>, +one iteration variable is permitted, otherwise there may be one or two. In the latter case, +if the second iteration variable is the <a href="#Blank_identifier">blank identifier</a>, the range clause is equivalent to the same clause with only the first variable present. </p> <p> -The range expression is evaluated once before beginning the loop -except if the expression is an array, in which case, depending on -the expression, it might not be evaluated (see below). +The range expression is evaluated once before beginning the loop, +with one exception. If the range expression is an array or a pointer to an array +and only the first iteration value is present, only the range expression's +length is evaluated; if that length is constant by definition +(see §<a href="#Length_and_capacity">Length and capacity</a>), +the range expression itself will not be evaluated. +</p> + +<p> Function calls on the left are evaluated once per iteration. For each iteration, iteration values are produced as follows: </p> @@ -4234,14 +4398,14 @@ Range expression 1st value 2nd value (if 2nd v array or slice a [n]E, *[n]E, or []E index i int a[i] E string s string type index i int see below rune map m map[K]V key k K m[k] V -channel c chan E element e E +channel c chan E, <-chan E element e E </pre> <ol> <li> For an array, pointer to array, or slice value <code>a</code>, the index iteration -values are produced in increasing order, starting at element index 0. As a special -case, if only the first iteration variable is present, the range loop produces +values are produced in increasing order, starting at element index 0. +If only the first iteration variable is present, the range loop produces iteration values from 0 up to <code>len(a)</code> and does not index into the array or slice itself. For a <code>nil</code> slice, the number of iterations is 0. </li> @@ -4260,11 +4424,12 @@ a single byte in the string. <li> The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next. -If map entries that have not yet been reached are deleted during iteration, +If map entries that have not yet been reached are removed during iteration, the corresponding iteration values will not be produced. If map entries are -inserted during iteration, the behavior is implementation-dependent, but the -iteration values for each entry will be produced at most once. If the map -is <code>nil</code>, the number of iterations is 0. +created during iteration, that entry may be produced during the iteration or +may be skipped. The choice may vary for each entry created and from one +iteration to the next. +If the map is <code>nil</code>, the number of iterations is 0. </li> <li> @@ -4327,7 +4492,7 @@ for w := range ch { <h3 id="Go_statements">Go statements</h3> <p> -A "go" statement starts the execution of a function or method call +A "go" statement starts the execution of a function call as an independent concurrent thread of control, or <i>goroutine</i>, within the same address space. </p> @@ -4337,7 +4502,12 @@ GoStmt = "go" Expression . </pre> <p> -The expression must be a call. +The expression must be a function or method call; it cannot be parenthesized. +Calls of built-in functions are restricted as for +<a href="#Expression_statements">expression statements</a>. +</p> + +<p> The function value and parameters are <a href="#Calls">evaluated as usual</a> in the calling goroutine, but @@ -4368,7 +4538,7 @@ cases all referring to communication operations. SelectStmt = "select" "{" { CommClause } "}" . CommClause = CommCase ":" { Statement ";" } . CommCase = "case" ( SendStmt | RecvStmt ) | "default" . -RecvStmt = [ Expression [ "," Expression ] ( "=" | ":=" ) ] RecvExpr . +RecvStmt = [ ExpressionList "=" | IdentifierList ":=" ] RecvExpr . RecvExpr = Expression . </pre> @@ -4385,7 +4555,8 @@ If any of the resulting operations can proceed, one of those is chosen and the corresponding communication and statements are evaluated. Otherwise, if there is a default case, that executes; if there is no default case, the statement blocks until one of the communications can -complete. +complete. There can be at most one default case and it may appear anywhere in the +"select" statement. If there are no cases with non-<code>nil</code> channels, the statement blocks forever. Even if the statement blocks, @@ -4437,8 +4608,10 @@ select {} // block forever <h3 id="Return_statements">Return statements</h3> <p> -A "return" statement terminates execution of the containing function -and optionally provides a result value or values to the caller. +A "return" statement in a function <code>F</code> terminates the execution +of <code>F</code>, and optionally provides one or more result values. +Any functions <a href="#Defer_statements">deferred</a> by <code>F</code> +are executed before <code>F</code> returns to its caller. </p> <pre class="ebnf"> @@ -4488,7 +4661,7 @@ func complexF2() (re float64, im float64) { </pre> </li> <li>The expression list may be empty if the function's result - type specifies names for its result parameters (§<a href="#Function_types">Function Types</a>). + type specifies names for its result parameters (§<a href="#Function_types">Function types</a>). The result parameters act as ordinary local variables and the function may assign values to them as necessary. The "return" statement returns the values of these variables. @@ -4508,7 +4681,10 @@ func (devnull) Write(p []byte) (n int, _ error) { </ol> <p> -Regardless of how they are declared, all the result values are initialized to the zero values for their type (§<a href="#The_zero_value">The zero value</a>) upon entry to the function. +Regardless of how they are declared, all the result values are initialized to the zero +values for their type (§<a href="#The_zero_value">The zero value</a>) upon entry to the +function. A "return" statement that specifies results sets the result parameters before +any deferred functions are executed. </p> <!-- @@ -4534,7 +4710,8 @@ BreakStmt = "break" [ Label ] . If there is a label, it must be that of an enclosing "for", "switch" or "select" statement, and that is the one whose execution terminates -(§<a href="#For_statements">For statements</a>, §<a href="#Switch_statements">Switch statements</a>, §<a href="#Select_statements">Select statements</a>). +(§<a href="#For_statements">For statements</a>, §<a href="#Switch_statements">Switch statements</a>, +§<a href="#Select_statements">Select statements</a>). </p> <pre> @@ -4623,9 +4800,8 @@ the "for" statement's block but the <code>goto</code> is not. <p> A "fallthrough" statement transfers control to the first statement of the -next case clause in a expression "switch" statement (§<a href="#Expression_switches">Expression switches</a>). It may -be used only as the final non-empty statement in a case or default clause in an -expression "switch" statement. +next case clause in a <a href="#Expression_switches">expression "switch" statement</a>. +It may be used only as the final non-empty statement in such a clause. </p> <pre class="ebnf"> @@ -4636,8 +4812,11 @@ FallthroughStmt = "fallthrough" . <h3 id="Defer_statements">Defer statements</h3> <p> -A "defer" statement invokes a function whose execution is deferred to the moment -the surrounding function returns. +A "defer" statement invokes a function whose execution is deferred +to the moment the surrounding function returns, either because the +surrounding function executed a <a href="#Return_statements">return statement</a>, +reached the end of its <a href="#Function_declarations">function body</a>, +or because the corresponding goroutine is <a href="#Handling_panics">panicking</a>. </p> <pre class="ebnf"> @@ -4645,22 +4824,30 @@ DeferStmt = "defer" Expression . </pre> <p> -The expression must be a function or method call. +The expression must be a function or method call; it cannot be parenthesized. +Calls of built-in functions are restricted as for +<a href="#Expression_statements">expression statements</a>. +</p> + +<p> Each time the "defer" statement executes, the function value and parameters to the call are <a href="#Calls">evaluated as usual</a> -and saved anew but the -actual function is not invoked. -Instead, deferred calls are executed in LIFO order -immediately before the surrounding function returns, -after the return values, if any, have been evaluated, but before they -are returned to the caller. For instance, if the deferred function is +and saved anew but the actual function body is not executed. +Instead, deferred functions are executed immediately before +the surrounding function returns, in the reverse order +they were deferred. +</p> + +<p> +For instance, if the deferred function is a <a href="#Function_literals">function literal</a> and the surrounding function has <a href="#Function_types">named result parameters</a> that are in scope within the literal, the deferred function may access and modify the result parameters before they are returned. If the deferred function has any return values, they are discarded when the function completes. +(See also the section on <a href="#Handling_panics">handling panics</a>.) </p> <pre> @@ -4698,7 +4885,7 @@ they cannot be used as function values. <pre class="ebnf"> BuiltinCall = identifier "(" [ BuiltinArgs [ "," ] ] ")" . -BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList . +BuiltinArgs = Type [ "," ArgumentList ] | ArgumentList . </pre> <h3 id="Close">Close</h3> @@ -4750,7 +4937,8 @@ At any time the following relationship holds: </pre> <p> -The length and capacity of a <code>nil</code> slice, map, or channel are 0. +The length of a <code>nil</code> slice, map or channel is 0. +The capacity of a <code>nil</code> slice and channel is 0. </p> <p> @@ -4822,15 +5010,20 @@ make(T, n) channel asynchronous channel of type T, buffer size n <p> -The arguments <code>n</code> and <code>m</code> must be of integer type. -A <a href="#Run_time_panics">run-time panic</a> occurs if <code>n</code> -is negative or larger than <code>m</code>, or if <code>n</code> or -<code>m</code> cannot be represented by an <code>int</code>. +The size arguments <code>n</code> and <code>m</code> must be integer values. +A <a href="#Constants">constant</a> size argument must be non-negative and +representable by a value of type <code>int</code>. +If both <code>n</code> and <code>m</code> are provided and are constant, then +<code>n</code> must be no larger than <code>m</code>. +If <code>n</code> is negative or larger than <code>m</code> at run time, +a <a href="#Run_time_panics">run-time panic</a> occurs. </p> <pre> s := make([]int, 10, 100) // slice with len(s) == 10, cap(s) == 100 -s := make([]int, 10) // slice with len(s) == cap(s) == 10 +s := make([]int, 1e3) // slice with len(s) == cap(s) == 1000 +s := make([]int, 1<<63) // illegal: len(s) is not representable by a value of type int +s := make([]int, 10, 0) // illegal: len(s) > cap(s) c := make(chan int, 10) // channel with a buffer size of 10 m := make(map[string]int, 100) // map with initial space for 100 elements </pre> @@ -4839,7 +5032,10 @@ m := make(map[string]int, 100) // map with initial space for 100 elements <h3 id="Appending_and_copying_slices">Appending to and copying slices</h3> <p> -Two built-in functions assist in common slice operations. +The built-in functions <code>append</code> and <code>copy</code> assist in +common slice operations. +For both functions, the result is independent of whether the memory referenced +by the arguments overlaps. </p> <p> @@ -4870,21 +5066,22 @@ slice may refer to a different underlying array. <pre> s0 := []int{0, 0} -s1 := append(s0, 2) // append a single element s1 == []int{0, 0, 2} -s2 := append(s1, 3, 5, 7) // append multiple elements s2 == []int{0, 0, 2, 3, 5, 7} -s3 := append(s2, s0...) // append a slice s3 == []int{0, 0, 2, 3, 5, 7, 0, 0} +s1 := append(s0, 2) // append a single element s1 == []int{0, 0, 2} +s2 := append(s1, 3, 5, 7) // append multiple elements s2 == []int{0, 0, 2, 3, 5, 7} +s3 := append(s2, s0...) // append a slice s3 == []int{0, 0, 2, 3, 5, 7, 0, 0} +s4 := append(s3[3:6], s3[2:]...) // append overlapping slice s4 == []int{3, 5, 7, 2, 3, 5, 7, 0, 0} var t []interface{} -t = append(t, 42, 3.1415, "foo") t == []interface{}{42, 3.1415, "foo"} +t = append(t, 42, 3.1415, "foo") t == []interface{}{42, 3.1415, "foo"} var b []byte -b = append(b, "bar"...) // append string contents b == []byte{'b', 'a', 'r' } +b = append(b, "bar"...) // append string contents b == []byte{'b', 'a', 'r' } </pre> <p> The function <code>copy</code> copies slice elements from a source <code>src</code> to a destination <code>dst</code> and returns the -number of elements copied. Source and destination may overlap. +number of elements copied. Both arguments must have <a href="#Type_identity">identical</a> element type <code>T</code> and must be <a href="#Assignability">assignable</a> to a slice of type <code>[]T</code>. The number of elements copied is the minimum of @@ -4927,9 +5124,8 @@ delete(m, k) // remove element m[k] from map m </pre> <p> -If the element <code>m[k]</code> does not exist, <code>delete</code> is -a no-op. Calling <code>delete</code> with a nil map causes a -<a href="#Run_time_panics">run-time panic</a>. +If the map <code>m</code> is <code>nil</code> or the element <code>m[k]</code> +does not exist, <code>delete</code> is a no-op. </p> @@ -4988,18 +5184,16 @@ func recover() interface{} </pre> <p> -When a function <code>F</code> calls <code>panic</code>, normal -execution of <code>F</code> stops immediately. Any functions whose -execution was <a href="#Defer_statements">deferred</a> by the -invocation of <code>F</code> are run in the usual way, and then -<code>F</code> returns to its caller. To the caller, <code>F</code> -then behaves like a call to <code>panic</code>, terminating its own -execution and running deferred functions. This continues until all -functions in the goroutine have ceased execution, in reverse order. -At that point, the program is -terminated and the error condition is reported, including the value of -the argument to <code>panic</code>. This termination sequence is -called <i>panicking</i>. +A <code>panic</code> call in a function <code>F</code> terminates the execution +of <code>F</code>. +Any functions <a href="#Defer_statements">deferred</a> by <code>F</code> +are executed before <code>F</code> returns to its caller. To the caller, +the call of <code>F</code> then behaves itself like a call to <code>panic</code>, +terminating its own execution and running deferred functions in the same manner. +This continues until all functions in the goroutine have ceased execution, +in reverse order. At that point, the program is terminated and the error +condition is reported, including the value of the argument to <code>panic</code>. +This termination sequence is called <i>panicking</i>. </p> <pre> @@ -5112,7 +5306,7 @@ An implementation may require that all source files for a package inhabit the sa An import declaration states that the source file containing the declaration depends on functionality of the <i>imported</i> package (<a href="#Program_initialization_and_execution">§Program initialization and execution</a>) -and it enables access to <a href="#Exported_identifiers">exported</a> identifiers +and enables access to <a href="#Exported_identifiers">exported</a> identifiers of that package. The import names an identifier (PackageName) to be used for access and an ImportPath that specifies the package to be imported. @@ -5145,7 +5339,7 @@ package and may be relative to a repository of installed packages. <p> Implementation restriction: A compiler may restrict ImportPaths to non-empty strings using only characters belonging to -<a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode's</a> +<a href="http://www.unicode.org/versions/Unicode6.2.0/">Unicode's</a> L, M, N, P, and S general categories (the Graphic characters without spaces) and may also exclude the characters <code>!"#$%&'()*,:;<=>?[\]^`{|}</code> @@ -5166,7 +5360,7 @@ various types of import declaration. Import declaration Local name of Sin import "lib/math" math.Sin -import M "lib/math" M.Sin +import m "lib/math" m.Sin import . "lib/math" Sin </pre> @@ -5292,8 +5486,10 @@ func init() </pre> <p> defined in its source. -A package may contain multiple -<code>init</code> functions, even +A package-scope or file-scope identifier +with name <code>init</code> may only be +declared to be a function with this signature. +Multiple such functions may be defined, even within a single source file; they execute in unspecified order. </p> @@ -5430,16 +5626,26 @@ func Sizeof(variable ArbitraryType) uintptr </pre> <p> -Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted into -a <code>Pointer</code> and vice versa. +Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted to +a <code>Pointer</code> type and vice versa. </p> + +<pre> +var f float64 +bits = *(*uint64)(unsafe.Pointer(&f)) + +type ptr unsafe.Pointer +bits = *(*uint64)(ptr(&f)) +</pre> + <p> -The function <code>Sizeof</code> takes an expression denoting a -variable of any type and returns the size of the variable in bytes. +The functions <code>Alignof</code> and <code>Sizeof</code> take an expression <code>x</code> +of any type and return the alignment or size, respectively, of a hypothetical variable <code>v</code> +as if <code>v</code> was declared via <code>var v = x</code>. </p> <p> -The function <code>Offsetof</code> takes a selector (§<a href="#Selectors">Selectors</a>) denoting a struct -field of any type and returns the field offset in bytes relative to the +The function <code>Offsetof</code> takes a (possibly parenthesized) <a href="#Selectors">selector</a> +denoting a struct field of any type and returns the field offset in bytes relative to the struct's address. For a struct <code>s</code> with field <code>f</code>: </p> @@ -5465,7 +5671,6 @@ uintptr(unsafe.Pointer(&x)) % unsafe.Alignof(x) == 0 Calls to <code>Alignof</code>, <code>Offsetof</code>, and <code>Sizeof</code> are compile-time constant expressions of type <code>uintptr</code>. </p> -<p> <h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3> diff --git a/doc/godocs.js b/doc/godocs.js index 8fd32fef0..5d12da131 100644 --- a/doc/godocs.js +++ b/doc/godocs.js @@ -1,213 +1,195 @@ -// Except as noted, this content is licensed under Creative Commons -// Attribution 3.0 +// Copyright 2012 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. /* A little code to ease navigation of these documents. * * On window load we: - * + Generate a table of contents (godocs_generateTOC) - * + Add links up to the top of the doc from each section (godocs_addTopLinks) + * + Bind search box hint placeholder show/hide events (bindSearchEvents) + * + Generate a table of contents (generateTOC) + * + Bind foldable sections (bindToggles) + * + Bind links to foldable sections (bindToggleLinks) */ -/* We want to do some stuff on page load (after the HTML is rendered). - So listen for that: - */ -function bindEvent(el, e, fn) { - if (el.addEventListener){ - el.addEventListener(e, fn, false); - } else if (el.attachEvent){ - el.attachEvent('on'+e, fn); - } -} +(function() { +'use strict'; -function godocs_bindSearchEvents() { - var search = document.getElementById('search'); - if (!search) { - // no search box (index disabled) - return; +function bindSearchEvents() { + + var search = $('#search'); + if (search.length === 0) { + return; // no search box } + function clearInactive() { - if (search.className == "inactive") { - search.value = ""; - search.className = ""; + if (search.is('.inactive')) { + search.val(''); + search.removeClass('inactive'); } } + function restoreInactive() { - if (search.value !== "") { + if (search.val() !== '') { return; } - if (search.type != "search") { - search.value = search.getAttribute("placeholder"); - } - search.className = "inactive"; + search.val(search.attr('placeholder')); + search.addClass('inactive'); } + + search.on('focus', clearInactive); + search.on('blur', restoreInactive); + restoreInactive(); - bindEvent(search, 'focus', clearInactive); - bindEvent(search, 'blur', restoreInactive); } -/* Returns the "This sweet header" from <h2>This <i>sweet</i> header</h2>. - * Takes a node, returns a string. +/* Generates a table of contents: looks for h2 and h3 elements and generates + * links. "Decorates" the element with id=="nav" with this table of contents. */ -function godocs_nodeToText(node) { - var TEXT_NODE = 3; // Defined in Mozilla but not MSIE :( - - var text = ''; - for (var j = 0; j != node.childNodes.length; j++) { - var child = node.childNodes[j]; - if (child.nodeType == TEXT_NODE) { - if (child.nodeValue != '[Top]') { //ok, that's a hack, but it works. - text = text + child.nodeValue; - } - } else { - text = text + godocs_nodeToText(child); - } +function generateTOC() { + if ($('#manual-nav').length > 0) { + return; } - return text; -} -/* Generates a table of contents: looks for h2 and h3 elements and generates - * links. "Decorates" the element with id=="nav" with this table of contents. - */ -function godocs_generateTOC() { - if (document.getElementById('manual-nav')) { return; } - var navbar = document.getElementById('nav'); - if (!navbar) { return; } + var nav = $('#nav'); + if (nav.length === 0) { + return; + } var toc_items = []; - - var i; - var seenNav = false; - for (i = 0; i < navbar.parentNode.childNodes.length; i++) { - var node = navbar.parentNode.childNodes[i]; - if (!seenNav) { - if (node.id == 'nav') { - seenNav = true; - } - continue; - } - if ((node.tagName != 'h2') && (node.tagName != 'H2') && - (node.tagName != 'h3') && (node.tagName != 'H3')) { - continue; - } - if (!node.id) { - node.id = 'tmp_' + i; - } - var text = godocs_nodeToText(node); - if (!text) { continue; } - - var textNode = document.createTextNode(text); - - var link = document.createElement('a'); - link.href = '#' + node.id; - link.appendChild(textNode); - - // Then create the item itself + $(nav).nextAll('h2, h3').each(function() { + var node = this; + if (node.id == '') + node.id = 'tmp_' + toc_items.length; + var link = $('<a/>').attr('href', '#' + node.id).text($(node).text()); var item; - if ((node.tagName == 'h2') || (node.tagName == 'H2')) { - item = document.createElement('dt'); + if ($(node).is('h2')) { + item = $('<dt/>'); } else { // h3 - item = document.createElement('dd'); + item = $('<dd/>'); } - - item.appendChild(link); + item.append(link); toc_items.push(item); + }); + if (toc_items.length <= 1) { + return; } - if (toc_items.length <= 1) { return; } - - var dl1 = document.createElement('dl'); - var dl2 = document.createElement('dl'); + var dl1 = $('<dl/>'); + var dl2 = $('<dl/>'); var split_index = (toc_items.length / 2) + 1; if (split_index < 8) { split_index = toc_items.length; } - - for (i = 0; i < split_index; i++) { - dl1.appendChild(toc_items[i]); + for (var i = 0; i < split_index; i++) { + dl1.append(toc_items[i]); } for (/* keep using i */; i < toc_items.length; i++) { - dl2.appendChild(toc_items[i]); + dl2.append(toc_items[i]); } - var tocTable = document.createElement('table'); - navbar.appendChild(tocTable); - tocTable.className = 'unruled'; - var tocBody = document.createElement('tbody'); - tocTable.appendChild(tocBody); - - var tocRow = document.createElement('tr'); - tocBody.appendChild(tocRow); + var tocTable = $('<table class="unruled"/>').appendTo(nav); + var tocBody = $('<tbody/>').appendTo(tocTable); + var tocRow = $('<tr/>').appendTo(tocBody); // 1st column - var tocCell = document.createElement('td'); - tocCell.className = 'first'; - tocRow.appendChild(tocCell); - tocCell.appendChild(dl1); - + $('<td class="first"/>').appendTo(tocRow).append(dl1); // 2nd column - tocCell = document.createElement('td'); - tocRow.appendChild(tocCell); - tocCell.appendChild(dl2); -} - -function getElementsByClassName(base, clazz) { - if (base.getElementsByClassName) { - return base.getElementsByClassName(clazz); - } - var elements = base.getElementsByTagName('*'), foundElements = []; - for (var n in elements) { - if (clazz == elements[n].className) { - foundElements.push(elements[n]); - } - } - return foundElements; + $('<td/>').appendTo(tocRow).append(dl2); } -function godocs_bindToggle(el) { - var button = getElementsByClassName(el, "toggleButton"); - var callback = function() { - if (el.className == "toggle") { - el.className = "toggleVisible"; +function bindToggle(el) { + $('.toggleButton', el).click(function() { + if ($(el).is('.toggle')) { + $(el).addClass('toggleVisible').removeClass('toggle'); } else { - el.className = "toggle"; + $(el).addClass('toggle').removeClass('toggleVisible'); } - }; - for (var i = 0; i < button.length; i++) { - bindEvent(button[i], "click", callback); - } + }); } -function godocs_bindToggles(className) { - var els = getElementsByClassName(document, className); - for (var i = 0; i < els.length; i++) { - godocs_bindToggle(els[i]); - } +function bindToggles(selector) { + $(selector).each(function(i, el) { + bindToggle(el); + }); } -function godocs_bindToggleLink(l, prefix) { - bindEvent(l, "click", function() { - var i = l.href.indexOf("#"+prefix); + +function bindToggleLink(el, prefix) { + $(el).click(function() { + var href = $(el).attr('href'); + var i = href.indexOf('#'+prefix); if (i < 0) { return; } - var id = prefix + l.href.slice(i+1+prefix.length); - var eg = document.getElementById(id); - eg.className = "toggleVisible"; + var id = '#' + prefix + href.slice(i+1+prefix.length); + if ($(id).is('.toggle')) { + $(id).find('.toggleButton').first().click(); + } }); } -function godocs_bindToggleLinks(className, prefix) { - var links = getElementsByClassName(document, className); - for (i = 0; i < links.length; i++) { - godocs_bindToggleLink(links[i], prefix); +function bindToggleLinks(selector, prefix) { + $(selector).each(function(i, el) { + bindToggleLink(el, prefix); + }); +} + +function setupDropdownPlayground() { + if (!$('#page').is('.wide')) { + return; // don't show on front page } + var button = $('#playgroundButton'); + var div = $('#playground'); + var setup = false; + button.toggle(function() { + button.addClass('active'); + div.show(); + if (setup) { + return; + } + setup = true; + playground({ + 'codeEl': $('.code', div), + 'outputEl': $('.output', div), + 'runEl': $('.run', div), + 'fmtEl': $('.fmt', div), + 'shareEl': $('.share', div), + 'shareRedirect': 'http://play.golang.org/p/' + }); + }, + function() { + button.removeClass('active'); + div.hide(); + }); + button.show(); + $('#menu').css('min-width', '+=60'); } -function godocs_onload() { - godocs_bindSearchEvents(); - godocs_generateTOC(); - godocs_bindToggles("toggle"); - godocs_bindToggles("toggleVisible"); - godocs_bindToggleLinks("exampleLink", "example_"); - godocs_bindToggleLinks("overviewLink", ""); +// fixFocus tries to put focus to div#page so that keyboard navigation works. +function fixFocus() { + var page = $('div#page'); + var topbar = $('div#topbar'); + page.css('outline', 0); // disable outline when focused + page.attr('tabindex', -1); // and set tabindex so that it is focusable + $(window).resize(function (evt) { + // only focus page when the topbar is at fixed position (that is, it's in + // front of page, and keyboard event will go to the former by default.) + // by focusing page, keyboard event will go to page so that up/down arrow, + // space, etc. will work as expected. + if (topbar.css('position') == "fixed") + page.focus(); + }).resize(); } -bindEvent(window, 'load', godocs_onload); +$(document).ready(function() { + bindSearchEvents(); + generateTOC(); + bindToggles(".toggle"); + bindToggles(".toggleVisible"); + bindToggleLinks(".exampleLink", "example_"); + bindToggleLinks(".overviewLink", ""); + bindToggleLinks(".examplesLink", ""); + bindToggleLinks(".indexLink", ""); + setupDropdownPlayground(); + fixFocus(); +}); + +})(); diff --git a/doc/gopher/pencil/gopherhat.jpg b/doc/gopher/pencil/gopherhat.jpg Binary files differnew file mode 100644 index 000000000..f34d7b325 --- /dev/null +++ b/doc/gopher/pencil/gopherhat.jpg diff --git a/doc/gopher/pencil/gopherhelmet.jpg b/doc/gopher/pencil/gopherhelmet.jpg Binary files differnew file mode 100644 index 000000000..c7b6c61b2 --- /dev/null +++ b/doc/gopher/pencil/gopherhelmet.jpg diff --git a/doc/gopher/pencil/gophermega.jpg b/doc/gopher/pencil/gophermega.jpg Binary files differnew file mode 100644 index 000000000..779fb073a --- /dev/null +++ b/doc/gopher/pencil/gophermega.jpg diff --git a/doc/gopher/pencil/gopherrunning.jpg b/doc/gopher/pencil/gopherrunning.jpg Binary files differnew file mode 100644 index 000000000..eeeddf106 --- /dev/null +++ b/doc/gopher/pencil/gopherrunning.jpg diff --git a/doc/gopher/pencil/gopherswim.jpg b/doc/gopher/pencil/gopherswim.jpg Binary files differnew file mode 100644 index 000000000..2f3287712 --- /dev/null +++ b/doc/gopher/pencil/gopherswim.jpg diff --git a/doc/gopher/pencil/gopherswrench.jpg b/doc/gopher/pencil/gopherswrench.jpg Binary files differnew file mode 100644 index 000000000..93005f42a --- /dev/null +++ b/doc/gopher/pencil/gopherswrench.jpg diff --git a/doc/help.html b/doc/help.html index fadf80a03..3478b9e60 100644 --- a/doc/help.html +++ b/doc/help.html @@ -28,11 +28,17 @@ archives and consult the <a href="/doc/go_faq.html">FAQ</a> and <p>Get live support at <b>#go-nuts</b> on <b>irc.freenode.net</b>, the official Go IRC channel.</p> +<h3 id="pluscom"><a href="https://plus.google.com/communities/114112804251407510571">The Go+ community</a></h3> +<p>The Google+ community for Go enthusiasts.</p> + +<h3 id="plus"><a href="https://plus.google.com/101406623878176903605/posts">The Go Programming Language at Google+</a></h3> +<p>The Go project's Google+ page.</p> + <h3 id="twitter"><a href="http://twitter.com/go_nuts">@go_nuts at Twitter</a></h3> <p>The Go project's official Twitter account.</p> <p>Tweeting your about problem with the <code>#golang</code> hashtag usually generates some helpful responses.</p> -<h3 id="plus"><a href="https://plus.google.com/101406623878176903605/posts">The Go Programming Language at Google+</a></h3> -<p>The Go project's Google+ page.</p> - +<h3 id="blog"><a href="http://blog.golang.org/">The Go Blog</a></h3> +<p>The official blog of the Go project, featuring news and in-depth articles by +the Go team and guests.</p> diff --git a/doc/install-source.html b/doc/install-source.html index 87c187ba8..ee7b39b7e 100644 --- a/doc/install-source.html +++ b/doc/install-source.html @@ -57,8 +57,7 @@ architectures. <code>arm</code> (a.k.a. <code>ARM</code>); <code>5g,5l,5c,5a</code> </dt> <dd> - Supports only Linux binaries. Less widely used than the other ports and therefore - not as thoroughly tested. + Supports only Linux binaries. Less widely used than the other ports and therefore not as thoroughly tested. </dd> </dl> @@ -81,25 +80,9 @@ The full set of supported combinations is listed in the discussion of <h2 id="ctools">Install C tools, if needed</h2> <p> -The Go tool chain is written in C. -To build it, you need a C compiler installed. -</p> - -<p> -On OS X, a C compiler can be installed as part of -<a href="http://developer.apple.com/Xcode/">Xcode</a>. -</p> - -<p> -On Ubuntu/Debian, use <code>sudo apt-get install gcc libc6-dev</code>. -If you want to build 32-bit binaries on a 64-bit system you'll also need the -<code>libc6-dev-i386</code> package. -</p> - -<p> -On Windows, install <code>gcc</code> with -<a href="http://www.mingw.org/">MinGW</a>. -(Make sure you add its <code>bin</code> subdirectory to your <code>PATH</code>.) +The Go tool chain is written in C. To build it, you need a C compiler installed. +Please refer to the <a href="http://code.google.com/p/go-wiki/wiki/InstallFromSource#Install_C_tools">InstallFromSource</a> +page on the Go community Wiki for operating system specific instructions. </p> <h2 id="mercurial">Install Mercurial, if needed</h2> @@ -144,6 +127,18 @@ Then check out the repository:</p> $ hg clone -u release https://code.google.com/p/go </pre> +<h2 id="head">(Optional) Switch to the default branch</h2> + +<p>If you intend to modify the go source code, and +<a href="/doc/contribute.html">contribute your changes</a> +to the project, then move your repository +off the release branch, and onto the default (development) branch. +Otherwise, skip this step.</p> + +<pre> +$ hg update default +</pre> + <h2 id="install">Install Go</h2> <p> @@ -218,6 +213,12 @@ hello, world If you see the "hello, world" message then Go is installed correctly. </p> +<h2 id="gopath">Set up your work environment</h2> + +<p> +The document <a href="/doc/code.html">How to Write Go Code</a> explains how to +set up a work environment in which to build and test Go code. +</p> <h2 id="community">Community resources</h2> @@ -241,8 +242,8 @@ Bugs can be reported using the <a href="http://code.google.com/p/go/issues/list" <h2 id="releases">Keeping up with releases</h2> <p> -The Go project maintains two stable tags in its Mercurial repository: -<code>release</code> and <code>weekly</code>. +The Go project maintains a stable tag in its Mercurial repository: +<code>release</code>. </p> <p> @@ -263,12 +264,6 @@ $ hg update release $ ./all.bash </pre> -<p> -The <code>weekly</code> tag is updated about once a week, and should be used -only by those who are actively working on the Go core. -To use the <code>weekly</code> tag run <code>hg update weekly</code> instead. -</p> - <h2 id="environment">Optional environment variables</h2> diff --git a/doc/install.html b/doc/install.html index b856836ff..03b13c018 100644 --- a/doc/install.html +++ b/doc/install.html @@ -40,14 +40,20 @@ proceeding. If your OS or architecture is not on the list, it's possible that <th align="middle">Notes</th> </tr> <tr><td colspan="3"><hr></td></tr> -<tr><td>FreeBSD 7 or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr> -<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; no binary distribution for ARM yet</tr> -<tr><td>Mac OS X 10.6/10.7</td> <td>amd64, 386</td> <td>use the gcc<sup>†</sup> that comes with Xcode</td></tr> +<tr><td>FreeBSD 7 or later</td> <td>amd64, 386, arm</td> <td>Debian GNU/kFreeBSD not supported; FreeBSD/ARM needs FreeBSD 10 or later</td></tr> +<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; no binary distribution for ARM yet</td></tr> +<tr><td>Mac OS X 10.6/10.7</td> <td>amd64, 386</td> <td>use the gcc<sup>†</sup> that comes with Xcode<sup>‡</sup></td></tr> <tr><td>Windows 2000 or later</td> <td>amd64, 386</td> <td>use mingw gcc<sup>†</sup>; cygwin or msys is not needed</td></tr> +<tr><td>NetBSD 6 or later</td> <td>amd64, 386</td> <td></td></tr> </table> <p> -<sup>†</sup><code>gcc</code> is required only if you plan to use <a href="/cmd/cgo">cgo</a>. +<sup>†</sup><code>gcc</code> is required only if you plan to use +<a href="/cmd/cgo">cgo</a>.<br/> +<sup>‡</sup>You only need to install the command line tools for +<a href="http://developer.apple.com/Xcode/">Xcode</a>. If you have already +installed Xcode 4.3+, you can install it from the Components tab of the +Downloads preferences panel. </p> <h2 id="download">Download the Go tools</h2> @@ -61,7 +67,7 @@ your operating system and processor architecture. <p> Official binary distributions are available -for the FreeBSD, Linux, Mac OS X (Snow Leopard/Lion), and Windows operating systems +for the FreeBSD, Linux, Mac OS X (Snow Leopard/Lion), NetBSD, and Windows operating systems and the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>) x86 processor architectures. </p> @@ -98,10 +104,10 @@ Windows users should read the section about <a href="#windows_env">setting environment variables under Windows</a>. </p> -<h3 id="freebsd_linux">FreeBSD and Linux</h3> +<h3 id="bsd_linux">FreeBSD, Linux, Mac OS X and NetBSD tarballs</h3> <p> -On FreeBSD and Linux, if you are upgrading from an older version of Go you must +If you are upgrading from an older version of Go you must first remove the existing version from <code>/usr/local/go</code>: </p> @@ -110,15 +116,21 @@ rm -r /usr/local/go </pre> <p> -Extract <a href="http://code.google.com/p/go/downloads/list?q=OpSys-FreeBSD+OR+OpSys-Linux">the archive</a> -into <code>/usr/local</code>, creating a Go tree in <code>/usr/local/go</code>: +Extract <a href="http://code.google.com/p/go/downloads/list?q=OpSys-FreeBSD+OR+OpSys-Linux+OR+OpSys-OSX+OR+OpSys-NetBSD+Type-Archive">the archive</a> +into <code>/usr/local</code>, creating a Go tree in <code>/usr/local/go</code>. +For example: </p> <pre> -tar -C /usr/local -xzf go.release.go1.tar.gz +tar -C /usr/local -xzf go1.0.3.linux-amd64.tar.gz </pre> <p> +The name of the archive may differ, depending on the version of Go you are +installing and your system's operating system and processor architecture. +</p> + +<p> (Typically these commands must be run as root or through <code>sudo</code>.) </p> @@ -132,10 +144,10 @@ variable. You can do this by adding this line to your <code>/etc/profile</code> export PATH=$PATH:/usr/local/go/bin </pre> -<h3 id="osx">Mac OS X</h3> +<h3 id="osx">Mac OS X package installer</h3> <p> -Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Darwin">package file</a> +Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-OSX+Type-Installer">package file</a> and follow the prompts to install the Go tools. The package installs the Go distribution to <code>/usr/local/go</code>. </p> @@ -155,7 +167,7 @@ a zip archive that requires you to set some environment variables and an experimental MSI installer that configures your installation automatically. </p> -<h4 id="windows_zip">Zip archive</h3> +<h4 id="windows_zip">Zip archive</h4> <p> Extract the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Windows+Type%3DArchive">zip file</a> @@ -171,7 +183,7 @@ the <code>GOROOT</code> environment variable to your chosen path. Add the <code>bin</code> subdirectory of your Go root (for example, <code>c:\Go\bin</code>) to to your <code>PATH</code> environment variable. </p> -<h4 id="windows_msi">MSI installer (experimental)</h3> +<h4 id="windows_msi">MSI installer (experimental)</h4> <p> Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Windows+Type%3DInstaller">MSI file</a> @@ -227,15 +239,17 @@ hello, world If you see the "hello, world" message then your Go installation is working. </p> -<h2 id="next">What's next</h2> +<h2 id="gopath">Set up your work environment</h2> <p> -Start by taking <a href="http://code.google.com/p/go-tour/">A Tour of Go</a>. +The document <a href="/doc/code.html">How to Write Go Code</a> explains how to +set up a work environment in which to build and test Go code. </p> +<h2 id="next">What's next</h2> + <p> -For more detail about the process of building and testing Go programs -read <a href="/doc/code.html">How to Write Go Code</a>. +Start by taking <a href="http://code.google.com/p/go-tour/">A Tour of Go</a>. </p> <p> diff --git a/doc/jquery.js b/doc/jquery.js new file mode 100644 index 000000000..bc3fbc81b --- /dev/null +++ b/doc/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(" ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);
\ No newline at end of file diff --git a/doc/play/fib.go b/doc/play/fib.go index 42da9ce82..19e472102 100644 --- a/doc/play/fib.go +++ b/doc/play/fib.go @@ -1,5 +1,7 @@ package main +import "fmt" + // fib returns a function that returns // successive Fibonacci numbers. func fib() func() int { @@ -13,5 +15,5 @@ func fib() func() int { func main() { f := fib() // Function calls are evaluated left-to-right. - println(f(), f(), f(), f(), f()) + fmt.Println(f(), f(), f(), f(), f()) } diff --git a/doc/play/playground.js b/doc/play/playground.js index d7cc58d6e..709136627 100644 --- a/doc/play/playground.js +++ b/doc/play/playground.js @@ -3,23 +3,19 @@ // license that can be found in the LICENSE file. // opts is an object with these keys -// codeEl - code editor element -// outputEl - program output element -// runEl - run button element -// fmtEl - fmt button element (optional) -// shareEl - share button element (optional) -// shareURLEl - share URL text input element (optional) -// shareRedirect - base URL to redirect to on share (optional) -// preCompile - callback to mutate request data before compiling (optional) -// postCompile - callback to read response data after compiling (optional) -// simple - use plain textarea instead of CodeMirror. (optional) -// toysEl - select element with a list of toys. (optional) +// codeEl - code editor element +// outputEl - program output element +// runEl - run button element +// fmtEl - fmt button element (optional) +// shareEl - share button element (optional) +// shareURLEl - share URL text input element (optional) +// shareRedirect - base URL to redirect to on share (optional) +// toysEl - toys select element (optional) +// enableHistory - enable using HTML5 history API (optional) function playground(opts) { - var simple = opts['simple']; var code = $(opts['codeEl']); - var editor; - // autoindent helpers for simple mode. + // autoindent helpers. function insertTabs(n) { // find the selection start and end var start = code[0].selectionStart; @@ -49,12 +45,12 @@ function playground(opts) { } } setTimeout(function() { - insertTabs(tabs, 1); + insertTabs(tabs); }, 1); } function keyHandler(e) { - if (simple && e.keyCode == 9) { // tab + if (e.keyCode == 9) { // tab insertTabs(1); e.preventDefault(); return false; @@ -64,58 +60,19 @@ function playground(opts) { run(); e.preventDefault(); return false; - } else if (simple) { + } else { autoindent(e.target); } } return true; } - if (simple) { - code.unbind('keydown').bind('keydown', keyHandler); - } else { - editor = CodeMirror.fromTextArea( - code[0], - { - lineNumbers: true, - indentUnit: 8, - indentWithTabs: true, - onKeyEvent: function(editor, e) { keyHandler(e); } - } - ); - } + code.unbind('keydown').bind('keydown', keyHandler); var output = $(opts['outputEl']); - function clearErrors() { - if (!editor) { - return; - } - var lines = editor.lineCount(); - for (var i = 0; i < lines; i++) { - editor.setLineClass(i, null); - } - } - function highlightErrors(text) { - if (!editor) { - return; - } - var errorRe = /[a-z]+\.go:([0-9]+):/g; - var result; - while ((result = errorRe.exec(text)) != null) { - var line = result[1]*1-1; - editor.setLineClass(line, "errLine") - } - } function body() { - if (editor) { - return editor.getValue(); - } return $(opts['codeEl']).val(); } function setBody(text) { - if (editor) { - editor.setValue(text); - return; - } $(opts['codeEl']).val(text); } function origin(href) { @@ -126,24 +83,116 @@ function playground(opts) { '<div class="loading">Waiting for remote server...</div>' ); } - function setOutput(text, error) { + var playbackTimeout; + function playback(pre, events) { + function show(msg) { + // ^L clears the screen. + var msgs = msg.split("\x0c"); + if (msgs.length == 1) { + pre.text(pre.text() + msg); + return; + } + pre.text(msgs.pop()); + } + function next() { + if (events.length == 0) { + var exit = $('<span class="exit"/>'); + exit.text("\nProgram exited."); + exit.appendTo(pre); + return; + } + var e = events.shift(); + if (e.Delay == 0) { + show(e.Message); + next(); + } else { + playbackTimeout = setTimeout(function() { + show(e.Message); + next(); + }, e.Delay / 1000000); + } + } + next(); + } + function stopPlayback() { + clearTimeout(playbackTimeout); + } + function setOutput(events, error) { + stopPlayback(); output.empty(); + $(".lineerror").removeClass("lineerror"); + + // Display errors. if (error) { output.addClass("error"); + var regex = /prog.go:([0-9]+)/g; + var r; + while (r = regex.exec(error)) { + $(".lines div").eq(r[1]-1).addClass("lineerror"); + } + $("<pre/>").text(error).appendTo(output); + return; + } + + // Display image output. + if (events.length > 0 && events[0].Message.indexOf("IMAGE:") == 0) { + var out = ""; + for (var i = 0; i < events.length; i++) { + out += events[i].Message; + } + var url = "data:image/png;base64," + out.substr(6); + $("<img/>").attr("src", url).appendTo(output); + return; + } + + // Play back events. + if (events !== null) { + var pre = $("<pre/>").appendTo(output); + playback(pre, events); + } + } + + var pushedEmpty = (window.location.pathname == "/"); + function inputChanged() { + if (pushedEmpty) { + return; } - $("<pre/>").text(text).appendTo(output); + pushedEmpty = true; + + $(opts['shareURLEl']).hide(); + window.history.pushState(null, "", "/"); + } + + function popState(e) { + if (e == null) { + return; + } + + if (e && e.state && e.state.code) { + setBody(e.state.code); + } + } + + var rewriteHistory = false; + + if (window.history && + window.history.pushState && + window.addEventListener && + opts['enableHistory']) { + rewriteHistory = true; + code[0].addEventListener('input', inputChanged); + window.addEventListener('popstate', popState) } var seq = 0; function run() { - clearErrors(); loading(); seq++; var cur = seq; - var data = {"body": body()}; - if (opts['preCompile']) { - opts['preCompile'](data); - } + var data = { + "version": 2, + "body": body() + }; $.ajax("/compile", { data: data, type: "POST", @@ -152,34 +201,19 @@ function playground(opts) { if (seq != cur) { return; } - if (opts['postCompile']) { - opts['postCompile'](data); - } if (!data) { return; } - if (data.compile_errors != "") { - setOutput(data.compile_errors, true); - highlightErrors(data.compile_errors); - return; - } - var out = ""+data.output; - if (out.indexOf("IMAGE:") == 0) { - var img = $("<img/>"); - var url = "data:image/png;base64,"; - url += out.substr(6) - img.attr("src", url); - output.empty().append(img); + if (data.Errors) { + setOutput(null, data.Errors); return; } - setOutput(out, false); + setOutput(data.Events, false); }, - error: function(xhr) { - var text = "Error communicating with remote server."; - if (xhr.status == 501) { - text = xhr.responseText; - } - output.addClass("error").text(text); + error: function() { + output.addClass("error").text( + "Error communicating with remote server." + ); } }); } @@ -193,29 +227,11 @@ function playground(opts) { dataType: "json", success: function(data) { if (data.Error) { - setOutput(data.Error, true); - highlightErrors(data.Error); + setOutput(null, data.Error); return; } setBody(data.Body); - setOutput("", false); - } - }); - }); - - $(opts['toysEl']).bind('change', function() { - var toy = $(this).val(); - loading(); - $.ajax("/doc/play/"+toy, { - processData: false, - type: "GET", - complete: function(xhr) { - if (xhr.status != 200) { - setOutput("Server error; try again.", true); - return; - } - setBody(xhr.responseText); - setOutput("", false); + setOutput(null); } }); }); @@ -229,16 +245,13 @@ function playground(opts) { $(opts['shareEl']).click(function() { if (sharing) return; sharing = true; + var sharingData = body(); $.ajax("/share", { processData: false, - data: body(), + data: sharingData, type: "POST", complete: function(xhr) { sharing = false; - if (xhr.status == 501) { - alert(xhr.responseText); - return; - } if (xhr.status != 200) { alert("Server error; try again."); return; @@ -247,13 +260,37 @@ function playground(opts) { window.location = opts['shareRedirect'] + xhr.responseText; } if (shareURL) { - var url = origin(window.location) + "/p/" + xhr.responseText; + var path = "/p/" + xhr.responseText + var url = origin(window.location) + path; shareURL.show().val(url).focus().select(); + + if (rewriteHistory) { + var historyData = { + "code": sharingData, + }; + window.history.pushState(historyData, "", path); + pushedEmpty = false; + } } } }); }); } - return editor; + if (opts['toysEl'] != null) { + $(opts['toysEl']).bind('change', function() { + var toy = $(this).val(); + $.ajax("/doc/play/"+toy, { + processData: false, + type: "GET", + complete: function(xhr) { + if (xhr.status != 200) { + alert("Server error; try again.") + return; + } + setBody(xhr.responseText); + } + }); + }); + } } diff --git a/doc/play/sieve.go b/doc/play/sieve.go index 585507ac4..519093453 100644 --- a/doc/play/sieve.go +++ b/doc/play/sieve.go @@ -2,6 +2,8 @@ package main +import "fmt" + // Send the sequence 2, 3, 4, ... to channel 'ch'. func Generate(ch chan<- int) { for i := 2; ; i++ { @@ -26,7 +28,7 @@ func main() { go Generate(ch) // Launch Generate goroutine. for i := 0; i < 10; i++ { prime := <-ch - print(prime, "\n") + fmt.Println(prime) ch1 := make(chan int) go Filter(ch, ch1, prime) ch = ch1 diff --git a/doc/play/solitaire.go b/doc/play/solitaire.go index 759d54281..15022aa19 100644 --- a/doc/play/solitaire.go +++ b/doc/play/solitaire.go @@ -28,7 +28,7 @@ var board = []rune( ........... `) -// center is the position of the center hole if +// center is the position of the center hole if // there is a single one; otherwise it is -1. var center int @@ -47,7 +47,7 @@ func init() { var moves int // number of times move is called -// move tests if there is a peg at position pos that +// move tests if there is a peg at position pos that // can jump over another peg in direction dir. If the // move is valid, it is executed and move returns true. // Otherwise, move returns false. @@ -69,11 +69,11 @@ func unmove(pos, dir int) { board[pos+2*dir] = '○' } -// solve tries to find a sequence of moves such that -// there is only one peg left at the end; if center is +// solve tries to find a sequence of moves such that +// there is only one peg left at the end; if center is // >= 0, that last peg must be in the center position. // If a solution is found, solve prints the board after -// each move in a backward fashion (i.e., the last +// each move in a backward fashion (i.e., the last // board position is printed first, all the way back to // the starting board position). func solve() bool { @@ -89,7 +89,7 @@ func solve() bool { // see if this new board has a solution if solve() { unmove(pos, dir) - println(string(board)) + fmt.Println(string(board)) return true } unmove(pos, dir) @@ -102,7 +102,7 @@ func solve() bool { // tried each possible move if n == 1 && (center < 0 || last == center) { // there's only one peg left - println(string(board)) + fmt.Println(string(board)) return true } // no solution found for this board diff --git a/doc/play/tree.go b/doc/play/tree.go index 5bcbf05a8..3790e6cda 100644 --- a/doc/play/tree.go +++ b/doc/play/tree.go @@ -2,7 +2,7 @@ // express concurrent concepts, such as // this binary tree comparison. // -// Trees may be of different shapes, +// Trees may be of different shapes, // but have the same contents. For example: // // 4 6 @@ -29,7 +29,7 @@ type Tree struct { Right *Tree } -// Walk traverses a tree depth-first, +// Walk traverses a tree depth-first, // sending each Value on a channel. func Walk(t *Tree, ch chan int) { if t == nil { diff --git a/doc/popups.js b/doc/popups.js deleted file mode 100644 index 23ccc8c75..000000000 --- a/doc/popups.js +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -function godocs_bindPopups(data) { - - $('#content span').bind('mouseenter', function() { - var id = $(this).attr('id'); - //var txt = $(this).text(); - if (typeof data[id] == 'undefined') - return; - var content = data[id]; - - var $el = $('.popup', this); - if (!$el.length) { // create it - $el = $('<div class="popup"></div>'); - $el.prependTo(this).css($(this).offset()).text(content); - } - }); - $('#content span').bind('mouseleave', function() { - $('.popup', this).remove(); - }); - -} diff --git a/doc/progs/cgo1.go b/doc/progs/cgo1.go index b79ee368a..1a2dc6c96 100644 --- a/doc/progs/cgo1.go +++ b/doc/progs/cgo1.go @@ -1,3 +1,5 @@ +// skip + // Copyright 2012 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. diff --git a/doc/progs/cgo2.go b/doc/progs/cgo2.go index f38473b13..9999af344 100644 --- a/doc/progs/cgo2.go +++ b/doc/progs/cgo2.go @@ -1,3 +1,5 @@ +// skip + // Copyright 2012 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. diff --git a/doc/progs/cgo3.go b/doc/progs/cgo3.go index 435fd0402..c4f4791e8 100644 --- a/doc/progs/cgo3.go +++ b/doc/progs/cgo3.go @@ -1,3 +1,5 @@ +// skip + // Copyright 2012 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. diff --git a/doc/progs/cgo4.go b/doc/progs/cgo4.go index 3808d6217..30b893572 100644 --- a/doc/progs/cgo4.go +++ b/doc/progs/cgo4.go @@ -1,3 +1,5 @@ +// skip + // Copyright 2012 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. diff --git a/doc/progs/defer.go b/doc/progs/defer.go index 2e11020ab..006a474b5 100644 --- a/doc/progs/defer.go +++ b/doc/progs/defer.go @@ -1,3 +1,5 @@ +// cmpout + // Copyright 2011 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. diff --git a/doc/progs/defer.out b/doc/progs/defer.out new file mode 100644 index 000000000..0cdf53a27 --- /dev/null +++ b/doc/progs/defer.out @@ -0,0 +1,3 @@ +0 +3210 +2 diff --git a/doc/progs/defer2.go b/doc/progs/defer2.go index cad66b070..ff7eaf9d8 100644 --- a/doc/progs/defer2.go +++ b/doc/progs/defer2.go @@ -1,3 +1,5 @@ +// cmpout + // Copyright 2011 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. diff --git a/doc/progs/defer2.out b/doc/progs/defer2.out new file mode 100644 index 000000000..6110685cd --- /dev/null +++ b/doc/progs/defer2.out @@ -0,0 +1,12 @@ +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. diff --git a/doc/progs/eff_bytesize.go b/doc/progs/eff_bytesize.go index b45961114..a0c3d5058 100644 --- a/doc/progs/eff_bytesize.go +++ b/doc/progs/eff_bytesize.go @@ -1,3 +1,5 @@ +// cmpout + // 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. diff --git a/doc/progs/eff_bytesize.out b/doc/progs/eff_bytesize.out new file mode 100644 index 000000000..df763f3b3 --- /dev/null +++ b/doc/progs/eff_bytesize.out @@ -0,0 +1 @@ +1.00YB 9.09TB diff --git a/doc/progs/eff_qr.go b/doc/progs/eff_qr.go index de96a0208..861131ddf 100644 --- a/doc/progs/eff_qr.go +++ b/doc/progs/eff_qr.go @@ -1,10 +1,16 @@ +// compile + +// 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. + package main import ( "flag" + "html/template" "log" "net/http" - "text/template" ) var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18 @@ -31,9 +37,9 @@ const templateStr = ` </head> <body> {{if .}} -<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={{urlquery .}}" /> +<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={{.}}" /> <br> -{{html .}} +{{.}} <br> <br> {{end}} diff --git a/doc/progs/eff_sequence.go b/doc/progs/eff_sequence.go index 11c885abf..c9b18ba93 100644 --- a/doc/progs/eff_sequence.go +++ b/doc/progs/eff_sequence.go @@ -1,3 +1,5 @@ +// cmpout + // 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. diff --git a/doc/progs/eff_sequence.out b/doc/progs/eff_sequence.out new file mode 100644 index 000000000..fd01a7d47 --- /dev/null +++ b/doc/progs/eff_sequence.out @@ -0,0 +1 @@ +[-1 2 6 16 44] diff --git a/doc/progs/error.go b/doc/progs/error.go index f85a5273a..57854c5fe 100644 --- a/doc/progs/error.go +++ b/doc/progs/error.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2011 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. @@ -18,7 +20,11 @@ import ( type File struct{} -func Open(name string) (file *File, err error) +func Open(name string) (file *File, err error) { + // OMIT + panic(1) + // STOP OMIT +} func openFile() { // OMIT f, err := os.Open("filename.ext") diff --git a/doc/progs/error2.go b/doc/progs/error2.go index 2b0e0c356..aad1dc8e8 100644 --- a/doc/progs/error2.go +++ b/doc/progs/error2.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2011 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. diff --git a/doc/progs/error3.go b/doc/progs/error3.go index e4e57e077..9f1b30072 100644 --- a/doc/progs/error3.go +++ b/doc/progs/error3.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2011 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. diff --git a/doc/progs/error4.go b/doc/progs/error4.go index 8f35cf74b..d40fc6eb2 100644 --- a/doc/progs/error4.go +++ b/doc/progs/error4.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2011 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. @@ -22,7 +24,7 @@ type appError struct { type appHandler func(http.ResponseWriter, *http.Request) *appError func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if e := fn(w, r); e != nil { // e is *appError, not os.Error. + if e := fn(w, r); e != nil { // e is *appError, not error. c := appengine.NewContext(r) c.Errorf("%v", e.Error) http.Error(w, e.Message, e.Code) diff --git a/doc/progs/go1.go b/doc/progs/go1.go index 50fd93441..a4dc64d46 100644 --- a/doc/progs/go1.go +++ b/doc/progs/go1.go @@ -1,3 +1,6 @@ +// compile +// this file will output a list of filenames in cwd, not suitable for cmpout + // Copyright 2011 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. diff --git a/doc/progs/gobs1.go b/doc/progs/gobs1.go index 7077ca159..d95f765d8 100644 --- a/doc/progs/gobs1.go +++ b/doc/progs/gobs1.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2011 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. diff --git a/doc/progs/gobs2.go b/doc/progs/gobs2.go index 85bb41cdc..acd18382f 100644 --- a/doc/progs/gobs2.go +++ b/doc/progs/gobs2.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2011 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. diff --git a/doc/progs/image_draw.go b/doc/progs/image_draw.go index bb73c8a71..0a1f7acb1 100644 --- a/doc/progs/image_draw.go +++ b/doc/progs/image_draw.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2012 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. diff --git a/doc/progs/image_package1.go b/doc/progs/image_package1.go index c4c401e72..d331834fc 100644 --- a/doc/progs/image_package1.go +++ b/doc/progs/image_package1.go @@ -1,3 +1,5 @@ +// cmpout + // Copyright 2012 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. diff --git a/doc/progs/image_package1.out b/doc/progs/image_package1.out new file mode 100644 index 000000000..809b31bf6 --- /dev/null +++ b/doc/progs/image_package1.out @@ -0,0 +1 @@ +X is 2 Y is 1 diff --git a/doc/progs/image_package2.go b/doc/progs/image_package2.go index fcb5d9fd0..e5b78b485 100644 --- a/doc/progs/image_package2.go +++ b/doc/progs/image_package2.go @@ -1,3 +1,5 @@ +// cmpout + // Copyright 2012 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. diff --git a/doc/progs/image_package2.out b/doc/progs/image_package2.out new file mode 100644 index 000000000..616d3078b --- /dev/null +++ b/doc/progs/image_package2.out @@ -0,0 +1 @@ +3 4 false diff --git a/doc/progs/image_package3.go b/doc/progs/image_package3.go index 13d0f0807..95d72a0b2 100644 --- a/doc/progs/image_package3.go +++ b/doc/progs/image_package3.go @@ -1,3 +1,5 @@ +// cmpout + // Copyright 2012 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. diff --git a/doc/progs/image_package3.out b/doc/progs/image_package3.out new file mode 100644 index 000000000..3fe35dea5 --- /dev/null +++ b/doc/progs/image_package3.out @@ -0,0 +1 @@ +3 4 true diff --git a/doc/progs/image_package4.go b/doc/progs/image_package4.go index c46fddf07..ec0e4613d 100644 --- a/doc/progs/image_package4.go +++ b/doc/progs/image_package4.go @@ -1,3 +1,5 @@ +// cmpout + // Copyright 2012 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. diff --git a/doc/progs/image_package4.out b/doc/progs/image_package4.out new file mode 100644 index 000000000..cb1b7776b --- /dev/null +++ b/doc/progs/image_package4.out @@ -0,0 +1 @@ +image.Point{X:2, Y:1} diff --git a/doc/progs/image_package5.go b/doc/progs/image_package5.go index 0bb5c7608..b9e27d6da 100644 --- a/doc/progs/image_package5.go +++ b/doc/progs/image_package5.go @@ -1,3 +1,5 @@ +// cmpout + // Copyright 2012 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. diff --git a/doc/progs/image_package5.out b/doc/progs/image_package5.out new file mode 100644 index 000000000..2da80c1fb --- /dev/null +++ b/doc/progs/image_package5.out @@ -0,0 +1 @@ +{255 0 0 255} diff --git a/doc/progs/image_package6.go b/doc/progs/image_package6.go index 62eeecdb9..5e6eefa04 100644 --- a/doc/progs/image_package6.go +++ b/doc/progs/image_package6.go @@ -1,3 +1,5 @@ +// cmpout + // Copyright 2012 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. diff --git a/doc/progs/image_package6.out b/doc/progs/image_package6.out new file mode 100644 index 000000000..fcd13c0c0 --- /dev/null +++ b/doc/progs/image_package6.out @@ -0,0 +1,2 @@ +8 4 +true diff --git a/doc/progs/interface.go b/doc/progs/interface.go index c2925d590..6972b7287 100644 --- a/doc/progs/interface.go +++ b/doc/progs/interface.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2012 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. diff --git a/doc/progs/interface2.go b/doc/progs/interface2.go index a541d94e4..85e7d5163 100644 --- a/doc/progs/interface2.go +++ b/doc/progs/interface2.go @@ -1,3 +1,5 @@ +// cmpout + // Copyright 2012 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. diff --git a/doc/progs/interface2.out b/doc/progs/interface2.out new file mode 100644 index 000000000..085bd017a --- /dev/null +++ b/doc/progs/interface2.out @@ -0,0 +1 @@ +type: float64 diff --git a/doc/progs/json1.go b/doc/progs/json1.go index 9e10f4743..887d7d183 100644 --- a/doc/progs/json1.go +++ b/doc/progs/json1.go @@ -1,3 +1,5 @@ +// run + // Copyright 2012 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. diff --git a/doc/progs/json2.go b/doc/progs/json2.go index 6089ae671..f358feaa2 100644 --- a/doc/progs/json2.go +++ b/doc/progs/json2.go @@ -1,3 +1,5 @@ +// cmpout + // Copyright 2012 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. diff --git a/doc/progs/json2.out b/doc/progs/json2.out new file mode 100644 index 000000000..8f2dea57d --- /dev/null +++ b/doc/progs/json2.out @@ -0,0 +1,2 @@ +the circle's area 24.227111172875365 +the reciprocal of i is 0.3601008282319049 diff --git a/doc/progs/json3.go b/doc/progs/json3.go index a04fdfa50..41eb3730c 100644 --- a/doc/progs/json3.go +++ b/doc/progs/json3.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2012 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. diff --git a/doc/progs/json4.go b/doc/progs/json4.go index 492630220..ee38f31ad 100644 --- a/doc/progs/json4.go +++ b/doc/progs/json4.go @@ -1,3 +1,5 @@ +// run + // Copyright 2012 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. diff --git a/doc/progs/json5.go b/doc/progs/json5.go index 6d7a4ca8c..9ab972df8 100644 --- a/doc/progs/json5.go +++ b/doc/progs/json5.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2012 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. diff --git a/doc/progs/run b/doc/progs/run index 92c8da5cd..da777f329 100755 --- a/doc/progs/run +++ b/doc/progs/run @@ -40,6 +40,15 @@ c_go_cgo=" if [ "$goos" == "freebsd" ]; then c_go_cgo="cgo3 cgo4" fi +# cgo1 and cgo2 don't run on netbsd, srandom has a different signature +# cgo3 and cgo4 don't run on netbsd, since cgo cannot handle stdout correctly +if [ "$goos" == "netbsd" ]; then + c_go_cgo="" +fi +# cgo3 and cgo4 don't run on openbsd, since cgo cannot handle stdout correctly +if [ "$goos" == "openbsd" ]; then + c_go_cgo="cgo1 cgo2" +fi timeout=" timeout1 diff --git a/doc/progs/slices.go b/doc/progs/slices.go index 8e440103e..0461684b7 100644 --- a/doc/progs/slices.go +++ b/doc/progs/slices.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2012 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. diff --git a/doc/progs/timeout1.go b/doc/progs/timeout1.go index 5221770ec..fbc39caac 100644 --- a/doc/progs/timeout1.go +++ b/doc/progs/timeout1.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2012 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. diff --git a/doc/progs/timeout2.go b/doc/progs/timeout2.go index 7145bc93e..a12bc2ab1 100644 --- a/doc/progs/timeout2.go +++ b/doc/progs/timeout2.go @@ -1,3 +1,5 @@ +// compile + // Copyright 2012 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. diff --git a/doc/progs/unused1.go b/doc/progs/unused1.go new file mode 100644 index 000000000..96a6d98a3 --- /dev/null +++ b/doc/progs/unused1.go @@ -0,0 +1,12 @@ +// skip + +package main + +import ( + "fmt" + "io" +) + +func main() { + greeting := "hello, world" +} diff --git a/doc/progs/unused2.go b/doc/progs/unused2.go new file mode 100644 index 000000000..5c5f9d74f --- /dev/null +++ b/doc/progs/unused2.go @@ -0,0 +1,16 @@ +// compile + +package main + +import ( + "fmt" + "io" +) + +var _ = fmt.Printf +var _ io.Reader + +func main() { + greeting := "hello, world" + _ = greeting +} diff --git a/doc/progs/update.bash b/doc/progs/update.bash new file mode 100755 index 000000000..d4ecfbeba --- /dev/null +++ b/doc/progs/update.bash @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# Copyright 2012 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 + +rm -f *.out *.rej *.orig [568].out + +for i in *.go; do + if grep -q '^// cmpout$' $i; then + echo $i + go run $i &> ${i/.go/.out} + fi +done diff --git a/doc/reference.html b/doc/reference.html index beaac431d..795c5e00e 100644 --- a/doc/reference.html +++ b/doc/reference.html @@ -21,13 +21,13 @@ The documentation for the Go tools. <h3 id="spec"><a href="/ref/spec">Language Specification</a></h3> <p> -The official Go Language specification. +The official Go Language specification. </p> -<h3 id="appengine"><a href="http://code.google.com/appengine/docs/go/">App Engine Go Runtime Documentation</a></h3> +<h3 id="appengine"><a href="https://developers.google.com/appengine/docs/go/">App Engine Go Runtime Documentation</a></h3> <p> The documentation for -<a href="http://code.google.com/appengine/">Google App Engine</a>'s Go runtime. +<a href="https://developers.google.com/appengine/">Google App Engine</a>'s Go runtime. </p> <h3 id="go_mem"><a href="/ref/mem">The Go Memory Model</a></h3> @@ -47,25 +47,14 @@ Install them with "<code><a href="/cmd/go/#Download_and_install_packages_and_dep </p> <ul> -<li><a href="http://code.google.com/p/go/source/browse?repo=codereview"><code>code.google.com/p/go.codereview</code></a> [<a href="http://gopkgdoc.appspot.com/pkg/code.google.com/p/go.codereview">docs</a>] -<li><a href="http://code.google.com/p/go/source/browse?repo=crypto"><code>code.google.com/p/go.crypto</code></a> [<a href="http://gopkgdoc.appspot.com/pkg/code.google.com/p/go.crypto">docs</a>] -<li><a href="http://code.google.com/p/go/source/browse?repo=image"><code>code.google.com/p/go.image</code></a> [<a href="http://gopkgdoc.appspot.com/pkg/code.google.com/p/go.image">docs</a>] -<li><a href="http://code.google.com/p/go/source/browse?repo=net"><code>code.google.com/p/go.net</code></a> [<a href="http://gopkgdoc.appspot.com/pkg/code.google.com/p/go.net">docs</a>] -</ul> - -<h4 id="articles">Articles</h4> - -<ul> -<li><a href="/doc/articles/c_go_cgo.html">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li> -<li><a href="/doc/gdb">Debugging Go Code with GDB</a></li> -<li><a href="/doc/articles/defer_panic_recover.html">Defer, Panic, and Recover</a></li> -<li><a href="/doc/articles/slices_usage_and_internals.html">Go Slices: usage and internals</a></li> -<li><a href="/doc/articles/godoc_documenting_go_code.html">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li> -<li><a href="http://blog.golang.org/2011/06/profiling-go-programs.html">Profiling Go Programs</a></li> +<li><a href="http://code.google.com/p/go/source/browse?repo=codereview"><code>code.google.com/p/go.codereview</code></a> [<a href="http://godoc.org/code.google.com/p/go.codereview">docs</a>] +<li><a href="http://code.google.com/p/go/source/browse?repo=crypto"><code>code.google.com/p/go.crypto</code></a> [<a href="http://godoc.org/code.google.com/p/go.crypto">docs</a>] +<li><a href="http://code.google.com/p/go/source/browse?repo=image"><code>code.google.com/p/go.image</code></a> [<a href="http://godoc.org/code.google.com/p/go.image">docs</a>] +<li><a href="http://code.google.com/p/go/source/browse?repo=net"><code>code.google.com/p/go.net</code></a> [<a href="http://godoc.org/code.google.com/p/go.net">docs</a>] </ul> <p> -See the <a href="/doc/#articles">documentation page</a> for more articles. +See the <a href="/doc/">documents page</a> for more documentation. </p> </div> diff --git a/doc/root.html b/doc/root.html index 3b92229cb..34915c025 100644 --- a/doc/root.html +++ b/doc/root.html @@ -53,11 +53,11 @@ simple, reliable, and efficient software. <div id="gopher"></div> <a href="/doc/install" id="start"> -<div class="big">Download Go</div> -<div class="desc"> +<span class="big">Download Go</span> +<span class="desc"> Binary distributions available for<br> Linux, Mac OS X, Windows, and more. -</div> +</span> </a> </div> @@ -68,8 +68,7 @@ Linux, Mac OS X, Windows, and more. <div id="video"> <div class="rootHeading">Featured video</div> -<a class="title" href="http://www.youtube.com/watch?v=Mo1YKpIF1PQ">Building integrated apps on Google's cloud platform with Go</a> -<iframe width="415" height="241" src="http://www.youtube.com/embed/Mo1YKpIF1PQ" frameborder="0" allowfullscreen></iframe> +<iframe width="415" height="241" src="http://www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe> </div> </div> @@ -86,10 +85,8 @@ Linux, Mac OS X, Windows, and more. <div style="clear: both;"></div> <script type="text/javascript" src="https://www.google.com/jsapi"></script> -<script type="text/javascript" src="/doc/play/playground.js"></script> <script type="text/javascript"> google.load("feeds", "1"); -google.load("jquery", "1.7.1"); function feedLoaded(result) { if (result.error) { @@ -124,7 +121,6 @@ function init() { // Set up playground. playground({ - "simple": true, "codeEl": "#learn .code", "outputEl": "#learn .output", "runEl": "#learn .run", diff --git a/doc/style.css b/doc/style.css index a0c632098..3d881b03a 100644 --- a/doc/style.css +++ b/doc/style.css @@ -130,22 +130,25 @@ div#heading a { div#topbar { background: #E0EBF5; height: 64px; + overflow: hidden; } body { text-align: center; } -div#page, +div#page { + width: 100%; +} +div#page > .container, div#topbar > .container { - clear: both; text-align: left; margin-left: auto; margin-right: auto; padding: 0 20px; width: 900px; } -div#page.wide, -div#topbar > .wide { +div#page.wide > .container, +div#topbar.wide > .container { width: auto; } div#plusone { @@ -153,6 +156,7 @@ div#plusone { } div#footer { + text-align: center; color: #666; font-size: 14px; margin: 40px 0; @@ -161,6 +165,7 @@ div#footer { div#menu > a, div#menu > input, div#learn .buttons a, +div.play .buttons a, div#blog .read a { padding: 10px; @@ -171,16 +176,23 @@ div#blog .read a { -moz-border-radius: 5px; border-radius: 5px; } +div#playground .buttons a, div#menu > a, div#menu > input { border: 1px solid #375EAB; } +div#playground .buttons a, div#menu > a { color: white; background: #375EAB; } +#playgroundButton.active { + background: white; + color: #375EAB; +} a#start, div#learn .buttons a, +div.play .buttons a, div#blog .read a { color: #222; border: 1px solid #375EAB; @@ -212,9 +224,11 @@ div#menu > input.inactive { div.left { float: left; + clear: left; } div.right { float: right; + clear: right; } div.left, div.right { @@ -253,10 +267,12 @@ a#start { border-radius: 5px; } a#start .big { + display: block; font-weight: bold; font-size: 20px; } a#start .desc { + display: block; font-size: 14px; font-weight: normal; margin-top: 5px; @@ -340,6 +356,9 @@ div#learn .toys select { border: 1px solid #375EAB; margin: 0; } +div#learn .output .exit { + display: none; +} div#blog, div#video { @@ -391,3 +410,120 @@ img.gopher { margin-bottom: -120px; } h2 { clear: right; } + +/* example and drop-down playground */ +div.play { + padding: 0 20px 40px 20px; +} +div.play pre, +div.play textarea, +div.play .lines { + padding: 0; + margin: 0; + font-family: Menlo, monospace; + font-size: 14px; +} +div.play .input { + padding: 10px; + margin-top: 10px; + + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + + overflow: hidden; +} +div.play .input textarea { + width: 100%; + height: 100%; + border: none; + outline: none; + resize: none; + + overflow: hidden; +} +div#playground .input textarea { + overflow: auto; + resize: auto; +} +div.play .output { + border-top: none !important; + + padding: 10px; + max-height: 200px; + overflow: auto; + + -webkit-border-bottom-right-radius: 5px; + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-bottomleft: 5px; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; +} +div.play .output pre { + padding: 0; + + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +div.play .input, +div.play .input textarea, +div.play .output, +div.play .output pre { + background: #FFFFD8; +} +div.play .input, +div.play .output { + border: 1px solid #375EAB; +} +div.play .buttons { + float: right; + padding: 20px 0 10px 0; + text-align: right; +} +div.play .buttons a { + height: 16px; + margin-left: 5px; + padding: 10px; + cursor: pointer; +} +div.play .output .exit { + color: #999; +} + +/* drop-down playground */ +#playgroundButton, +div#playground { + /* start hidden; revealed by javascript */ + display: none; +} +div#playground { + position: absolute; + top: 63px; + right: 20px; + padding: 0 10px 10px 10px; + z-index: 1; + text-align: left; + background: #E0EBF5; + + border: 1px solid #B0BBC5; + border-top: none; + + -webkit-border-bottom-left-radius: 5px; + -webkit-border-bottom-right-radius: 5px; + -moz-border-radius-bottomleft: 5px; + -moz-border-radius-bottomright: 5px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; +} +div#playground .code { + width: 520px; + height: 200px; +} +div#playground .output { + height: 100px; +} diff --git a/doc/talks/go_talk-20091030.pdf b/doc/talks/go_talk-20091030.pdf Binary files differdeleted file mode 100644 index 5139ff2bd..000000000 --- a/doc/talks/go_talk-20091030.pdf +++ /dev/null diff --git a/doc/talks/go_talk-20100112.html b/doc/talks/go_talk-20100112.html deleted file mode 100644 index 2e3643512..000000000 --- a/doc/talks/go_talk-20100112.html +++ /dev/null @@ -1,411 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> -<title>Go (January 12, 2010)</title> -<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="font-size-adjustment" content="-1" /> -<link rel="stylesheet" href="slidy.css" - type="text/css" media="screen, projection, print" /> -<script src="slidy.js" type="text/javascript"> -</script> -</head> -<body> -<!-- this defines the slide background --> - -<div class="background"> - - <div class="header"> - <!-- sized and colored via CSS --> - </div> - - <div class="footer"></div> - </div> - -<div class="slide titlepage"> -<div style="height: 135px; width: 480px; overflow: hidden; position: fixed; top: auto; bottom: 10px; left: auto; right: 0; "> -<img src="../gordon/bumper480x270.png" style="margin: -135px 0 0 0;"/> -</div> -<!-- <img src="google.png" style="position: fixed; top: auto; bottom: 30px; left: 20px; right: auto;"/> --> -<br/> -<img src="../go-logo-white.png"> -<br/> -<br/> -<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1> -<div style="color: #ffcc00;"> -<h2>Russ Cox</h2> -<!-- <h3><i>rsc@google.com</i></h3> --> -<br/> -<h3>Stanford University<br/><br/>January 12, 2010</h3> -</div> -</div> - -<div class="slide"> - <h1>Go</h1> - - <h2>New</h2> - <h2>Experimental</h2> - <h2>Concurrent</h2> - <h2>Garbage-collected</h2> - <h2>Systems</h2> - <h2>Language</h2> -</div> - -<div class="slide"> - <h1>Hello, world</h1> -<pre> -package main - -import "fmt" - -func main() { - fmt.Printf("Hello, 世界\n") -} -</pre> -</div> - -<div class="slide"> - <h1>History</h1> - - <h2>Design started in late 2007.</h2> - <h2>Implementation starting to work mid-2008.</h2> - <h2>Released as an open source project in November 2009.</h2> - <h2>Work continues.<h2> - <h2>Robert Griesemer, Ken Thompson, Rob Pike, Ian Lance Taylor, Russ Cox, many others</h2> -</div> - -<div class="slide"> - <h1>Why?</h1> - - <h2>Go fast!</h2> - <h2>Make programming fun again.</h2> -</div> - -<div class="slide"> - <h1>Why isn't programming fun?</h1> - - <div class="incremental"> - <h2>Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:</h2> - - <ul> - <li>verbose, lots of repetition</li> - <li>too much focus on type hierarchy</li> - <li>types get in the way as much as they help</li> - <li>compiles take far too long</li> - </ul> - </div> - - <div class="incremental"> - <h2>Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:</h2> - - <ul> - <li>errors at run time that should be caught statically</li> - <li>no compilation means slow code</li> - </ul> - </div> - - <h2 class="incremental">Can we combine the best of both?</h2> -</div> - -<div class="slide"> - <h1>Go</h1> - - <h2>Make the language fast.</h2> - <h2>Make the tools fast.</h2> -</div> - -<div class="slide"> - <h1>Go Approach: Static Types</h1> - - <h2>Static types, but declarations can infer type from expression:</h2> - -<pre> -var one, hi = 1, "hello" - -var double = func(x int) int { return x*2 } -</pre> - - <h2>Not full Hindley-Milner type inference.</h2> -</div> - - -<div class="slide"> - <h1>Go Approach: Methods</h1> - - <h2>Methods can be defined on any type.</h2> - -<pre> -type Point struct { - X, Y float64 -} - -func (p Point) Abs() float64 { - return math.Sqrt(p.X*p.X + p.Y*p.Y) -} -</pre> -</div> - -<div class="slide"> - <h1>Go Approach: Methods</h1> - - <h2>Methods can be defined on any type.</h2> - -<pre> -type MyFloat float64 - -func (f MyFloat) Abs() float64 { - v := float64(f) - if v < 0 { - v = -v - } - return v -} -</pre> -</div> - -<div class="slide"> - <h1>Go Approach: Abstract Types</h1> - - <h2>An interface type lists a set of methods. Any value with those methods satisfies the interface.</h2> - -<pre> -type Abser interface { - Abs() float64 -} - -func AbsPrinter(a Abser) -</pre> - - <h2>Can use Point or MyFloat (or ...):</h2> - -<pre> -p := Point{3, 4} -AbsPrinter(p) - -f := MyFloat(-10) -AbsPrinter(f) -</pre> - - <h2>Notice that Point never declared that it implements Abser. It just does. Same with MyFloat.</h2> -</div> - -<div class="slide"> - <h1>Go Approach: Packages</h1> - - <h2>A Go program comprises one or more packages.</h2> - <h2>Each package is one or more source files compiled and imported as a unit.</h2> -<pre> -package draw - -type Point struct { - X, Y int -} -</pre> - -<pre> -package main - -import "draw" - -var p draw.Point -</pre> -</div> - -<div class="slide"> - <h1>Go Approach: Visibility</h1> - - <h2>Inside a package, all locally defined names are visible in all source files.</h2> - - <h2>When imported, only the upper case names are visible.</h2> - -<pre> -package draw - -type <span style="color: black;">Point</span> struct { - <span style="color: black;">X</span>, <span style="color: black;">Y</span> int - dist float64 -} - -type cache map[Point] float64 -</pre> - -<h2>Clients that <code>import "draw"</code> can use the black names only.</h2> - -<h2>“Shift is the new <code>public</code>.”</h2> -</div> - -<div class="slide"> - <h1>Go Approach: Concurrency</h1> - - <h2>Cheap to create a new flow of control (goroutine):</h2> - -<pre> -func main() { - go expensiveComputation(x, y, z) - anotherExpensiveComputation(a, b, c) -} -</pre> - - <h2>Two expensive computations in parallel.</h2> -</div> - -<div class="slide"> - <h1>Go Approach: Synchronization</h1> - - <h2>Use explicit messages to communicate and synchronize.</h2> - -<pre> -func computeAndSend(ch chan int, x, y, z int) { - ch <- expensiveComputation(x, y, z) -} - -func main() { - ch := make(chan int) - go computeAndSend(ch, x, y, z) - v2 := anotherExpensiveComputation(a, b, c) - v1 := <-ch - fmt.Println(v1, v2) -} -</pre> - <h2>Notice communication of result in addition to synchronization.</h2> -</div> - -<div class="slide"> - <h1>Go Fast: Language</h1> - - <h2 class="incremental">Static types: enough to compile well, but inferred much of the time.</h2> - - <h2 class="incremental">Methods: on any type, orthogonal to type system.</h2> - - <h2 class="incremental">Abstract types: interface values, relations inferred statically.</h2> - - <h2 class="incremental">Visibility: inferred from case of name.</h2> - - <h2 class="incremental">Concurrency: lightweight way to start new thread of control.</h2> - - <h2 class="incremental">Synchronization: explicit, easy message passing.</h2> - - <br/> - - <h2 class="incremental">Lightweight feel of a scripting language but compiled.</h2> -</div> - -<div class="slide"> - <h1>Compile fast</h1> - - <div class="incremental"> - <h2>Observation: much of the compile time for a source file is spent processing - other, often unrelated files.</h2> - - <h2>In C: <code>a.c</code> includes <code>b.h</code>, which includes <code>c.h</code>, which includes <code>d.h</code>. - </h2> - - <h2>Except that it's more often a tree instead of a chain.</h2> - - <h2>On my Mac (OS X 10.5.8, gcc 4.0.1):</h2> - <ul> - <li>C: <code>#include <stdio.h></code> reads 360 lines from 9 files. - <li>C++: <code>#include <iostream></code> reads 25,326 lines from 131 files. - <li>Objective C: <code>#include <Carbon/Carbon.h></code> reads 124,730 lines from 689 files. - </ul> - - <h2>And we haven't done any real work yet!</h2> - - <h2>Same story in Java, Python, but reading binaries instead of source files.</h2> - </div> -</div> - -<div class="slide"> - <h1>Implementation: Summarize Dependencies</h1> - -<pre> -package gui - -import "draw" - -type Mouse struct { - Loc draw.Point - Buttons uint -} -</pre> - <h2>Compiled form of <code>gui</code> summarizes the necessary part of <code>draw</code> (just <code>Point</code>).</h2> - -</div> - -<div class="slide"> - <h1>Implementation: Summarize Dependencies</h1> - - <h2>Compiled form of <code>gui</code> summarizes the necessary part of <code>draw</code> (just <code>Point</code>). Pseudo-object:</h2> - -<pre> -package gui -type draw.Point struct { - X, Y int -} -type gui.Mouse struct { - Loc draw.Point - Buttons uint -} -</pre> - - <h2>A file that imports <code>gui</code> compiles without consulting <code>draw</code> or its dependencies.</h2> - - <h2>In Go: <code>import "fmt"</code> reads <i>one</i> file: 184 lines summarizing types from 7 packages.</h2> - - <h2>Tiny effect in this program but can be exponential in large programs.</h2> -</div> - -<div class="slide"> - <h1>Compilation Demo</h1> - - <h2>Build all standard Go packages: ~120,000 lines of code.</h2> -</div> - -<div class="slide"> - <h1>Go Status</h1> - - <div class="incremental"> - <div> - <h2>Open source:</h2> - <ul> - <li>released on November 10, 2009 - <li>regular releases (~ weekly) - <li>all development done in public Mercurial repository - <li>outside contributions welcome - </ul> - </div> - - <div> - <h2>Portable:</h2> - <ul> - <li>FreeBSD, Linux, OS X (x86, x86-64) - <li>(in progress) Linux arm, Native Client x86, Windows x86. - </ul> - </div> - - <div> - <h2>Still in progress, experimental. Yet to come:</h2> - <ul> - <li>mature garbage collector - <li>generics? - <li>exceptions? - <li>unions or sum types? - </ul> - </div> - </div> - -</div> - -<div class="slide titlepage"> - <h1>Questions?</h1> - <br><br> - <center> - <img src="../gordon/bumper640x360.png"> - </center> - <br><br> - <div style="color: #ffcc00;"> - <!-- <h3><i>rsc@google.com</i></h3> --> - </div> -</div> - -</body></html> diff --git a/doc/talks/go_talk-20100121.html b/doc/talks/go_talk-20100121.html deleted file mode 100644 index d5e4bc66f..000000000 --- a/doc/talks/go_talk-20100121.html +++ /dev/null @@ -1,453 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> -<title>Go, Networked (January 21, 2010)</title> -<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="font-size-adjustment" content="-1" /> -<link rel="stylesheet" href="slidy.css" - type="text/css" media="screen, projection, print" /> -<script src="slidy.js" type="text/javascript"> -</script> -</head> -<body> -<!-- this defines the slide background --> - -<div class="background"> - - <div class="header"> - <!-- sized and colored via CSS --> - </div> - - <div class="footer"></div> - </div> - -<div class="slide titlepage"> -<div style="height: 135px; width: 480px; overflow: hidden; position: fixed; top: auto; bottom: 10px; left: auto; right: 0; "> -<img src="../gordon/bumper480x270.png" style="margin: -135px 0 0 0;"/> -</div> -<!-- <img src="../google.png" style="position: fixed; top: auto; bottom: 30px; left: 20px; right: auto;"/> --> -<br/> -<img src="../go-logo-white.png"> -<br/> -<br/> -<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1> -<div style="color: #ffcc00;"> -<h2>Russ Cox</h2> -<!-- <h3><i>rsc@google.com</i></h3> --> -<br/> -<h3>CNS Winter Research Review<br/><br/>January 21, 2010</h3> -<br/> -<br/> -<!-- -<h4><i>click to start; then left/right arrow to change slides</i></h4> --> -</div> -</div> - -<div class="slide"> - <h1>Go</h1> - - <h2>New</h2> - <h2>Experimental</h2> - <h2>Concurrent</h2> - <h2>Garbage-collected</h2> - <h2>Systems</h2> - <h2>Language</h2> -</div> - -<div class="slide"> - <h1>Hello, world</h1> -<pre> -package main - -import "fmt" - -func main() { - fmt.Printf("Hello, 世界\n") -} -</pre> -</div> - -<div class="slide"> - <h1>History</h1> - - <h2>Design started in late 2007.</h2> - <h2>Implementation starting to work mid-2008.</h2> - <h2>Released as an open source project in November 2009.</h2> - <h2>Work continues.<h2> - <h2>Robert Griesemer, Ken Thompson, Rob Pike, Ian Lance Taylor, Russ Cox, many others</h2> -</div> - -<div class="slide"> - <h1>Goals and Motivation</h1> - - <h2>Go fast!</h2> - <h2>Make programming fun again.</h2> - <h2>Targeted at systems software, broadly.</h2> -</div> - -<div class="slide"> - <h1>Why isn't programming fun?</h1> - - <div class="incremental"> - <h2>Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:</h2> - - <ul> - <li>verbose, lots of repetition</li> - <li>too much focus on type hierarchy</li> - <li>types get in the way as much as they help</li> - <li>compiles take far too long</li> - </ul> - </div> - - <div class="incremental"> - <h2>Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:</h2> - - <ul> - <li>errors at run time that should be caught statically</li> - <li>no compilation means slow code</li> - </ul> - </div> - - <h2 class="incremental">Can we combine the best of both?</h2> -</div> - -<div class="slide"> - <h1>Why a new language?</h1> - - <div class="incremental"> - <h2>No new systems language in 10+ years.</h2> - <h2>Current languages designed before ...</h2> - <h3>... rise of large-scale, networked and multicore computing</h3> - <h3>... rise of Internet-scale distributed development (many libraries)</h3> - </div> -</div> - -<div class="slide"> - <h1>Go</h1> - - <h2>Make the language fast.</h2> - <h2>Make the tools fast.</h2> -</div> - -<div class="slide"> - <h1>Compilation Demo</h1> - - <h2>Build all standard Go packages: ~120,000 lines of code.</h2> -</div> - -<div class="slide"> - <h1>Go in one slide</h1> - - <h2 class="incremental">Lightweight syntax.</h2> - - <h2 class="incremental">Static types: enough to compile well, but inferred much of the time.</h2> - - <h2 class="incremental">Methods: on any type, orthogonal to type system.</h2> - - <h2 class="incremental">Abstract types: interface values, relations inferred statically.</h2> - - <h2 class="incremental">Visibility: inferred from case of name.</h2> - - <h2 class="incremental">First-class functions.</h2> - - <h2 class="incremental">Garbage collection.</h2> - - <br/> - - <h2 class="incremental">Lightweight feel of a scripting language but compiled.</h2> -</div> - -<div class="slide"> - <h1>Go, concurrently</h1> - - <h2>Cheap to create a new flow of control (goroutine):</h2> - -<pre> -func main() { - go expensiveComputation(x, y, z) - anotherExpensiveComputation(a, b, c) -} -</pre> - - <h2>Two expensive computations in parallel.</h2> -</div> - -<div class="slide"> - <h1>Go, concurrently</h1> - - <h2>Cheap to create a new flow of control (goroutine):</h2> - -<pre> - for { - rw := l.Accept() - conn := newConn(rw, handler) - go conn.serve() - } -</pre> - - <h2>Concurrent web server.</h2> - <h2>Network connections multiplexed onto epoll.</h2> - <ul> - <li>many blocked Read calls != many blocked OS threads</li> - </ul> - -</div> - -<div class="slide"> - <h1>Go, synchronized</h1> - - <h2>Use explicit messages to communicate and synchronize.</h2> - -<pre> -func computeAndSend(ch chan int, x, y, z int) { - ch <- expensiveComputation(x, y, z) -} - -func main() { - ch := make(chan int) - go computeAndSend(ch, x, y, z) - v2 := anotherExpensiveComputation(a, b, c) - v1 := <-ch - fmt.Println(v1, v2) -} -</pre> - <h2>Notice communication of result in addition to synchronization.</h2> -</div> - -<div class="slide"> - <h1>Go, synchronized</h1> - - <h2>RPC client</h2> - -<pre> -func (client *Client) Call(method string, args, reply interface{}) os.Error { - // Send RPC message. - call := client.Go(method, args, reply, nil) - - // Read reply from Done channel. - <-call.Done - - return call.Error -} -</pre> -</div> - -<div class="slide"> - <h1>Go, synchronized</h1> - - <h2>RPC client demux</h2> - -<pre> -func (client *Client) input() { - for { - resp := client.readResponse() - client.mutex.Lock() - c := client.pending[resp.Seq] - client.pending[resp.Seq] = c, false - client.mutex.Unlock() - if resp.Error != "" { - c.Error = os.ErrorString(resp.error) - } - resp.Decode(c.Reply) - c.Done <- c - } -} -</pre> -</div> - -<div class="slide"> - <h1>Go, synchronized</h1> - - <h2>RPC client demux</h2> - -<pre> -func (client *Client) input() { - for { - <font style="color: black;">resp := client.readResponse()</font> - client.mutex.Lock() - c := client.pending[resp.Seq] - client.pending[resp.Seq] = c, false - client.mutex.Unlock() - if resp.Error != "" { - c.Error = os.ErrorString(resp.error) - } - resp.Decode(c.Reply) - c.Done <- c - } -} -</pre> -<h2>Read response from network.</h2 -</div> - -<div class="slide"> - <h1>Go, synchronized</h1> - - <h2>RPC client demux</h2> - -<pre> -func (client *Client) input() { - for { - resp := client.readResponse() - <font style="color: black;">client.mutex.Lock() - c := client.pending[resp.Seq] - client.pending[resp.Seq] = c, false - client.mutex.Unlock()</font> - if resp.Error != "" { - c.Error = os.ErrorString(resp.error) - } - resp.Decode(c.Reply) - c.Done <- c - } -} -</pre> -<h2>Look up request by sequence number.</h2 -</div> - -<div class="slide"> - <h1>Go, synchronized</h1> - - <h2>RPC client demux</h2> - -<pre> -func (client *Client) input() { - for { - resp := client.readResponse() - client.mutex.Lock() - c := client.pending[resp.Seq] - client.pending[resp.Seq] = c, false - client.mutex.Unlock() - <font style="color: black;">if resp.Error != "" { - c.Error = os.ErrorString(resp.error) - } - resp.Decode(c.Reply)</font> - c.Done <- c - } -} -</pre> -<h2>Decode response fields from payload.</h2 -</div> - -<div class="slide"> - <h1>Go, synchronized</h1> - - <h2>RPC client demux</h2> - -<pre> -func (client *Client) input() { - for { - resp := client.readResponse() - client.mutex.Lock() - c := client.pending[resp.Seq] - client.pending[resp.Seq] = c, false - client.mutex.Unlock() - if resp.Error != "" { - c.Error = os.ErrorString(resp.error) - } - resp.Decode(c.Reply) - <font style="color: black;">c.Done <- c</font> - } -} -</pre> -<h2>Tell client that it finished.</h2 -</div> - -<div class="slide"> - <h1>Go, synchronized</h1> - - <h2>RPC client demux</h2> - -<pre> -func (client *Client) input() { - for { - resp := client.readResponse() - client.mutex.Lock() - c := client.pending[resp.Seq] - client.pending[resp.Seq] = c, false - client.mutex.Unlock() - if resp.Error != "" { - c.Error = os.ErrorString(resp.error) - } - resp.Decode(c.Reply) - c.Done <- c - } -} -</pre> - -<h2>Can create multiple Calls with same Done channel -and distinguish which finished by inspecting value sent on channel. -</h2> - -</div> - -<div class="slide"> - <h1>Goroutine demo</h1> - - <h2>Chain together 100,000 goroutines connected by 100,001 channels.</h2> - - <h2>Send a value to one end of the chain.</h2> - - <h2>Each passes it along, increments.</h2> - - <h2>Receive value out the other end of the chain.</h2> -</div> - - -<div class="slide"> - <h1>Go Status</h1> -</div> - -<div class="slide"> - <h1>Go Status</h1> - - <h2>Open source:</h2> - <ul> - <li>released on November 10, 2009 - <li>regular releases (~ weekly) - <li>all development done in public Mercurial repository - <li>outside contributions welcome - <li>two independent compiler implementations - <li>XML, JSON, HTTP, TLS/SSL, native RPC, (network channels,) ... - </ul> -</div> - -<div class="slide"> - <h1>Go Status</h1> - - <h2>Open source</h2> - - <h2>Portable:</h2> - <ul> - <li>FreeBSD, Linux, OS X (x86, x86-64) - <li>(in progress) Linux arm, Native Client x86, Windows x86. - </ul> -</div> - -<div class="slide"> - <h1>Go Status</h1> - - <h2>Open source</h2> - <h2>Portable</h2> - - <h2>Still in progress, experimental. Yet to come:</h2> - <ul> - <li>production garbage collector - <li>generics? - <li>exceptions? - <li>unions or sum types? - </ul> -</div> - -<div class="slide titlepage"> - <h1>Questions?</h1> - <br><br> - <center> - <img src="../gordon/bumper640x360.png"> - </center> - <br><br> - <div style="color: #ffcc00;"> - <!-- <h3><i>rsc@google.com</i></h3> --> - </div> -</div> - -</body></html> diff --git a/doc/talks/go_talk-20100323.html b/doc/talks/go_talk-20100323.html deleted file mode 100644 index 7330dd2ae..000000000 --- a/doc/talks/go_talk-20100323.html +++ /dev/null @@ -1,395 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> -<title>Go Tech Talk</title> -<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="font-size-adjustment" content="-1" /> -<link rel="stylesheet" href="slidy.css" - type="text/css" media="screen, projection, print" /> -<script src="slidy.js" type="text/javascript"> -</script> -</head> -<body> -<!-- this defines the slide background --> - -<div class="background"> - - <div class="header"> - <!-- sized and colored via CSS --> - </div> - - <div class="footer"></div> - </div> - -<div class="slide titlepage"> -<br/> -<br/> -<img src="../go-logo-white.png" width="588px" height="217px"> -<br/> -<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1> -<div style="color: #ffcc00;"> -<br/> -<h3>Sydney University<br/><br/>March 23, 2010</h3> -</div> -</div> - -<div class="slide"> - <h1>Go</h1> - - <h2>New</h2> - <h2>Experimental</h2> - <h2>Concurrent</h2> - <h2>Garbage Collected</h2> - <h2>Systems Language</h2> -</div> - -<div class="slide"> - <h1>Hello, world</h1> -<pre> -package main - -import "fmt" - -func main() { - fmt.Printf("Hello, 世界\n") -} -</pre> -</div> - -<div class="slide"> - <h1>Hello, world 2.0</h1> - - <h2>Serving <a href="http://localhost:8080/world">http://localhost:8080/world</a></h2> -<pre> -package main - -import ( - "fmt" - "http" -) - -func handler(c *http.Conn, r *http.Request) { - fmt.Fprintf(c, "Hello, %s.", r.URL.Path[1:]) -} - -func main() { - http.ListenAndServe(":8080", - http.HandlerFunc(handler)) -} -</pre> -</div> - -<div class="slide"> - <h1>New</h1> - - <h2>It's about two years old:</h2> - <ul> - <li>Design started in late 2007</li> - <li>Implementation starting to work mid-2008</li> - <li>Released as an open source project in November 2009</li> - <li>Development continues with an active community</li> - </ul> - - <h2>Why invent a new language? Older languages weren't designed for concurrency, but modern software needs it:</h2> - <ul> - <li>Large scale, networked computing, such as Google web search</li> - <li>Multi-core hardware</li> - </ul> -</div> - -<div class="slide"> - <h1>New</h1> - - <h2>Older languages are also frustrating on a day-to-day basis</h2> - <h2>Statically-typed languages (C, C++, Java) have issues:</h2> - <ul> - <li>Edit-Compile-Run cycle takes far too long</li> - <li>Type hierarchy can hurt as much as it helps</li> - </ul> -<div style="text-align:center"> -<img src="java-typing.png" width="800px" height="90px"><br> -</div> - - <h2>Dynamic languages (Python, JavaScript) fix some issues but introduce others:</h2> - <ul> - <li>No compilation means slow code</li> - <li>Runtime errors that should be caught statically</li> - </ul> - - <h2>Go has the lighter feel of a scripting language but is compiled</h2> -</div> - -<div class="slide"> - <h1>New</h1> - - <h2>Large C++ programs (e.g. Firefox, OpenOffice, Chromium) have enormous build times:</h2> - <ul> - <li>XKCD's #1 Programmer Excuse for Legitimately Slacking Off: "<a href="http://xkcd.com/303/">My Code's Compiling</a>"</li> - </ul> - - <h2>On a Mac (OS X 10.5.8, gcc 4.0.1):</h2> - <ul> - <li>C: <code>#include <stdio.h></code> reads 360 lines from 9 files</li> - <li>C++: <code>#include <iostream></code> reads 25,326 lines from 131 files</li> - <li>Objective-C: <code>#include <Carbon/Carbon.h></code> reads 124,730 lines from 689 files</li> - <li>We haven't done any real work yet!</li> - </ul> - - <h2>In Go: <code>import "fmt"</code> reads <i>one</i> file: 184 lines summarizing 7 packages</h2> -</div> - -<div class="slide"> - <h1>New</h1> - - <h2>Compilation demo</h2> -</div> - -<div class="slide"> - <h1>Experimental</h1> - - <h2>Go is still unproven</h2> - <h2>Language is still evolving</h2> - <h2>Package library is incomplete</h2> - <h2>Concurrent garbage collection is an active research problem</h2> - <h2>Reviving forgotten concepts:</h2> - <ul> - <li>Go's concurrency is strongly influenced by <i>Communicating Sequential Processes</i> (Hoare, 1978)</li> - <li>Go has types and interfaces, but no inheritance. It is arguably more object-oriented than previously mentioned languages, being closer to the original Smalltalk meaning (1970s)</li> - </ul> -</div> - -<div class="slide"> - <h1>Concurrent</h1> - - <h2>Unix philosophy: write <i>programs</i> that do one thing and do it well</h2> - <h2>Connect them with <i>pipes</i>:</h2> - <ul> - <li>How many lines of test code are there in the Go standard library?</li> - <li><code>find ~/go/src/pkg | grep _test.go$ | xargs wc -l</code></li> - </ul> - - <h2>Unlike other languages, Go makes it easy to:</h2> - <ul> - <li>Launch <i>goroutines</i></li> - <li>Connect them with <i>channels</i></li> - </ul> -</div> - -<div class="slide"> - <h1>Concurrent</h1> - - <h2>Start a new flow of control with the <code>go</code> keyword</h2> - <h2>Parallel computation is easy:</h2> -<pre> -func main() { - go expensiveComputation(x, y, z) - anotherExpensiveComputation(a, b, c) -} -</pre> - - <h2>Roughly speaking, a goroutine is like a thread, but lighter weight:</h2> - <ul> - <li>Goroutines have segmented stacks, and typically smaller stacks</li> - <li>This requires compiler support. Goroutines can't just be a C++ library on top of a thread library</li> - </ul> -</div> - -<div class="slide"> - <h1>Concurrent</h1> - - <h2>Consider web servers ("the C10k problem"):</h2> - <ul> - <li>"Thread per connection" approach is conceptually neat, but doesn't scale well in practice</li> - <li>What does scale well (event-driven callbacks, asynchronous APIs) are harder to understand, maintain, and debug</li> - <li>We think "goroutine per connection" can scale well, and is conceptually neat</li> - </ul> -<pre> - for { - rw := socket.Accept() - conn := newConn(rw, handler) - go conn.serve() - } -</pre> -</div> - -<div class="slide"> - <h1>Concurrent</h1> - - <h2>Let's look again at our simple parallel computation:</h2> -<pre> -func main() { - go expensiveComputation(x, y, z) - anotherExpensiveComputation(a, b, c) -} -</pre> - - <h2>This story is incomplete:</h2> - <ul> - <li>How do we know when the two computations are done?</li> - <li>What are their values?</li> - </ul> -</div> - -<div class="slide"> - <h1>Concurrent</h1> - - <h2>Goroutines communicate with other goroutines via channels</h2> -<pre> -func computeAndSend(ch chan int, x, y, z int) { - ch <- expensiveComputation(x, y, z) -} - -func main() { - ch := make(chan int) - go computeAndSend(ch, x, y, z) - v2 := anotherExpensiveComputation(a, b, c) - v1 := <-ch - fmt.Println(v1, v2) -} -</pre> - -</div> - -<div class="slide"> - <h1>Concurrent</h1> - - <h2>In traditional concurrent programs, you <i>communicate by sharing memory</i>. In Go, you <i>share memory by communicating</i>:</h2> - <ul> - <li>Communication (the <code><-</code> operator) is sharing and synchronization</li> - </ul> - - <h2>Threads and locks are concurrency primitives; CSP is a concurrency model:</h2> - <ul> - <li>Analogy: "Go To Statement Considered Harmful" (Dijsktra, 1968)</li> - <li><code>goto</code> is a control flow primitive; structured programming (<code>if</code> statements, <code>for</code> loops, function calls) is a control flow model</li> - </ul> - - <h2>Learning CSP changes the way you think about concurrent programming:</h2> - <ul> - <li>Every language has its grain. If your Go program uses mutexes, you're probably working against the grain</li> - </ul> -</div> - -<div class="slide"> - <h1>Garbage Collected</h1> - - <h2>Automatic memory management makes writing (and maintaining) programs easier</h2> - <h2>Especially in a concurrent world:</h2> - <ul> - <li>Who "owns" a shared piece of memory, and is responsible for destroying it?</li> - </ul> - - <h2>Large C++ programs usually end up with semi-automatic memory management anyway, via "smart pointers"</h2> - <h2>Mixing the two models can be problematic:</h2> - <ul> - <li>Browsers can leak memory easily; DOM elements are C++ objects, but JavaScript is garbage collected</li> - </ul> -</div> - -<div class="slide"> - <h1>Garbage Collected</h1> - - <h2>Go is also a safer language:</h2> - <ul> - <li>Pointers but no pointer arithmetic</li> - <li>No dangling pointers</li> - <li>Variables are zero-initialized</li> - <li>Array access is bounds-checked</li> - </ul> - - <h2>No buffer overflow exploits</h2> -</div> - -<div class="slide"> - <h1>Systems Language</h1> - - <h2>This just means you could write decently large programs in Go:</h2> - <ul> - <li>Web servers</li> - <li>Web browsers</li> - <li>Web crawlers</li> - <li>Search indexers</li> - <li>Databases</li> - <li>Word processors</li> - <li>Integrated Development Environments (IDEs)</li> - <li>Operating systems</li> - <li>...</li> - </ul> -</div> - -<div class="slide"> - <h1>Systems Language</h1> - - <h2>Garbage collection has a reputation for being "slower"</h2> - <h2>We're expecting Go to be slightly slower than optimized C, but faster than Java, depending on the task. Nonetheless:</h2> - <ul> - <li>Fast and buggy is worse than almost-as-fast and correct</li> - <li>It is easier to optimize a correct program than to correct an optimized program</li> - <li>Fundamentally, it's simply a trade-off we're willing to make</li> - </ul> - - <h2>Memory layout can drastically affect performance. These two designs are equivalent in Go, but significantly different in Java:</h2> -<pre> -type Point struct { X, Y int } -type Rect struct { P0, P1 Point } - -// or ... - -type Rect struct { X0, Y0, X1, Y1 int } -</pre> -</div> - -<div class="slide"> - <h1>Systems Language</h1> - - <h2>Quote from http://loadcode.blogspot.com/2009/12/go-vs-java.html</h2> - -<h2> -"[Git] is known to be very fast. It is written in C. A Java version -JGit was made. It was considerably slower. Handling of memory and lack -of unsigned types was some of the important reasons. -</h2> - -<h2>Shawn O. Pearce wrote on the git mailinglist:</h2> -<ul><li>"JGit struggles with not -having an efficient way to represent a SHA-1. C can just say "unsigned -char[20]" and have it inline into the container's memory allocation. A -byte[20] in Java will cost an *additional* 16 bytes of memory, and be -slower to access because the bytes themselves are in a different area -of memory from the container object. We try to work around it by -converting from a byte[20] to 5 ints, but that costs us machine -instructions" -</li></ul> - -<h2> -Like C, Go does allow unsigned types and defining data structures -containing other data structures as continuous blocks of memory." -</h2> -</div> - -<div class="slide"> - <h1>Go</h1> - - <h2>New</h2> - <h2>Experimental</h2> - <h2>Concurrent</h2> - <h2>Garbage Collected</h2> - <h2>Systems Language</h2> - - <h2>And more:</h2> - <ul> - <li>I haven't talked about the type system, interfaces, slices, closures, selects, ...</li> - <li>Documentation, mailing list, source code all online</li> - </ul> -</div> - -<div class="slide titlepage"> - <h1>Questions?</h1> - <br><br> - <center> - <img src="../gordon/bumper640x360.png" width="640px" height="360px"> - </center> -</div> - -</body></html> diff --git a/doc/talks/gofrontend-gcc-summit-2010.pdf b/doc/talks/gofrontend-gcc-summit-2010.pdf Binary files differdeleted file mode 100644 index 157fd7676..000000000 --- a/doc/talks/gofrontend-gcc-summit-2010.pdf +++ /dev/null diff --git a/doc/talks/io2010/balance.go b/doc/talks/io2010/balance.go deleted file mode 100644 index a3825cbc5..000000000 --- a/doc/talks/io2010/balance.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2010 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. - -package main - -import ( - "container/heap" - "flag" - "fmt" - "math/rand" - "time" -) - -const nRequester = 100 -const nWorker = 10 - -var roundRobin = flag.Bool("r", false, "use round-robin scheduling") - -// Simulation of some work: just sleep for a while and report how long. -func op() int { - n := rand.Int63n(1e9) - time.Sleep(nWorker * n) - return int(n) -} - -type Request struct { - fn func() int - c chan int -} - -func requester(work chan Request) { - c := make(chan int) - for { - time.Sleep(rand.Int63n(nWorker * 2e9)) - work <- Request{op, c} - <-c - } -} - -type Worker struct { - i int - requests chan Request - pending int -} - -func (w *Worker) work(done chan *Worker) { - for { - req := <-w.requests - req.c <- req.fn() - done <- w - } -} - -type Pool []*Worker - -func (p Pool) Len() int { return len(p) } - -func (p Pool) Less(i, j int) bool { - return p[i].pending < p[j].pending -} - -func (p *Pool) Swap(i, j int) { - a := *p - a[i], a[j] = a[j], a[i] - a[i].i = i - a[j].i = j -} - -func (p *Pool) Push(x interface{}) { - a := *p - n := len(a) - a = a[0 : n+1] - w := x.(*Worker) - a[n] = w - w.i = n - *p = a -} - -func (p *Pool) Pop() interface{} { - a := *p - *p = a[0 : len(a)-1] - w := a[len(a)-1] - w.i = -1 // for safety - return w -} - -type Balancer struct { - pool Pool - done chan *Worker - i int -} - -func NewBalancer() *Balancer { - done := make(chan *Worker, nWorker) - b := &Balancer{make(Pool, 0, nWorker), done, 0} - for i := 0; i < nWorker; i++ { - w := &Worker{requests: make(chan Request, nRequester)} - heap.Push(&b.pool, w) - go w.work(b.done) - } - return b -} - -func (b *Balancer) balance(work chan Request) { - for { - select { - case req := <-work: - b.dispatch(req) - case w := <-b.done: - b.completed(w) - } - b.print() - } -} - -func (b *Balancer) print() { - sum := 0 - sumsq := 0 - for _, w := range b.pool { - fmt.Printf("%d ", w.pending) - sum += w.pending - sumsq += w.pending * w.pending - } - avg := float64(sum) / float64(len(b.pool)) - variance := float64(sumsq)/float64(len(b.pool)) - avg*avg - fmt.Printf(" %.2f %.2f\n", avg, variance) -} - -func (b *Balancer) dispatch(req Request) { - if *roundRobin { - w := b.pool[b.i] - w.requests <- req - w.pending++ - b.i++ - if b.i >= len(b.pool) { - b.i = 0 - } - return - } - - w := heap.Pop(&b.pool).(*Worker) - w.requests <- req - w.pending++ - // fmt.Printf("started %p; now %d\n", w, w.pending) - heap.Push(&b.pool, w) -} - -func (b *Balancer) completed(w *Worker) { - if *roundRobin { - w.pending-- - return - } - - w.pending-- - // fmt.Printf("finished %p; now %d\n", w, w.pending) - heap.Remove(&b.pool, w.i) - heap.Push(&b.pool, w) -} - -func main() { - flag.Parse() - work := make(chan Request) - for i := 0; i < nRequester; i++ { - go requester(work) - } - NewBalancer().balance(work) -} diff --git a/doc/talks/io2010/decrypt.go b/doc/talks/io2010/decrypt.go deleted file mode 100644 index e63418b1a..000000000 --- a/doc/talks/io2010/decrypt.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2010 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. - -// This code differs from the slides in that it handles errors. - -package main - -import ( - "crypto/aes" - "crypto/cipher" - "compress/gzip" - "io" - "log" - "os" -) - -func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) error { - r, err := os.Open(srcfile) - if err != nil { - return err - } - var w io.Writer - w, err = os.Create(dstfile) - if err != nil { - return err - } - c, err := aes.NewCipher(key) - if err != nil { - return err - } - w = cipher.StreamWriter{S: cipher.NewOFB(c, iv), W: w} - w2, err := gzip.NewWriter(w) - if err != nil { - return err - } - defer w2.Close() - _, err = io.Copy(w2, r) - return err -} - -func DecryptAndGunzip(dstfile, srcfile string, key, iv []byte) error { - f, err := os.Open(srcfile) - if err != nil { - return err - } - defer f.Close() - c, err := aes.NewCipher(key) - if err != nil { - return err - } - r := cipher.StreamReader{S: cipher.NewOFB(c, iv), R: f} - r2, err := gzip.NewReader(r) - if err != nil { - return err - } - w, err := os.Create(dstfile) - if err != nil { - return err - } - defer w.Close() - _, err = io.Copy(w, r2) - return err -} - -func main() { - err := EncryptAndGzip( - "/tmp/passwd.gz", - "/etc/passwd", - make([]byte, 16), - make([]byte, 16), - ) - if err != nil { - log.Fatal(err) - } - err = DecryptAndGunzip( - "/dev/stdout", - "/tmp/passwd.gz", - make([]byte, 16), - make([]byte, 16), - ) - if err != nil { - log.Fatal(err) - } -} diff --git a/doc/talks/io2010/encrypt.go b/doc/talks/io2010/encrypt.go deleted file mode 100644 index 57c888c74..000000000 --- a/doc/talks/io2010/encrypt.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2010 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. - -// This code differs from the slides in that it handles errors. - -package main - -import ( - "crypto/aes" - "crypto/cipher" - "compress/gzip" - "io" - "log" - "os" -) - -func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) error { - r, err := os.Open(srcfile) - if err != nil { - return err - } - var w io.WriteCloser - w, err = os.Create(dstfile) - if err != nil { - return err - } - defer w.Close() - w, err = gzip.NewWriter(w) - if err != nil { - return err - } - defer w.Close() - c, err := aes.NewCipher(key) - if err != nil { - return err - } - _, err = io.Copy(cipher.StreamWriter{S: cipher.NewOFB(c, iv), W: w}, r) - return err -} - -func main() { - err := EncryptAndGzip( - "/tmp/passwd.gz", - "/etc/passwd", - make([]byte, 16), - make([]byte, 16), - ) - if err != nil { - log.Fatal(err) - } -} diff --git a/doc/talks/io2010/eval1.go b/doc/talks/io2010/eval1.go deleted file mode 100644 index 582f43e8e..000000000 --- a/doc/talks/io2010/eval1.go +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2010 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. - -package main - -import ( - "bufio" - "fmt" - "os" - "strconv" - "strings" -) - -// Generic expression parser/evaluator - -type Value interface { - String() string - BinaryOp(op string, y Value) Value -} - -type Parser struct { - precTab map[string]int - newVal func(string) Value - src string - pos int - tok string -} - -const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - -func (p *Parser) stop(c uint8) bool { - switch { - case p.pos >= len(p.src): - return true - case c == '"': - if p.src[p.pos] == '"' { - p.pos++ - return true - } - return false - case strings.IndexRune(alphanum, int(c)) >= 0: - return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0 - } - return true -} - -func (p *Parser) next() { - // skip blanks - for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ { - } - if p.pos >= len(p.src) { - p.tok = "" - return - } - start := p.pos - c := p.src[p.pos] - for p.pos < len(p.src) { - p.pos++ - if p.stop(c) { - break - } - } - p.tok = p.src[start:p.pos] -} - -func (p *Parser) binaryExpr(prec1 int) Value { - x := p.newVal(p.tok) - p.next() - for prec := p.precTab[p.tok]; prec >= prec1; prec-- { - for p.precTab[p.tok] == prec { - op := p.tok - p.next() - y := p.binaryExpr(prec + 1) - x = x.BinaryOp(op, y) - } - } - return x -} - -func Eval(precTab map[string]int, newVal func(string) Value, src string) Value { - var p Parser - p.precTab = precTab - p.newVal = newVal - p.src = src - p.next() - return p.binaryExpr(1) -} - -// Command-line expression evaluator - -func main() { - r := bufio.NewReader(os.Stdin) - for { - fmt.Printf("> ") - line, err := r.ReadString('\n') - if err != nil { - break - } - fmt.Printf("%s\n", Eval(precTab, trace(newVal), line)) - } -} - -// Custom grammar and values - -var precTab = map[string]int{ - "&&": 1, - "||": 2, - "==": 3, - "!=": 3, - "<": 3, - "<=": 3, - ">": 3, - ">=": 3, - "+": 4, - "-": 4, - "*": 5, - "/": 5, - "%": 5, -} - -func newVal(lit string) Value { - x, err := strconv.Atoi(lit) - if err == nil { - return Int(x) - } - b, err := strconv.ParseBool(lit) - if err == nil { - return Bool(b) - } - return Error(fmt.Sprintf("illegal literal '%s'", lit)) -} - -type Error string - -func (e Error) String() string { return string(e) } -func (e Error) BinaryOp(op string, y Value) Value { return e } - -type Int int - -func (x Int) String() string { return strconv.Itoa(int(x)) } -func (x Int) BinaryOp(op string, y Value) Value { - switch y := y.(type) { - case Error: - return y - case Int: - switch op { - case "+": - return x + y - case "-": - return x - y - case "*": - return x * y - case "/": - return x / y - case "%": - return x % y - case "==": - return Bool(x == y) - case "!=": - return Bool(x != y) - case "<": - return Bool(x < y) - case "<=": - return Bool(x <= y) - case ">": - return Bool(x > y) - case ">=": - return Bool(x >= y) - } - } - return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y)) -} - -type Bool bool - -func (x Bool) String() string { return strconv.FormatBool(bool(x)) } -func (x Bool) BinaryOp(op string, y Value) Value { - switch y := y.(type) { - case Error: - return y - case Bool: - switch op { - case "&&": - return Bool(x && y) - case "||": - return Bool(x || y) - case "==": - return Bool(x == y) - case "!=": - return Bool(x != y) - } - } - return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y)) -} - -func trace(newVal func(string) Value) func(string) Value { - return func(s string) Value { - v := newVal(s) - fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v)) - return &traceValue{v} - } -} - -type traceValue struct { - Value -} - -func (x *traceValue) BinaryOp(op string, y Value) Value { - z := x.Value.BinaryOp(op, y.(*traceValue).Value) - fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z)) - return &traceValue{z} -} - -func (x *traceValue) String() string { - s := x.Value.String() - fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s) - return s -} - -func fmtv(v Value) string { - t := fmt.Sprintf("%T", v) - if i := strings.LastIndex(t, "."); i >= 0 { // strip package - t = t[i+1:] - } - return fmt.Sprintf("%s(%#v)", t, v) -} diff --git a/doc/talks/io2010/eval2.go b/doc/talks/io2010/eval2.go deleted file mode 100644 index 6f826e12d..000000000 --- a/doc/talks/io2010/eval2.go +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2010 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. - -package main - -import ( - "bufio" - "fmt" - "os" - "strconv" - "strings" -) - -// Generic expression parser/evaluator - -type Value interface { - String() string - BinaryOp(op string, y Value) Value -} - -type Parser struct { - precTab map[string]int - newVal func(string) Value - src string - pos int - tok string -} - -const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - -func (p *Parser) stop(c uint8) bool { - switch { - case p.pos >= len(p.src): - return true - case c == '"': - if p.src[p.pos] == '"' { - p.pos++ - return true - } - return false - case strings.IndexRune(alphanum, int(c)) >= 0: - return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0 - } - return true -} - -func (p *Parser) next() { - // skip blanks - for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ { - } - if p.pos >= len(p.src) { - p.tok = "" - return - } - start := p.pos - c := p.src[p.pos] - for p.pos < len(p.src) { - p.pos++ - if p.stop(c) { - break - } - } - p.tok = p.src[start:p.pos] -} - -func (p *Parser) binaryExpr(prec1 int) Value { - x := p.newVal(p.tok) - p.next() - for prec := p.precTab[p.tok]; prec >= prec1; prec-- { - for p.precTab[p.tok] == prec { - op := p.tok - p.next() - y := p.binaryExpr(prec + 1) - x = x.BinaryOp(op, y) - } - } - return x -} - -func Eval(precTab map[string]int, newVal func(string) Value, src string) Value { - var p Parser - p.precTab = precTab - p.newVal = newVal - p.src = src - p.next() - return p.binaryExpr(1) -} - -// Command-line expression evaluator - -func main() { - r := bufio.NewReader(os.Stdin) - for { - fmt.Printf("> ") - line, err := r.ReadString('\n') - if err != nil { - break - } - fmt.Printf("%s\n", Eval(precTab, trace(newVal), line)) - } -} - -// Custom grammar and values - -var precTab = map[string]int{ - "&&": 1, - "||": 2, - "==": 3, - "!=": 3, - "<": 3, - "<=": 3, - ">": 3, - ">=": 3, - "+": 4, - "-": 4, - "*": 5, - "/": 5, - "%": 5, -} - -func newVal(lit string) Value { - x, err := strconv.Atoi(lit) - if err == nil { - return Int(x) - } - b, err := strconv.ParseBool(lit) - if err == nil { - return Bool(b) - } - s, err := strconv.Unquote(lit) - if err == nil { - return String(s) - } - return Error(fmt.Sprintf("illegal literal '%s'", lit)) -} - -type Error string - -func (e Error) String() string { return string(e) } -func (e Error) BinaryOp(op string, y Value) Value { return e } - -type Int int - -func (x Int) String() string { return strconv.Itoa(int(x)) } -func (x Int) BinaryOp(op string, y Value) Value { - switch y := y.(type) { - case Error: - return y - case String: - switch op { - case "*": - return String(strings.Repeat(string(y), int(x))) - } - case Int: - switch op { - case "+": - return x + y - case "-": - return x - y - case "*": - return x * y - case "/": - return x / y - case "%": - return x % y - case "==": - return Bool(x == y) - case "!=": - return Bool(x != y) - case "<": - return Bool(x < y) - case "<=": - return Bool(x <= y) - case ">": - return Bool(x > y) - case ">=": - return Bool(x >= y) - } - } - return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y)) -} - -type Bool bool - -func (x Bool) String() string { return strconv.FormatBool(bool(x)) } -func (x Bool) BinaryOp(op string, y Value) Value { - switch y := y.(type) { - case Error: - return y - case Bool: - switch op { - case "&&": - return Bool(x && y) - case "||": - return Bool(x || y) - case "==": - return Bool(x == y) - case "!=": - return Bool(x != y) - } - } - return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y)) -} - -type String string - -func (x String) String() string { return strconv.Quote(string(x)) } -func (x String) BinaryOp(op string, y Value) Value { - switch y := y.(type) { - case Error: - return y - case Int: - switch op { - case "*": - return String(strings.Repeat(string(x), int(y))) - } - case String: - switch op { - case "+": - return x + y - case "<": - return Bool(x < y) - } - } - return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y)) -} - -func trace(newVal func(string) Value) func(string) Value { - return func(s string) Value { - v := newVal(s) - fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v)) - return &traceValue{v} - } -} - -type traceValue struct { - Value -} - -func (x *traceValue) BinaryOp(op string, y Value) Value { - z := x.Value.BinaryOp(op, y.(*traceValue).Value) - fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z)) - return &traceValue{z} -} - -func (x *traceValue) String() string { - s := x.Value.String() - fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s) - return s -} - -func fmtv(v Value) string { - t := fmt.Sprintf("%T", v) - if i := strings.LastIndex(t, "."); i >= 0 { // strip package - t = t[i+1:] - } - return fmt.Sprintf("%s(%#v)", t, v) -} diff --git a/doc/talks/io2010/talk.pdf b/doc/talks/io2010/talk.pdf Binary files differdeleted file mode 100644 index aff42c21d..000000000 --- a/doc/talks/io2010/talk.pdf +++ /dev/null diff --git a/doc/talks/io2011/Real_World_Go.pdf b/doc/talks/io2011/Real_World_Go.pdf Binary files differdeleted file mode 100644 index 2a187116b..000000000 --- a/doc/talks/io2011/Real_World_Go.pdf +++ /dev/null diff --git a/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf b/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf Binary files differdeleted file mode 100644 index ca4702ee9..000000000 --- a/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf +++ /dev/null diff --git a/doc/talks/java-typing.png b/doc/talks/java-typing.png Binary files differdeleted file mode 100644 index 54abf0186..000000000 --- a/doc/talks/java-typing.png +++ /dev/null diff --git a/doc/talks/slidy.css b/doc/talks/slidy.css deleted file mode 100644 index e9ff53218..000000000 --- a/doc/talks/slidy.css +++ /dev/null @@ -1,277 +0,0 @@ -/* http://www.w3.org/Talks/Tools/Slidy/slidy.css - - Copyright (c) 2005 W3C (MIT, ERCIM, Keio), All Rights Reserved. - W3C liability, trademark, document use and software licensing - rules apply, see: - - http://www.w3.org/Consortium/Legal/copyright-documents - http://www.w3.org/Consortium/Legal/copyright-software -*/ -body -{ - margin: 0 0 0 0; - padding: 0 0 0 0; - width: 100%; - height: 100%; - color: black; - background-color: white; - font-family: "Lucida Sans", "Lucida Grande", Lucida, sans-serif; - font-size: 14pt; -} - -.hidden { display: none; visibility: hidden } - -div.toolbar { - position: fixed; z-index: 200; - top: auto; bottom: 0; left: 0; right: 0; - height: 1.2em; text-align: right; - padding-left: 1em; - padding-right: 1em; - font-size: 60%; - color: red; background: rgb(240,240,240); -} - -div.background { - display: none; -} - -div.handout { - margin-left: 20px; - margin-right: 20px; -} - -div.slide.titlepage { - color: white; - background: black; - text-align: center; -} - -div.slide { - z-index: 20; - margin: 0 0 0 0; - padding-top: 0; - padding-bottom: 0; - padding-left: 20px; - padding-right: 20px; - border-width: 0; - top: 0; - bottom: 0; - left: 0; - right: 0; - line-height: 120%; - background-color: transparent; -} - -/* this rule is hidden from IE 6 and below which don't support + selector */ -div.slide + div[class].slide { page-break-before: always;} - -div.slide h1 { - padding-left: 20px; - padding-right: 20px; - padding-top: 10px; - padding-bottom: 10px; - margin-top: 0; - margin-left: 0; - margin-right: 0; - margin-bottom: 0.5em; - border-bottom: 4px solid #36c; - display: block; - font-size: 160%; - line-height: 1.2em; -} - -div.slide h2 { - font-size:120%; - line-height: 1.2em; -} - -div.toc { - position: absolute; - top: auto; - bottom: 4em; - left: 4em; - right: auto; - width: 60%; - max-width: 30em; - height: 30em; - border: solid thin black; - padding: 1em; - background: rgb(240,240,240); - color: black; - z-index: 300; - overflow: auto; - display: block; - visibility: visible; -} - -div.toc-heading { - width: 100%; - border-bottom: solid 1px rgb(180,180,180); - margin-bottom: 1em; - text-align: center; -} - -pre { - font-size: 120%; - font-weight: bold; - line-height: 140%; - padding-top: 0.2em; - padding-bottom: 0.2em; - padding-left: 1em; - padding-right: 1em; -/* - border-style: solid; - border-left-width: 1em; - border-top-width: thin; - border-right-width: thin; - border-bottom-width: thin; - border-color: #95ABD0; -*/ - color: #0F398D; - background-color: #fff8f8; -} - -@media print { - div.slide { - display: block; - visibility: visible; - position: relative; - border-top-style: solid; - border-top-width: thin; - border-top-color: black; - } - div.slide pre { font-size: 60%; padding-left: 0.5em; } - div.handout { display: block; visibility: visible; } -} - -blockquote { font-style: italic } - -img { background-color: transparent } - -p.copyright { font-size: smaller } - -.center { text-align: center } -.footnote { font-size: smaller; margin-left: 2em; } - -a img { border-width: 0; border-style: none } - -a:visited { color: navy } -a:link { color: navy } -a:hover { color: red; text-decoration: underline } -a:active { color: red; text-decoration: underline } - -a {text-decoration: none} -.navbar a:link {color: white} -.navbar a:visited {color: yellow} -.navbar a:active {color: red} -.navbar a:hover {color: red} - -ul { list-style-type: square; } -ul ul { list-style-type: disc; } -ul ul ul { list-style-type: circle; } -ul ul ul ul { list-style-type: disc; } -li { margin-left: 2em; margin-top: 0.5em; } -li li { font-size: 85%; font-style: italic } -li li li { font-size: 85%; font-style: normal } - -div dt -{ - margin-left: 0; - margin-top: 1em; - margin-bottom: 0.5em; - font-weight: bold; -} -div dd -{ - margin-left: 2em; - margin-bottom: 0.5em; -} - - -p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table { - margin-left: 1em; - margin-right: 1em; -} - -p.subhead { font-weight: bold; margin-top: 2em; } - -p.smaller { font-size: smaller } - -td,th { padding: 0.2em } - -ul { - margin: 0.5em 1.5em 0.5em 1.5em; - padding: 0; -} - -ol { - margin: 0.5em 1.5em 0.5em 1.5em; - padding: 0; -} - -ul { list-style-type: square; } -ul ul { list-style-type: disc; } -ul ul ul { list-style-type: circle; } -ul ul ul ul { list-style-type: disc; } - -ul li { - list-style: square; - //margin: 0.1em 0em 0.6em 0; - padding: 0 0 0 0; - line-height: 140%; -} - -ol li { - margin: 0.1em 0em 0.6em 1.5em; - padding: 0 0 0 0px; - line-height: 140%; - list-style-type: decimal; -} - -li ul li { - font-size: 85%; - font-style: italic; - list-style-type: disc; - background: transparent; - padding: 0 0 0 0; -} -li li ul li { - font-size: 85%; - font-style: normal; - list-style-type: circle; - background: transparent; - padding: 0 0 0 0; -} -li li li ul li { - list-style-type: disc; - background: transparent; - padding: 0 0 0 0; -} - -li ol li { - list-style-type: decimal; -} - - -li li ol li { - list-style-type: decimal; -} - -/* - setting class="outline on ol or ul makes it behave as an - ouline list where blocklevel content in li elements is - hidden by default and can be expanded or collapsed with - mouse click. Set class="expand" on li to override default -*/ - -ol.outline li:hover { cursor: pointer } -ol.outline li.nofold:hover { cursor: default } - -ul.outline li:hover { cursor: pointer } -ul.outline li.nofold:hover { cursor: default } - -ol.outline { list-style:decimal; } -ol.outline ol { list-style-type:lower-alpha } - -/* for slides with class "title" in table of contents */ -a.titleslide { font-weight: bold; font-style: italic } diff --git a/doc/talks/slidy.js b/doc/talks/slidy.js deleted file mode 100644 index 6a5561a6c..000000000 --- a/doc/talks/slidy.js +++ /dev/null @@ -1,2772 +0,0 @@ -/* http://www.w3.org/Talks/Tools/Slidy/slidy.js - - Copyright (c) 2005 W3C (MIT, ERCIM, Keio), All Rights Reserved. - W3C liability, trademark, document use and software licensing - rules apply, see: - - http://www.w3.org/Consortium/Legal/copyright-documents - http://www.w3.org/Consortium/Legal/copyright-software -*/ - -var ns_pos = (typeof window.pageYOffset!='undefined'); -var khtml = ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false); -var opera = ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false); -var ie7 = (!ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1); - -window.onload = startup; // equivalent to onload on body element - -// IE only event handlers to ensure all slides are printed -// I don't yet know how to emulate these for other browsers -window.onbeforeprint = beforePrint; -window.onafterprint = afterPrint; - -// hack to hide slides while loading -setTimeout(hideAll, 50); - -function hideAll() -{ - if (document.body) - document.body.style.visibility = "hidden"; - else - setTimeout(hideAll, 50); -} - -var slidenum = 0; // integer slide count: 0, 1, 2, ... -var slides; // set to array of slide div's -var slideNumElement; // element containing slide number -var notes; // set to array of handout div's -var backgrounds; // set to array of background div's -var toolbar; // element containing toolbar -var title; // document title -var lastShown = null; // last incrementally shown item -var eos = null; // span element for end of slide indicator -var toc = null; // table of contents -var outline = null; // outline element with the focus -var selectedTextLen; // length of drag selection on document - -var viewAll = 0; // 1 to view all slides + handouts -var wantToolbar = 1; // 0 if toolbar isn't wanted -var mouseClickEnabled = true; // enables left click for next slide -var scrollhack = 0; // IE work around for position: fixed - -var helpAnchor; // used for keyboard focus hack in showToolbar() -var helpPage = "http://www.w3.org/Talks/Tools/Slidy/help.html"; -var helpText = "Navigate with mouse click, space bar, Cursor Left/Right, " + - "or Pg Up and Pg Dn. Use S and B to change font size."; - -var sizeIndex = 0; -var sizeAdjustment = 0; -var sizes = new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt", - "22pt", "24pt", "26pt", "28pt", "30pt", "32pt"); - -var okayForIncremental = incrementalElementList(); - -// needed for efficient resizing -var lastWidth = 0; -var lastHeight = 0; - -// Needed for cross browser support for relative width/height on -// object elements. The work around is to save width/height attributes -// and then to recompute absolute width/height dimensions on resizing -var objects; - -// updated to language specified by html file -var lang = "en"; - -//var localize = {}; - -// for each language there is an associative array -var strings_es = { - "slide":"pág.", - "help?":"Ayuda", - "contents?":"Índice", - "table of contents":"tabla de contenidos", - "Table of Contents":"Tabla de Contenidos", - "restart presentation":"Reiniciar presentación", - "restart?":"Inicio" - }; - -strings_es[helpText] = - "Utilice el ratón, barra espaciadora, teclas Izda/Dhca, " + - "o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente."; - -var strings_nl = { - "slide":"pagina", - "help?":"Help?", - "contents?":"Inhoud?", - "table of contents":"inhoudsopgave", - "Table of Contents":"Inhoudsopgave", - "restart presentation":"herstart presentatie", - "restart?":"Herstart?" - }; - -strings_nl[helpText] = - "Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " + - "of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen."; - -var strings_de = { - "slide":"Seite", - "help?":"Hilfe", - "contents?":"Übersicht", - "table of contents":"Inhaltsverzeichnis", - "Table of Contents":"Inhaltsverzeichnis", - "restart presentation":"Präsentation neu starten", - "restart?":"Neustart" - }; - -strings_de[helpText] = - "Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts" + - "oder Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse."; - -var strings_pl = { - "slide":"slajd", - "help?":"pomoc?", - "contents?":"spis treści?", - "table of contents":"spis treści", - "Table of Contents":"Spis Treści", - "restart presentation":"Restartuj prezentację", - "restart?":"restart?" - }; - -strings_pl[helpText] = - "Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" + - "lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki."; - -var strings_fr = { - "slide":"page", - "help?":"Aide", - "contents?":"Index", - "table of contents":"table des matières", - "Table of Contents":"Table des matières", - "restart presentation":"Recommencer l'exposé", - "restart?":"Début" - }; - -strings_fr[helpText] = - "Naviguez avec la souris, la barre d'espace, les flèches" + - "gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " + - "les touches S et B pour modifier la taille de la police."; - -var strings_hu = { - "slide":"oldal", - "help?":"segítség", - "contents?":"tartalom", - "table of contents":"tartalomjegyzék", - "Table of Contents":"Tartalomjegyzék", - "restart presentation":"bemutató újraindítása", - "restart?":"újraindítás" - }; - -strings_hu[helpText] = - "Az oldalak közti lépkedéshez kattintson az egérrel, vagy használja a szóköz, a bal, vagy a jobb nyíl, " + - "illetve a Page Down, Page Up billentyűket. Az S és a B billentyűkkel változtathatja a szöveg méretét."; - -var strings_it = { - "slide":"pag.", - "help?":"Aiuto", - "contents?":"Indice", - "table of contents":"indice", - "Table of Contents":"Indice", - "restart presentation":"Ricominciare la presentazione", - "restart?":"Inizio" - }; - -strings_it[helpText] = - "Navigare con mouse, barra spazio, frecce sinistra/destra o " + - "PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri."; - -var strings_el = { - "slide":"σελίδα", - "help?":"βοήθεια;", - "contents?":"περιεχόμενα;", - "table of contents":"πίνακας περιεχομένων", - "Table of Contents":"Πίνακας Περιεχομένων", - "restart presentation":"επανεκκίνηση παρουσίασης", - "restart?":"επανεκκίνηση;" - }; - -strings_el[helpText] = - "Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " + - "ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " + - "το μέγεθος της γραμματοσειράς."; - -var strings_ja = { - "slide":"スライド", - "help?":"ヘルプ", - "contents?":"目次", - "table of contents":"目次を表示", - "Table of Contents":"目次", - "restart presentation":"最初から再生", - "restart?":"最初から" -}; - -strings_ja[helpText] = - "マウス左クリック ・ スペース ・ 左右キー " + - "または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更"; - - -// each such language array is declared in the localize array -// used indirectly as in help.innerHTML = "help".localize(); -var localize = { - "es":strings_es, - "nl":strings_nl, - "de":strings_de, - "pl":strings_pl, - "fr":strings_fr, - "hu":strings_hu, - "it":strings_it, - "el":strings_el, - "jp":strings_ja - }; - -/* general initialization */ -function startup() -{ - // find human language from html element - // for use in localizing strings - lang = document.body.parentNode.getAttribute("lang"); - - if (!lang) - lang = document.body.parentNode.getAttribute("xml:lang"); - - if (!lang) - lang = "en"; - - document.body.style.visibility = "visible"; - title = document.title; - toolbar = addToolbar(); - wrapImplicitSlides(); - slides = collectSlides(); - notes = collectNotes(); - objects = document.body.getElementsByTagName("object"); - backgrounds = collectBackgrounds(); - patchAnchors(); - - slidenum = findSlideNumber(location.href); - window.offscreenbuffering = true; - sizeAdjustment = findSizeAdjust(); - hideImageToolbar(); // suppress IE image toolbar popup - initOutliner(); // activate fold/unfold support - - if (slides.length > 0) - { - var slide = slides[slidenum]; - slide.style.position = "absolute"; - - if (slidenum > 0) - { - setVisibilityAllIncremental("visible"); - lastShown = previousIncrementalItem(null); - setEosStatus(true); - } - else - { - lastShown = null; - setVisibilityAllIncremental("hidden"); - setEosStatus(!nextIncrementalItem(lastShown)); - } - - setLocation(); - } - - toc = tableOfContents(); - hideTableOfContents(); - - // bind event handlers - document.onclick = mouseButtonClick; - document.onmouseup = mouseButtonUp; - document.onkeydown = keyDown; - window.onresize = resized; - window.onscroll = scrolled; - singleSlideView(); - - setLocation(); - resized(); - - if (ie7) - setTimeout("ieHack()", 100); - - showToolbar(); -} - -// add localize method to all strings for use -// as in help.innerHTML = "help".localize(); -String.prototype.localize = function() -{ - if (this == "") - return this; - - // try full language code, e.g. en-US - var s, lookup = localize[lang]; - - if (lookup) - { - s = lookup[this]; - - if (s) - return s; - } - - // try en if undefined for en-US - var lg = lang.split("-"); - - if (lg.length > 1) - { - lookup = localize[lg[0]]; - - if (lookup) - { - s = lookup[this]; - - if (s) - return s; - } - } - - // otherwise string as is - return this; -} - -// suppress IE's image toolbar pop up -function hideImageToolbar() -{ - if (!ns_pos) - { - var images = document.getElementsByTagName("IMG"); - - for (var i = 0; i < images.length; ++i) - images[i].setAttribute("galleryimg", "no"); - } -} - -// hack to persuade IE to compute correct document height -// as needed for simulating fixed positioning of toolbar -function ieHack() -{ - window.resizeBy(0,-1); - window.resizeBy(0, 1); -} - -// Firefox reload SVG bug work around -function reload(e) -{ - if (!e) - var e = window.event; - - hideBackgrounds(); - setTimeout("document.reload();", 100); - - stopPropagation(e); - e.cancel = true; - e.returnValue = false; - - return false; -} - -// Safari and Konqueror don't yet support getComputedStyle() -// and they always reload page when location.href is updated -function isKHTML() -{ - var agent = navigator.userAgent; - return (agent.indexOf("KHTML") >= 0 ? true : false); -} - -function resized() -{ - var width = 0; - - if ( typeof( window.innerWidth ) == 'number' ) - width = window.innerWidth; // Non IE browser - else if (document.documentElement && document.documentElement.clientWidth) - width = document.documentElement.clientWidth; // IE6 - else if (document.body && document.body.clientWidth) - width = document.body.clientWidth; // IE4 - - var height = 0; - - if ( typeof( window.innerHeight ) == 'number' ) - height = window.innerHeight; // Non IE browser - else if (document.documentElement && document.documentElement.clientHeight) - height = document.documentElement.clientHeight; // IE6 - else if (document.body && document.body.clientHeight) - height = document.body.clientHeight; // IE4 - - if (height && (width/height > 1.05*1024/768)) - { - width = height * 1024.0/768; - } - - // IE fires onresize even when only font size is changed! - // so we do a check to avoid blocking < and > actions - if (width != lastWidth || height != lastHeight) - { - if (width >= 1100) - sizeIndex = 5; // 4 - else if (width >= 1000) - sizeIndex = 4; // 3 - else if (width >= 800) - sizeIndex = 3; // 2 - else if (width >= 600) - sizeIndex = 2; // 1 - else if (width) - sizeIndex = 0; - - // add in font size adjustment from meta element e.g. - // <meta name="font-size-adjustment" content="-2" /> - // useful when slides have too much content ;-) - - if (0 <= sizeIndex + sizeAdjustment && - sizeIndex + sizeAdjustment < sizes.length) - sizeIndex = sizeIndex + sizeAdjustment; - - // enables cross browser use of relative width/height - // on object elements for use with SVG and Flash media - adjustObjectDimensions(width, height); - - document.body.style.fontSize = sizes[sizeIndex]; - - lastWidth = width; - lastHeight = height; - - // force reflow to work around Mozilla bug - //if (ns_pos) - { - var slide = slides[slidenum]; - hideSlide(slide); - showSlide(slide); - } - - // force correct positioning of toolbar - refreshToolbar(200); - } -} - -function scrolled() -{ - if (toolbar && !ns_pos && !ie7) - { - hackoffset = scrollXOffset(); - // hide toolbar - toolbar.style.display = "none"; - - // make it reappear later - if (scrollhack == 0 && !viewAll) - { - setTimeout(showToolbar, 1000); - scrollhack = 1; - } - } -} - -// used to ensure IE refreshes toolbar in correct position -function refreshToolbar(interval) -{ - if (!ns_pos && !ie7) - { - hideToolbar(); - setTimeout(showToolbar, interval); - } -} - -// restores toolbar after short delay -function showToolbar() -{ - if (wantToolbar) - { - if (!ns_pos) - { - // adjust position to allow for scrolling - var xoffset = scrollXOffset(); - toolbar.style.left = xoffset; - toolbar.style.right = xoffset; - - // determine vertical scroll offset - //var yoffset = scrollYOffset(); - - // bottom is doc height - window height - scroll offset - //var bottom = documentHeight() - lastHeight - yoffset - - //if (yoffset > 0 || documentHeight() > lastHeight) - // bottom += 16; // allow for height of scrollbar - - toolbar.style.bottom = 0; //bottom; - } - - toolbar.style.display = "block"; - toolbar.style.visibility = "visible"; - } - - scrollhack = 0; - - - // set the keyboard focus to the help link on the - // toolbar to ensure that document has the focus - // IE doesn't always work with window.focus() - // and this hack has benefit of Enter for help - - try - { - if (!opera) - helpAnchor.focus(); - } - catch (e) - { - } -} - -function test() -{ - var s = "docH: " + documentHeight() + - " winH: " + lastHeight + - " yoffset: " + scrollYOffset() + - " toolbot: " + (documentHeight() - lastHeight - scrollYOffset()); - - //alert(s); - - var slide = slides[slidenum]; - // IE getAttribute requires "class" to be "className" - var name = ns_pos ? "class" : "className"; - var style = (slide.currentStyle ? slide.currentStyle["backgroundColor"] : - document.defaultView.getComputedStyle(slide, '').getPropertyValue("background-color")); - alert("class='" + slide.getAttribute(name) + "' backgroundColor: " + style); -} - -function hideToolbar() -{ - toolbar.style.display = "none"; - toolbar.style.visibility = "hidden"; - window.focus(); -} - -// invoked via F key -function toggleToolbar() -{ - if (!viewAll) - { - if (toolbar.style.display == "none") - { - toolbar.style.display = "block"; - toolbar.style.visibility = "visible"; - wantToolbar = 1; - } - else - { - toolbar.style.display = "none"; - toolbar.style.visibility = "hidden"; - wantToolbar = 0; - } - } -} - -function scrollXOffset() -{ - if (window.pageXOffset) - return self.pageXOffset; - - if (document.documentElement && - document.documentElement.scrollLeft) - return document.documentElement.scrollLeft; - - if (document.body) - return document.body.scrollLeft; - - return 0; -} - - -function scrollYOffset() -{ - if (window.pageYOffset) - return self.pageYOffset; - - if (document.documentElement && - document.documentElement.scrollTop) - return document.documentElement.scrollTop; - - if (document.body) - return document.body.scrollTop; - - return 0; -} - -// looking for a way to determine height of slide content -// the slide itself is set to the height of the window -function optimizeFontSize() -{ - var slide = slides[slidenum]; - - //var dh = documentHeight(); //getDocHeight(document); - var dh = slide.scrollHeight; - var wh = getWindowHeight(); - var u = 100 * dh / wh; - - alert("window utilization = " + u + "% (doc " - + dh + " win " + wh + ")"); -} - -function getDocHeight(doc) // from document object -{ - if (!doc) - doc = document; - - if (doc && doc.body && doc.body.offsetHeight) - return doc.body.offsetHeight; // ns/gecko syntax - - if (doc && doc.body && doc.body.scrollHeight) - return doc.body.scrollHeight; - - alert("couldn't determine document height"); -} - -function getWindowHeight() -{ - if ( typeof( window.innerHeight ) == 'number' ) - return window.innerHeight; // Non IE browser - - if (document.documentElement && document.documentElement.clientHeight) - return document.documentElement.clientHeight; // IE6 - - if (document.body && document.body.clientHeight) - return document.body.clientHeight; // IE4 -} - - - -function documentHeight() -{ - var sh, oh; - - sh = document.body.scrollHeight; - oh = document.body.offsetHeight; - - if (sh && oh) - { - return (sh > oh ? sh : oh); - } - - // no idea! - return 0; -} - -function smaller() -{ - if (sizeIndex > 0) - { - --sizeIndex; - } - - toolbar.style.display = "none"; - document.body.style.fontSize = sizes[sizeIndex]; - var slide = slides[slidenum]; - hideSlide(slide); - showSlide(slide); - setTimeout(showToolbar, 300); -} - -function bigger() -{ - if (sizeIndex < sizes.length - 1) - { - ++sizeIndex; - } - - toolbar.style.display = "none"; - document.body.style.fontSize = sizes[sizeIndex]; - var slide = slides[slidenum]; - hideSlide(slide); - showSlide(slide); - setTimeout(showToolbar, 300); -} - -// enables cross browser use of relative width/height -// on object elements for use with SVG and Flash media -// with thanks to Ivan Herman for the suggestion -function adjustObjectDimensions(width, height) -{ - for( var i = 0; i < objects.length; i++ ) - { - var obj = objects[i]; - var mimeType = obj.getAttribute("type"); - - if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash") - { - if ( !obj.initialWidth ) - obj.initialWidth = obj.getAttribute("width"); - - if ( !obj.initialHeight ) - obj.initialHeight = obj.getAttribute("height"); - - if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" ) - { - var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1)); - var newW = width * (w/100.0); - obj.setAttribute("width",newW); - } - - if ( obj.initialHeight && obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" ) - { - var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1)); - var newH = height * (h/100.0); - obj.setAttribute("height", newH); - } - } - } -} - -function cancel(event) -{ - if (event) - { - event.cancel = true; - event.returnValue = false; - - if (event.preventDefault) - event.preventDefault(); - } - - return false; -} - -// See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes -function keyDown(event) -{ - var key; - - if (!event) - var event = window.event; - - // kludge around NS/IE differences - if (window.event) - key = window.event.keyCode; - else if (event.which) - key = event.which; - else - return true; // Yikes! unknown browser - - // ignore event if key value is zero - // as for alt on Opera and Konqueror - if (!key) - return true; - - // check for concurrent control/command/alt key - // but are these only present on mouse events? - - if (event.ctrlKey || event.altKey || event.metaKey) - return true; - - // dismiss table of contents if visible - if (isShownToc() && key != 9 && key != 16 && key != 38 && key != 40) - { - hideTableOfContents(); - - if (key == 27 || key == 84 || key == 67) - return cancel(event); - } - - if (key == 34) // Page Down - { - nextSlide(false); - return cancel(event); - } - else if (key == 33) // Page Up - { - previousSlide(false); - return cancel(event); - } - else if (key == 32) // space bar - { - nextSlide(true); - return cancel(event); - } - else if (key == 37 || key == 38) // Left arrow || Up arrow - { - previousSlide(!event.shiftKey); - return cancel(event); - } - else if (key == 36) // Home - { - firstSlide(); - return cancel(event); - } - else if (key == 35) // End - { - lastSlide(); - return cancel(event); - } - else if (key == 39 || key == 40) // Right arrow || Down arrow - { - nextSlide(!event.shiftKey); - return cancel(event); - } - else if (key == 13) // Enter - { - if (outline) - { - if (outline.visible) - fold(outline); - else - unfold(outline); - - return cancel(event); - } - } - else if (key == 188) // < for smaller fonts - { - smaller(); - return cancel(event); - } - else if (key == 190) // > for larger fonts - { - bigger(); - return cancel(event); - } - else if (key == 189 || key == 109) // - for smaller fonts - { - smaller(); - return cancel(event); - } - else if (key == 187 || key == 191 || key == 107) // = + for larger fonts - { - bigger(); - return cancel(event); - } - else if (key == 83) // S for smaller fonts - { - smaller(); - return cancel(event); - } - else if (key == 66) // B for larger fonts - { - bigger(); - return cancel(event); - } - else if (key == 90) // Z for last slide - { - lastSlide(); - return cancel(event); - } - else if (key == 70) // F for toggle toolbar - { - toggleToolbar(); - return cancel(event); - } - else if (key == 65) // A for toggle view single/all slides - { - toggleView(); - return cancel(event); - } - else if (key == 75) // toggle action of left click for next page - { - mouseClickEnabled = !mouseClickEnabled; - alert((mouseClickEnabled ? "enabled" : "disabled") + " mouse click advance"); - return cancel(event); - } - else if (key == 84 || key == 67) // T or C for table of contents - { - if (toc) - showTableOfContents(); - - return cancel(event); - } - else if (key == 72) // H for help - { - window.location = helpPage; - return cancel(event); - } - - //else if (key == 93) // Windows menu key - //alert("lastShown is " + lastShown); - //else alert("key code is "+ key); - - - return true; -} - -// make note of length of selected text -// as this evaluates to zero in click event -function mouseButtonUp(e) -{ - selectedTextLen = getSelectedText().length; -} - -// right mouse button click is reserved for context menus -// it is more reliable to detect rightclick than leftclick -function mouseButtonClick(e) -{ - var rightclick = false; - var leftclick = false; - var middleclick = false; - var target; - - if (!e) - var e = window.event; - - if (e.target) - target = e.target; - else if (e.srcElement) - target = e.srcElement; - - // work around Safari bug - if (target.nodeType == 3) - target = target.parentNode; - - if (e.which) // all browsers except IE - { - leftclick = (e.which == 1); - middleclick = (e.which == 2); - rightclick = (e.which == 3); - } - else if (e.button) - { - // Konqueror gives 1 for left, 4 for middle - // IE6 gives 0 for left and not 1 as I expected - - if (e.button == 4) - middleclick = true; - - // all browsers agree on 2 for right button - rightclick = (e.button == 2); - } - else leftclick = true; - - // dismiss table of contents - hideTableOfContents(); - - if (selectedTextLen > 0) - { - stopPropagation(e); - e.cancel = true; - e.returnValue = false; - return false; - } - - // check if target is something that probably want's clicks - // e.g. embed, object, input, textarea, select, option - - if (mouseClickEnabled && leftclick && - target.nodeName != "EMBED" && - target.nodeName != "OBJECT" && - target.nodeName != "INPUT" && - target.nodeName != "TEXTAREA" && - target.nodeName != "SELECT" && - target.nodeName != "OPTION") - { - nextSlide(true); - stopPropagation(e); - e.cancel = true; - e.returnValue = false; - } -} - -function previousSlide(incremental) -{ - if (!viewAll) - { - var slide; - - if ((incremental || slidenum == 0) && lastShown != null) - { - lastShown = hidePreviousItem(lastShown); - setEosStatus(false); - } - else if (slidenum > 0) - { - slide = slides[slidenum]; - hideSlide(slide); - - slidenum = slidenum - 1; - slide = slides[slidenum]; - setVisibilityAllIncremental("visible"); - lastShown = previousIncrementalItem(null); - setEosStatus(true); - showSlide(slide); - } - - setLocation(); - - if (!ns_pos) - refreshToolbar(200); - } -} - -function nextSlide(incremental) -{ - if (!viewAll) - { - var slide, last = lastShown; - - if (incremental || slidenum == slides.length - 1) - lastShown = revealNextItem(lastShown); - - if ((!incremental || lastShown == null) && slidenum < slides.length - 1) - { - slide = slides[slidenum]; - hideSlide(slide); - - slidenum = slidenum + 1; - slide = slides[slidenum]; - lastShown = null; - setVisibilityAllIncremental("hidden"); - showSlide(slide); - } - else if (!lastShown) - { - if (last && incremental) - lastShown = last; - } - - setLocation(); - - setEosStatus(!nextIncrementalItem(lastShown)); - - if (!ns_pos) - refreshToolbar(200); - } -} - -// to first slide with nothing revealed -// i.e. state at start of presentation -function firstSlide() -{ - if (!viewAll) - { - var slide; - - if (slidenum != 0) - { - slide = slides[slidenum]; - hideSlide(slide); - - slidenum = 0; - slide = slides[slidenum]; - lastShown = null; - setVisibilityAllIncremental("hidden"); - showSlide(slide); - } - - setEosStatus(!nextIncrementalItem(lastShown)); - setLocation(); - } -} - - -// to last slide with everything revealed -// i.e. state at end of presentation -function lastSlide() -{ - if (!viewAll) - { - var slide; - - lastShown = null; //revealNextItem(lastShown); - - if (lastShown == null && slidenum < slides.length - 1) - { - slide = slides[slidenum]; - hideSlide(slide); - slidenum = slides.length - 1; - slide = slides[slidenum]; - setVisibilityAllIncremental("visible"); - lastShown = previousIncrementalItem(null); - - showSlide(slide); - } - else - { - setVisibilityAllIncremental("visible"); - lastShown = previousIncrementalItem(null); - } - - setEosStatus(true); - setLocation(); - } -} - -function setEosStatus(state) -{ - if (eos) - eos.style.color = (state ? "rgb(240,240,240)" : "red"); -} - -function showSlide(slide) -{ - syncBackground(slide); - window.scrollTo(0,0); - slide.style.visibility = "visible"; - slide.style.display = "block"; -} - -function hideSlide(slide) -{ - slide.style.visibility = "hidden"; - slide.style.display = "none"; -} - -function beforePrint() -{ - showAllSlides(); - hideToolbar(); -} - -function afterPrint() -{ - if (!viewAll) - { - singleSlideView(); - showToolbar(); - } -} - -function printSlides() -{ - beforePrint(); - window.print(); - afterPrint(); -} - -function toggleView() -{ - if (viewAll) - { - singleSlideView(); - showToolbar(); - viewAll = 0; - } - else - { - showAllSlides(); - hideToolbar(); - viewAll = 1; - } -} - -// prepare for printing -function showAllSlides() -{ - var slide; - - for (var i = 0; i < slides.length; ++i) - { - slide = slides[i]; - - slide.style.position = "relative"; - slide.style.borderTopStyle = "solid"; - slide.style.borderTopWidth = "thin"; - slide.style.borderTopColor = "black"; - - try { - if (i == 0) - slide.style.pageBreakBefore = "avoid"; - else - slide.style.pageBreakBefore = "always"; - } - catch (e) - { - //do nothing - } - - setVisibilityAllIncremental("visible"); - showSlide(slide); - } - - var note; - - for (var i = 0; i < notes.length; ++i) - { - showSlide(notes[i]); - } - - // no easy way to render background under each slide - // without duplicating the background divs for each slide - // therefore hide backgrounds to avoid messing up slides - hideBackgrounds(); -} - -// restore after printing -function singleSlideView() -{ - var slide; - - for (var i = 0; i < slides.length; ++i) - { - slide = slides[i]; - - slide.style.position = "absolute"; - - if (i == slidenum) - { - slide.style.borderStyle = "none"; - showSlide(slide); - } - else - { - slide.style.borderStyle = "none"; - hideSlide(slide); - } - } - - setVisibilityAllIncremental("visible"); - lastShown = previousIncrementalItem(null); - - var note; - - for (var i = 0; i < notes.length; ++i) - { - hideSlide(notes[i]); - } -} - -// the string str is a whitespace separated list of tokens -// test if str contains a particular token, e.g. "slide" -function hasToken(str, token) -{ - if (str) - { - // define pattern as regular expression - var pattern = /\w+/g; - - // check for matches - // place result in array - var result = str.match(pattern); - - // now check if desired token is present - for (var i = 0; i < result.length; i++) - { - if (result[i] == token) - return true; - } - } - - return false; -} - -function getClassList(element) -{ - if (typeof window.pageYOffset =='undefined') - return element.getAttribute("className"); - - return element.getAttribute("class"); -} - -function hasClass(element, name) -{ - var regexp = new RegExp("(^| )" + name + "\W*"); - - if (regexp.test(getClassList(element))) - return true; - - return false; - -} - -function removeClass(element, name) -{ - // IE getAttribute requires "class" to be "className" - var clsname = ns_pos ? "class" : "className"; - var clsval = element.getAttribute(clsname); - - var regexp = new RegExp("(^| )" + name + "\W*"); - - if (clsval) - { - clsval = clsval.replace(regexp, ""); - element.setAttribute(clsname, clsval); - } -} - -function addClass(element, name) -{ - if (!hasClass(element, name)) - { - // IE getAttribute requires "class" to be "className" - var clsname = ns_pos ? "class" : "className"; - var clsval = element.getAttribute(clsname); - element.setAttribute(clsname, (clsval ? clsval + " " + name : name)); - } -} - -// wysiwyg editors make it hard to use div elements -// e.g. amaya loses the div when you copy and paste -// this function wraps div elements around implicit -// slides which start with an h1 element and continue -// up to the next heading or div element -function wrapImplicitSlides() -{ - var i, heading, node, next, div; - var headings = document.getElementsByTagName("h1"); - - if (!headings) - return; - - for (i = 0; i < headings.length; ++i) - { - heading = headings[i]; - - if (heading.parentNode != document.body) - continue; - - node = heading.nextSibling; - - div = document.createElement("div"); - div.setAttribute((ns_pos ? "class" : "className"), "slide"); - document.body.replaceChild(div, heading); - div.appendChild(heading); - - while (node) - { - if (node.nodeType == 1 && // an element - (node.nodeName == "H1" || - node.nodeName == "h1" || - node.nodeName == "DIV" || - node.nodeName == "div")) - break; - - next = node.nextSibling; - node = document.body.removeChild(node); - div.appendChild(node); - node = next; - } - } -} - -// return new array of all slides -function collectSlides() -{ - var slides = new Array(); - var divs = document.body.getElementsByTagName("div"); - - for (var i = 0; i < divs.length; ++i) - { - div = divs.item(i); - - if (hasClass(div, "slide")) - { - // add slide to collection - slides[slides.length] = div; - - // hide each slide as it is found - div.style.display = "none"; - div.style.visibility = "hidden"; - - // add dummy <br/> at end for scrolling hack - var node1 = document.createElement("br"); - div.appendChild(node1); - var node2 = document.createElement("br"); - div.appendChild(node2); - } - else if (hasClass(div, "background")) - { // work around for Firefox SVG reload bug - // which otherwise replaces 1st SVG graphic with 2nd - div.style.display = "block"; - } - } - - return slides; -} - -// return new array of all <div class="handout"> -function collectNotes() -{ - var notes = new Array(); - var divs = document.body.getElementsByTagName("div"); - - for (var i = 0; i < divs.length; ++i) - { - div = divs.item(i); - - if (hasClass(div, "handout")) - { - // add slide to collection - notes[notes.length] = div; - - // hide handout notes as they are found - div.style.display = "none"; - div.style.visibility = "hidden"; - } - } - - return notes; -} - -// return new array of all <div class="background"> -// including named backgrounds e.g. class="background titlepage" -function collectBackgrounds() -{ - var backgrounds = new Array(); - var divs = document.body.getElementsByTagName("div"); - - for (var i = 0; i < divs.length; ++i) - { - div = divs.item(i); - - if (hasClass(div, "background")) - { - // add slide to collection - backgrounds[backgrounds.length] = div; - - // hide named backgrounds as they are found - // e.g. class="background epilog" - if (getClassList(div) != "background") - { - div.style.display = "none"; - div.style.visibility = "hidden"; - } - } - } - - return backgrounds; -} - -// show just the backgrounds pertinent to this slide -function syncBackground(slide) -{ - var background; - var bgColor; - - if (slide.currentStyle) - bgColor = slide.currentStyle["backgroundColor"]; - else if (document.defaultView) - { - var styles = document.defaultView.getComputedStyle(slide,null); - - if (styles) - bgColor = styles.getPropertyValue("background-color"); - else // broken implementation probably due Safari or Konqueror - { - //alert("defective implementation of getComputedStyle()"); - bgColor = "transparent"; - } - } - else - bgColor == "transparent"; - - if (bgColor == "transparent") - { - var slideClass = getClassList(slide); - - for (var i = 0; i < backgrounds.length; i++) - { - background = backgrounds[i]; - - var bgClass = getClassList(background); - - if (matchingBackground(slideClass, bgClass)) - { - background.style.display = "block"; - background.style.visibility = "visible"; - } - else - { - background.style.display = "none"; - background.style.visibility = "hidden"; - } - } - } - else // forcibly hide all backgrounds - hideBackgrounds(); -} - -function hideBackgrounds() -{ - for (var i = 0; i < backgrounds.length; i++) - { - background = backgrounds[i]; - background.style.display = "none"; - background.style.visibility = "hidden"; - } -} - -// compare classes for slide and background -function matchingBackground(slideClass, bgClass) -{ - if (bgClass == "background") - return true; - - // define pattern as regular expression - var pattern = /\w+/g; - - // check for matches and place result in array - var result = slideClass.match(pattern); - - // now check if desired name is present for background - for (var i = 0; i < result.length; i++) - { - if (hasToken(bgClass, result[i])) - return true; - } - - return false; -} - -// left to right traversal of root's content -function nextNode(root, node) -{ - if (node == null) - return root.firstChild; - - if (node.firstChild) - return node.firstChild; - - if (node.nextSibling) - return node.nextSibling; - - for (;;) - { - node = node.parentNode; - - if (!node || node == root) - break; - - if (node && node.nextSibling) - return node.nextSibling; - } - - return null; -} - -// right to left traversal of root's content -function previousNode(root, node) -{ - if (node == null) - { - node = root.lastChild; - - if (node) - { - while (node.lastChild) - node = node.lastChild; - } - - return node; - } - - if (node.previousSibling) - { - node = node.previousSibling; - - while (node.lastChild) - node = node.lastChild; - - return node; - } - - if (node.parentNode != root) - return node.parentNode; - - return null; -} - -// HTML elements that can be used with class="incremental" -// note that you can also put the class on containers like -// up, ol, dl, and div to make their contents appear -// incrementally. Upper case is used since this is what -// browsers report for HTML node names (text/html). -function incrementalElementList() -{ - var inclist = new Array(); - inclist["P"] = true; - inclist["PRE"] = true; - inclist["LI"] = true; - inclist["BLOCKQUOTE"] = true; - inclist["DT"] = true; - inclist["DD"] = true; - inclist["H2"] = true; - inclist["H3"] = true; - inclist["H4"] = true; - inclist["H5"] = true; - inclist["H6"] = true; - inclist["SPAN"] = true; - inclist["ADDRESS"] = true; - inclist["TABLE"] = true; - inclist["TR"] = true; - inclist["TH"] = true; - inclist["TD"] = true; - inclist["IMG"] = true; - inclist["OBJECT"] = true; - return inclist; -} - -function nextIncrementalItem(node) -{ - var slide = slides[slidenum]; - - for (;;) - { - node = nextNode(slide, node); - - if (node == null || node.parentNode == null) - break; - - if (node.nodeType == 1) // ELEMENT - { - if (node.nodeName == "BR") - continue; - - if (hasClass(node, "incremental") - && okayForIncremental[node.nodeName]) - return node; - - if (hasClass(node.parentNode, "incremental") - && !hasClass(node, "non-incremental")) - return node; - } - } - - return node; -} - -function previousIncrementalItem(node) -{ - var slide = slides[slidenum]; - - for (;;) - { - node = previousNode(slide, node); - - if (node == null || node.parentNode == null) - break; - - if (node.nodeType == 1) - { - if (node.nodeName == "BR") - continue; - - if (hasClass(node, "incremental") - && okayForIncremental[node.nodeName]) - return node; - - if (hasClass(node.parentNode, "incremental") - && !hasClass(node, "non-incremental")) - return node; - } - } - - return node; -} - -// set visibility for all elements on current slide with -// a parent element with attribute class="incremental" -function setVisibilityAllIncremental(value) -{ - var node = nextIncrementalItem(null); - - while (node) - { - node.style.visibility = value; - node = nextIncrementalItem(node); - } -} - -// reveal the next hidden item on the slide -// node is null or the node that was last revealed -function revealNextItem(node) -{ - node = nextIncrementalItem(node); - - if (node && node.nodeType == 1) // an element - node.style.visibility = "visible"; - - return node; -} - - -// exact inverse of revealNextItem(node) -function hidePreviousItem(node) -{ - if (node && node.nodeType == 1) // an element - node.style.visibility = "hidden"; - - return previousIncrementalItem(node); -} - - -/* set click handlers on all anchors */ -function patchAnchors() -{ - var anchors = document.body.getElementsByTagName("a"); - - for (var i = 0; i < anchors.length; ++i) - { - anchors[i].onclick = clickedAnchor; - } -} - -function clickedAnchor(e) -{ - if (!e) - var e = window.event; - - // compare this.href with location.href - // for link to another slide in this doc - - if (pageAddress(this.href) == pageAddress(location.href)) - { - // yes, so find new slide number - var newslidenum = findSlideNumber(this.href); - - if (newslidenum != slidenum) - { - slide = slides[slidenum]; - hideSlide(slide); - slidenum = newslidenum; - slide = slides[slidenum]; - showSlide(slide); - setLocation(); - } - } - else if (this.target == null) - location.href = this.href; - - this.blur(); - stopPropagation(e); -} - -function pageAddress(uri) -{ - var i = uri.indexOf("#"); - - // check if anchor is entire page - - if (i < 0) - return uri; // yes - - return uri.substr(0, i); -} - -function showSlideNumber() -{ - slideNumElement.innerHTML = "slide".localize() + " " + - (slidenum + 1) + "/" + slides.length; -} - -function setLocation() -{ - var uri = pageAddress(location.href); - - //if (slidenum > 0) - uri = uri + "#(" + (slidenum+1) + ")"; - - if (uri != location.href && !khtml) - location.href = uri; - - document.title = title + " (" + (slidenum+1) + ")"; - //document.title = (slidenum+1) + ") " + slideName(slidenum); - - showSlideNumber(); -} - -// find current slide based upon location -// first find target anchor and then look -// for associated div element enclosing it -// finally map that to slide number -function findSlideNumber(uri) -{ - // first get anchor from page location - - var i = uri.indexOf("#"); - - // check if anchor is entire page - - if (i < 0) - return 0; // yes - - var anchor = unescape(uri.substr(i+1)); - - // now use anchor as XML ID to find target - var target = document.getElementById(anchor); - - if (!target) - { - // does anchor look like "(2)" for slide 2 ?? - // where first slide is (1) - var re = /\((\d)+\)/; - - if (anchor.match(re)) - { - var num = parseInt(anchor.substring(1, anchor.length-1)); - - if (num > slides.length) - num = 1; - - if (--num < 0) - num = 0; - - return num; - } - - // accept [2] for backwards compatibility - re = /\[(\d)+\]/; - - if (anchor.match(re)) - { - var num = parseInt(anchor.substring(1, anchor.length-1)); - - if (num > slides.length) - num = 1; - - if (--num < 0) - num = 0; - - return num; - } - - // oh dear unknown anchor - return 0; - } - - // search for enclosing slide - - while (true) - { - // browser coerces html elements to uppercase! - if (target.nodeName.toLowerCase() == "div" && - hasClass(target, "slide")) - { - // found the slide element - break; - } - - // otherwise try parent element if any - - target = target.parentNode; - - if (!target) - { - return 0; // no luck! - } - }; - - for (i = 0; i < slides.length; ++i) - { - if (slides[i] == target) - return i; // success - } - - // oh dear still no luck - return 0; -} - -// find slide name from first h1 element -// default to document title + slide number -function slideName(index) -{ - var name = null; - var slide = slides[index]; - - var heading = findHeading(slide); - - if (heading) - name = extractText(heading); - - if (!name) - name = title + "(" + (index + 1) + ")"; - - name.replace(/\&/g, "&"); - name.replace(/\</g, "<"); - name.replace(/\>/g, ">"); - - return name; -} - -// find first h1 element in DOM tree -function findHeading(node) -{ - if (!node || node.nodeType != 1) - return null; - - if (node.nodeName == "H1" || node.nodeName == "h1") - return node; - - var child = node.firstChild; - - while (child) - { - node = findHeading(child); - - if (node) - return node; - - child = child.nextSibling; - } - - return null; -} - -// recursively extract text from DOM tree -function extractText(node) -{ - if (!node) - return ""; - - // text nodes - if (node.nodeType == 3) - return node.nodeValue; - - // elements - if (node.nodeType == 1) - { - node = node.firstChild; - var text = ""; - - while (node) - { - text = text + extractText(node); - node = node.nextSibling; - } - - return text; - } - - return ""; -} - - -// find copyright text from meta element -function findCopyright() -{ - var name, content; - var meta = document.getElementsByTagName("meta"); - - for (var i = 0; i < meta.length; ++i) - { - name = meta[i].getAttribute("name"); - content = meta[i].getAttribute("content"); - - if (name == "copyright") - return content; - } - - return null; -} - -function findSizeAdjust() -{ - var name, content, offset; - var meta = document.getElementsByTagName("meta"); - - for (var i = 0; i < meta.length; ++i) - { - name = meta[i].getAttribute("name"); - content = meta[i].getAttribute("content"); - - if (name == "font-size-adjustment") - return 1 * content; - } - - return 0; -} - -function addToolbar() -{ - var slideCounter, page; - - var toolbar = createElement("div"); - toolbar.setAttribute("class", "toolbar"); - - if (ns_pos) // a reasonably behaved browser - { - var right = document.createElement("div"); - right.setAttribute("style", "float: right; text-align: right"); - - slideCounter = document.createElement("div") - slideCounter.innerHTML = "slide".localize() + " n/m"; - right.appendChild(slideCounter); - toolbar.appendChild(right); - - var left = document.createElement("div"); - left.setAttribute("style", "text-align: left"); - - // global end of slide indicator - eos = document.createElement("span"); - eos.innerHTML = "* "; - left.appendChild(eos); - - var help = document.createElement("a"); - help.setAttribute("href", helpPage); - help.setAttribute("title", helpText.localize()); - help.innerHTML = "help?".localize(); - left.appendChild(help); - helpAnchor = help; // save for focus hack - - var gap1 = document.createTextNode(" "); - left.appendChild(gap1); - - var contents = document.createElement("a"); - contents.setAttribute("href", "javascript:toggleTableOfContents()"); - contents.setAttribute("title", "table of contents".localize()); - contents.innerHTML = "contents?".localize(); - left.appendChild(contents); - - var gap2 = document.createTextNode(" "); - left.appendChild(gap2); - - var i = location.href.indexOf("#"); - - // check if anchor is entire page - - if (i > 0) - page = location.href.substr(0, i); - else - page = location.href; - - var start = document.createElement("a"); - start.setAttribute("href", page); - start.setAttribute("title", "restart presentation".localize()); - start.innerHTML = "restart?".localize(); -// start.setAttribute("href", "javascript:printSlides()"); -// start.setAttribute("title", "print all slides".localize()); -// start.innerHTML = "print!".localize(); - left.appendChild(start); - - var copyright = findCopyright(); - - if (copyright) - { - var span = document.createElement("span"); - span.innerHTML = copyright; - span.style.color = "black"; - span.style.marginLeft = "4em"; - left.appendChild(span); - } - - toolbar.appendChild(left); - } - else // IE so need to work around its poor CSS support - { - toolbar.style.position = (ie7 ? "fixed" : "absolute"); - toolbar.style.zIndex = "200"; - toolbar.style.width = "99.9%"; - toolbar.style.height = "1.2em"; - toolbar.style.top = "auto"; - toolbar.style.bottom = "0"; - toolbar.style.left = "0"; - toolbar.style.right = "0"; - toolbar.style.textAlign = "left"; - toolbar.style.fontSize = "60%"; - toolbar.style.color = "red"; - toolbar.borderWidth = 0; - toolbar.style.background = "rgb(240,240,240)"; - - // would like to have help text left aligned - // and page counter right aligned, floating - // div's don't work, so instead use nested - // absolutely positioned div's. - - var sp = document.createElement("span"); - sp.innerHTML = " * "; - toolbar.appendChild(sp); - eos = sp; // end of slide indicator - - var help = document.createElement("a"); - help.setAttribute("href", helpPage); - help.setAttribute("title", helpText.localize()); - help.innerHTML = "help?".localize(); - toolbar.appendChild(help); - helpAnchor = help; // save for focus hack - - var gap1 = document.createTextNode(" "); - toolbar.appendChild(gap1); - - var contents = document.createElement("a"); - contents.setAttribute("href", "javascript:toggleTableOfContents()"); - contents.setAttribute("title", "table of contents".localize()); - contents.innerHTML = "contents?".localize(); - toolbar.appendChild(contents); - - var gap2 = document.createTextNode(" "); - toolbar.appendChild(gap2); - - var i = location.href.indexOf("#"); - - // check if anchor is entire page - - if (i > 0) - page = location.href.substr(0, i); - else - page = location.href; - - var start = document.createElement("a"); - start.setAttribute("href", page); - start.setAttribute("title", "restart presentation".localize()); - start.innerHTML = "restart?".localize(); -// start.setAttribute("href", "javascript:printSlides()"); -// start.setAttribute("title", "print all slides".localize()); -// start.innerHTML = "print!".localize(); - toolbar.appendChild(start); - - var copyright = findCopyright(); - - if (copyright) - { - var span = document.createElement("span"); - span.innerHTML = copyright; - span.style.color = "black"; - span.style.marginLeft = "2em"; - toolbar.appendChild(span); - } - - slideCounter = document.createElement("div") - slideCounter.style.position = "absolute"; - slideCounter.style.width = "auto"; //"20%"; - slideCounter.style.height = "1.2em"; - slideCounter.style.top = "auto"; - slideCounter.style.bottom = 0; - slideCounter.style.right = "0"; - slideCounter.style.textAlign = "right"; - slideCounter.style.color = "red"; - slideCounter.style.background = "rgb(240,240,240)"; - - slideCounter.innerHTML = "slide".localize() + " n/m"; - toolbar.appendChild(slideCounter); - } - - // ensure that click isn't passed through to the page - toolbar.onclick = stopPropagation; - document.body.appendChild(toolbar); - slideNumElement = slideCounter; - setEosStatus(false); - - return toolbar; -} - -function isShownToc() -{ - if (toc && toc.style.visible == "visible") - return true; - - return false; -} - -function showTableOfContents() -{ - if (toc) - { - if (toc.style.visibility != "visible") - { - toc.style.visibility = "visible"; - toc.style.display = "block"; - toc.focus(); - - if (ie7 && slidenum == 0) - setTimeout("ieHack()", 100); - } - else - hideTableOfContents(); - } -} - -function hideTableOfContents() -{ - if (toc && toc.style.visibility != "hidden") - { - toc.style.visibility = "hidden"; - toc.style.display = "none"; - - try - { - if (!opera) - helpAnchor.focus(); - } - catch (e) - { - } - } -} - -function toggleTableOfContents() -{ - if (toc) - { - if (toc.style.visible != "visible") - showTableOfContents(); - else - hideTableOfContents(); - } -} - -// called on clicking toc entry -function gotoEntry(e) -{ - var target; - - if (!e) - var e = window.event; - - if (e.target) - target = e.target; - else if (e.srcElement) - target = e.srcElement; - - // work around Safari bug - if (target.nodeType == 3) - target = target.parentNode; - - if (target && target.nodeType == 1) - { - var uri = target.getAttribute("href"); - - if (uri) - { - //alert("going to " + uri); - var slide = slides[slidenum]; - hideSlide(slide); - slidenum = findSlideNumber(uri); - slide = slides[slidenum]; - lastShown = null; - setLocation(); - setVisibilityAllIncremental("hidden"); - setEosStatus(!nextIncrementalItem(lastShown)); - showSlide(slide); - //target.focus(); - - try - { - if (!opera) - helpAnchor.focus(); - } - catch (e) - { - } - } - } - - hideTableOfContents(e); - if (ie7) ieHack(); - stopPropagation(e); - return cancel(e); -} - -// called onkeydown for toc entry -function gotoTocEntry(event) -{ - var key; - - if (!event) - var event = window.event; - - // kludge around NS/IE differences - if (window.event) - key = window.event.keyCode; - else if (event.which) - key = event.which; - else - return true; // Yikes! unknown browser - - // ignore event if key value is zero - // as for alt on Opera and Konqueror - if (!key) - return true; - - // check for concurrent control/command/alt key - // but are these only present on mouse events? - - if (event.ctrlKey || event.altKey) - return true; - - if (key == 13) - { - var uri = this.getAttribute("href"); - - if (uri) - { - //alert("going to " + uri); - var slide = slides[slidenum]; - hideSlide(slide); - slidenum = findSlideNumber(uri); - slide = slides[slidenum]; - lastShown = null; - setLocation(); - setVisibilityAllIncremental("hidden"); - setEosStatus(!nextIncrementalItem(lastShown)); - showSlide(slide); - //target.focus(); - - try - { - if (!opera) - helpAnchor.focus(); - } - catch (e) - { - } - } - - hideTableOfContents(); - if (ie7) ieHack(); - return cancel(event); - } - - if (key == 40 && this.next) - { - this.next.focus(); - return cancel(event); - } - - if (key == 38 && this.previous) - { - this.previous.focus(); - return cancel(event); - } - - return true; -} - -function isTitleSlide(slide) -{ - return hasClass(slide, "title"); -} - -// create div element with links to each slide -function tableOfContents() -{ - var toc = document.createElement("div"); - addClass(toc, "toc"); - //toc.setAttribute("tabindex", "0"); - - var heading = document.createElement("div"); - addClass(heading, "toc-heading"); - heading.innerHTML = "Table of Contents".localize(); - - heading.style.textAlign = "center"; - heading.style.width = "100%"; - heading.style.margin = "0"; - heading.style.marginBottom = "1em"; - heading.style.borderBottomStyle = "solid"; - heading.style.borderBottomColor = "rgb(180,180,180)"; - heading.style.borderBottomWidth = "1px"; - - toc.appendChild(heading); - var previous = null; - - for (var i = 0; i < slides.length; ++i) - { - var title = hasClass(slides[i], "title"); - var num = document.createTextNode((i + 1) + ". "); - - toc.appendChild(num); - - var a = document.createElement("a"); - a.setAttribute("href", "#(" + (i+1) + ")"); - - if (title) - addClass(a, "titleslide"); - - var name = document.createTextNode(slideName(i)); - a.appendChild(name); - a.onclick = gotoEntry; - a.onkeydown = gotoTocEntry; - a.previous = previous; - - if (previous) - previous.next = a; - - toc.appendChild(a); - - if (i == 0) - toc.first = a; - - if (i < slides.length - 1) - { - var br = document.createElement("br"); - toc.appendChild(br); - } - - previous = a; - } - - toc.focus = function () { - if (this.first) - this.first.focus(); - } - - toc.onclick = function (e) { - e||(e=window.event); - hideTableOfContents(); - stopPropagation(e); - - if (e.cancel != undefined) - e.cancel = true; - - if (e.returnValue != undefined) - e.returnValue = false; - - return false; - }; - - toc.style.position = "absolute"; - toc.style.zIndex = "300"; - toc.style.width = "60%"; - toc.style.maxWidth = "30em"; - toc.style.height = "30em"; - toc.style.overflow = "auto"; - toc.style.top = "auto"; - toc.style.right = "auto"; - toc.style.left = "4em"; - toc.style.bottom = "4em"; - toc.style.padding = "1em"; - toc.style.background = "rgb(240,240,240)"; - toc.style.borderStyle = "solid"; - toc.style.borderWidth = "2px"; - toc.style.fontSize = "60%"; - - document.body.insertBefore(toc, document.body.firstChild); - return toc; -} - -function replaceByNonBreakingSpace(str) -{ - for (var i = 0; i < str.length; ++i) - str[i] = 160; -} - - -function initOutliner() -{ - var items = document.getElementsByTagName("LI"); - - for (var i = 0; i < items.length; ++i) - { - var target = items[i]; - - if (!hasClass(target.parentNode, "outline")) - continue; - - target.onclick = outlineClick; - - if (!ns_pos) - { - target.onmouseover = hoverOutline; - target.onmouseout = unhoverOutline; - } - - if (foldable(target)) - { - target.foldable = true; - target.onfocus = function () {outline = this;}; - target.onblur = function () {outline = null;}; - - if (!target.getAttribute("tabindex")) - target.setAttribute("tabindex", "0"); - - if (hasClass(target, "expand")) - unfold(target); - else - fold(target); - } - else - { - addClass(target, "nofold"); - target.visible = true; - target.foldable = false; - } - } -} - -function foldable(item) -{ - if (!item || item.nodeType != 1) - return false; - - var node = item.firstChild; - - while (node) - { - if (node.nodeType == 1 && isBlock(node)) - return true; - - node = node.nextSibling; - } - - return false; -} - -function fold(item) -{ - if (item) - { - removeClass(item, "unfolded"); - addClass(item, "folded"); - } - - var node = item ? item.firstChild : null; - - while (node) - { - if (node.nodeType == 1 && isBlock(node)) // element - { - // note that getElementStyle won't work for Safari 1.3 - node.display = getElementStyle(node, "display", "display"); - node.style.display = "none"; - node.style.visibility = "hidden"; - } - - node = node.nextSibling; - } - - item.visible = false; -} - -function unfold(item) -{ - if (item) - { - addClass(item, "unfolded"); - removeClass(item, "folded"); - } - - var node = item ? item.firstChild : null; - - while (node) - { - if (node.nodeType == 1 && isBlock(node)) // element - { - // with fallback for Safari, see above - node.style.display = (node.display ? node.display : "block"); - node.style.visibility = "visible"; - } - - node = node.nextSibling; - } - - item.visible = true; -} - -function outlineClick(e) -{ - var rightclick = false; - var target; - - if (!e) - var e = window.event; - - if (e.target) - target = e.target; - else if (e.srcElement) - target = e.srcElement; - - // work around Safari bug - if (target.nodeType == 3) - target = target.parentNode; - - while (target && target.visible == undefined) - target = target.parentNode; - - if (!target) - return true; - - if (e.which) - rightclick = (e.which == 3); - else if (e.button) - rightclick = (e.button == 2); - - if (!rightclick && target.visible != undefined) - { - if (target.foldable) - { - if (target.visible) - fold(target); - else - unfold(target); - } - - stopPropagation(e); - e.cancel = true; - e.returnValue = false; - } - - return false; -} - -function hoverOutline(e) -{ - var target; - - if (!e) - var e = window.event; - - if (e.target) - target = e.target; - else if (e.srcElement) - target = e.srcElement; - - // work around Safari bug - if (target.nodeType == 3) - target = target.parentNode; - - while (target && target.visible == undefined) - target = target.parentNode; - - if (target && target.foldable) - target.style.cursor = "pointer"; - - return true; -} - -function unhoverOutline(e) -{ - var target; - - if (!e) - var e = window.event; - - if (e.target) - target = e.target; - else if (e.srcElement) - target = e.srcElement; - - // work around Safari bug - if (target.nodeType == 3) - target = target.parentNode; - - while (target && target.visible == undefined) - target = target.parentNode; - - if (target) - target.style.cursor = "default"; - - return true; -} - - -function stopPropagation(e) -{ - if (window.event) - { - window.event.cancelBubble = true; - //window.event.returnValue = false; - } - else if (e) - { - e.cancelBubble = true; - e.stopPropagation(); - //e.preventDefault(); - } -} - -/* can't rely on display since we set that to none to hide things */ -function isBlock(elem) -{ - var tag = elem.nodeName; - - return tag == "OL" || tag == "UL" || tag == "P" || - tag == "LI" || tag == "TABLE" || tag == "PRE" || - tag == "H1" || tag == "H2" || tag == "H3" || - tag == "H4" || tag == "H5" || tag == "H6" || - tag == "BLOCKQUOTE" || tag == "ADDRESS"; -} - -function getElementStyle(elem, IEStyleProp, CSSStyleProp) -{ - if (elem.currentStyle) - { - return elem.currentStyle[IEStyleProp]; - } - else if (window.getComputedStyle) - { - var compStyle = window.getComputedStyle(elem, ""); - return compStyle.getPropertyValue(CSSStyleProp); - } - return ""; -} - -// works with text/html and text/xhtml+xml with thanks to Simon Willison -function createElement(element) -{ - if (typeof document.createElementNS != 'undefined') - { - return document.createElementNS('http://www.w3.org/1999/xhtml', element); - } - - if (typeof document.createElement != 'undefined') - { - return document.createElement(element); - } - - return false; -} - -// designed to work with both text/html and text/xhtml+xml -function getElementsByTagName(name) -{ - if (typeof document.getElementsByTagNameNS != 'undefined') - { - return document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', name); - } - - if (typeof document.getElementsByTagName != 'undefined') - { - return document.getElementsByTagName(name); - } - - return null; -} - -/* -// clean alternative to innerHTML method, but on IE6 -// it doesn't work with named entities like -// which need to be replaced by numeric entities -function insertText(element, text) -{ - try - { - element.textContent = text; // DOM3 only - } - catch (e) - { - if (element.firstChild) - { - // remove current children - while (element.firstChild) - element.removeChild(element.firstChild); - } - - element.appendChild(document.createTextNode(text)); - } -} - -// as above, but as method of all element nodes -// doesn't work in IE6 which doesn't allow you to -// add methods to the HTMLElement prototype -if (HTMLElement != undefined) -{ - HTMLElement.prototype.insertText = function(text) { - var element = this; - - try - { - element.textContent = text; // DOM3 only - } - catch (e) - { - if (element.firstChild) - { - // remove current children - while (element.firstChild) - element.removeChild(element.firstChild); - } - - element.appendChild(document.createTextNode(text)); - } - }; -} -*/ - -function getSelectedText() -{ - try - { - if (window.getSelection) - return window.getSelection().toString(); - - if (document.getSelection) - return document.getSelection().toString(); - - if (document.selection) - return document.selection.createRange().text; - } - catch (e) - { - return ""; - } - return ""; -} |