From 04b08da9af0c450d645ab7389d1467308cfc2db8 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 4 Mar 2013 21:27:36 +0100 Subject: Imported Upstream version 1.1~hg20130304 --- doc/ExpressivenessOfGo.pdf | Bin 859406 -> 0 bytes doc/Makefile | 5 + doc/articles/c_go_cgo.html | 9 +- doc/articles/concurrency_patterns.html | 4 +- doc/articles/error_handling.html | 2 +- doc/articles/go_command.html | 4 +- doc/articles/godoc_documenting_go_code.html | 18 +- doc/articles/image_package.html | 8 +- doc/articles/json_and_go.html | 23 +- doc/articles/json_rpc_tale_of_interfaces.html | 2 +- doc/articles/laws_of_reflection.html | 2 +- doc/articles/race_detector.html | 369 ++++ doc/articles/slices_usage_and_internals.html | 2 +- doc/articles/wiki/get.go | 19 +- doc/articles/wiki/index.html | 209 +- doc/articles/wiki/part3-errorhandling.go | 75 + doc/articles/wiki/part3.go | 59 + doc/articles/wiki/test.bash | 7 +- doc/code.html | 14 +- doc/codereview_with_mq.html | 115 - doc/codewalk/codewalk.js | 2 +- doc/codewalk/markov.xml | 2 +- doc/codewalk/pig.go | 2 +- doc/contrib.html | 8 +- doc/contribute.html | 193 +- doc/debugging_with_gdb.html | 15 +- doc/devel/release.html | 11 +- doc/devel/weekly.html | 13 +- doc/docs.html | 54 +- doc/effective_go.html | 351 +++- doc/gccgo_contribute.html | 8 +- doc/go1.1.html | 207 ++ doc/go1.html | 8 +- doc/go_faq.html | 155 +- doc/go_mem.html | 4 +- doc/go_spec.html | 751 ++++--- doc/godocs.js | 294 ++- doc/gopher/pencil/gopherhat.jpg | Bin 0 -> 129627 bytes doc/gopher/pencil/gopherhelmet.jpg | Bin 0 -> 151965 bytes doc/gopher/pencil/gophermega.jpg | Bin 0 -> 122348 bytes doc/gopher/pencil/gopherrunning.jpg | Bin 0 -> 86299 bytes doc/gopher/pencil/gopherswim.jpg | Bin 0 -> 158593 bytes doc/gopher/pencil/gopherswrench.jpg | Bin 0 -> 231095 bytes doc/help.html | 12 +- doc/install-source.html | 53 +- doc/install.html | 50 +- doc/jquery.js | 2 + doc/play/fib.go | 4 +- doc/play/playground.js | 263 ++- doc/play/sieve.go | 4 +- doc/play/solitaire.go | 14 +- doc/play/tree.go | 4 +- doc/popups.js | 24 - doc/progs/cgo1.go | 2 + doc/progs/cgo2.go | 2 + doc/progs/cgo3.go | 2 + doc/progs/cgo4.go | 2 + doc/progs/defer.go | 2 + doc/progs/defer.out | 3 + doc/progs/defer2.go | 2 + doc/progs/defer2.out | 12 + doc/progs/eff_bytesize.go | 2 + doc/progs/eff_bytesize.out | 1 + doc/progs/eff_qr.go | 12 +- doc/progs/eff_sequence.go | 2 + doc/progs/eff_sequence.out | 1 + doc/progs/error.go | 8 +- doc/progs/error2.go | 2 + doc/progs/error3.go | 2 + doc/progs/error4.go | 4 +- doc/progs/go1.go | 3 + doc/progs/gobs1.go | 2 + doc/progs/gobs2.go | 2 + doc/progs/image_draw.go | 2 + doc/progs/image_package1.go | 2 + doc/progs/image_package1.out | 1 + doc/progs/image_package2.go | 2 + doc/progs/image_package2.out | 1 + doc/progs/image_package3.go | 2 + doc/progs/image_package3.out | 1 + doc/progs/image_package4.go | 2 + doc/progs/image_package4.out | 1 + doc/progs/image_package5.go | 2 + doc/progs/image_package5.out | 1 + doc/progs/image_package6.go | 2 + doc/progs/image_package6.out | 2 + doc/progs/interface.go | 2 + doc/progs/interface2.go | 2 + doc/progs/interface2.out | 1 + doc/progs/json1.go | 2 + doc/progs/json2.go | 2 + doc/progs/json2.out | 2 + doc/progs/json3.go | 2 + doc/progs/json4.go | 2 + doc/progs/json5.go | 2 + doc/progs/run | 9 + doc/progs/slices.go | 2 + doc/progs/timeout1.go | 2 + doc/progs/timeout2.go | 2 + doc/progs/unused1.go | 12 + doc/progs/unused2.go | 16 + doc/progs/update.bash | 15 + doc/reference.html | 27 +- doc/root.html | 12 +- doc/style.css | 144 +- doc/talks/go_talk-20091030.pdf | Bin 247502 -> 0 bytes doc/talks/go_talk-20100112.html | 411 ---- doc/talks/go_talk-20100121.html | 453 ---- doc/talks/go_talk-20100323.html | 395 ---- doc/talks/gofrontend-gcc-summit-2010.pdf | Bin 125185 -> 0 bytes doc/talks/io2010/balance.go | 168 -- doc/talks/io2010/decrypt.go | 85 - doc/talks/io2010/encrypt.go | 52 - doc/talks/io2010/eval1.go | 227 -- doc/talks/io2010/eval2.go | 259 --- doc/talks/io2010/talk.pdf | Bin 1094941 -> 0 bytes doc/talks/io2011/Real_World_Go.pdf | Bin 609477 -> 0 bytes doc/talks/io2011/Writing_Web_Apps_in_Go.pdf | Bin 729499 -> 0 bytes doc/talks/java-typing.png | Bin 19328 -> 0 bytes doc/talks/slidy.css | 277 --- doc/talks/slidy.js | 2772 ------------------------- 121 files changed, 2665 insertions(+), 6235 deletions(-) delete mode 100644 doc/ExpressivenessOfGo.pdf create mode 100644 doc/articles/race_detector.html create mode 100644 doc/articles/wiki/part3-errorhandling.go create mode 100644 doc/articles/wiki/part3.go delete mode 100644 doc/codereview_with_mq.html create mode 100644 doc/go1.1.html create mode 100644 doc/gopher/pencil/gopherhat.jpg create mode 100644 doc/gopher/pencil/gopherhelmet.jpg create mode 100644 doc/gopher/pencil/gophermega.jpg create mode 100644 doc/gopher/pencil/gopherrunning.jpg create mode 100644 doc/gopher/pencil/gopherswim.jpg create mode 100644 doc/gopher/pencil/gopherswrench.jpg create mode 100644 doc/jquery.js delete mode 100644 doc/popups.js create mode 100644 doc/progs/defer.out create mode 100644 doc/progs/defer2.out create mode 100644 doc/progs/eff_bytesize.out create mode 100644 doc/progs/eff_sequence.out create mode 100644 doc/progs/image_package1.out create mode 100644 doc/progs/image_package2.out create mode 100644 doc/progs/image_package3.out create mode 100644 doc/progs/image_package4.out create mode 100644 doc/progs/image_package5.out create mode 100644 doc/progs/image_package6.out create mode 100644 doc/progs/interface2.out create mode 100644 doc/progs/json2.out create mode 100644 doc/progs/unused1.go create mode 100644 doc/progs/unused2.go create mode 100755 doc/progs/update.bash delete mode 100644 doc/talks/go_talk-20091030.pdf delete mode 100644 doc/talks/go_talk-20100112.html delete mode 100644 doc/talks/go_talk-20100121.html delete mode 100644 doc/talks/go_talk-20100323.html delete mode 100644 doc/talks/gofrontend-gcc-summit-2010.pdf delete mode 100644 doc/talks/io2010/balance.go delete mode 100644 doc/talks/io2010/decrypt.go delete mode 100644 doc/talks/io2010/encrypt.go delete mode 100644 doc/talks/io2010/eval1.go delete mode 100644 doc/talks/io2010/eval2.go delete mode 100644 doc/talks/io2010/talk.pdf delete mode 100644 doc/talks/io2011/Real_World_Go.pdf delete mode 100644 doc/talks/io2011/Writing_Web_Apps_in_Go.pdf delete mode 100644 doc/talks/java-typing.png delete mode 100644 doc/talks/slidy.css delete mode 100644 doc/talks/slidy.js (limited to 'doc') diff --git a/doc/ExpressivenessOfGo.pdf b/doc/ExpressivenessOfGo.pdf deleted file mode 100644 index f1931d081..000000000 Binary files a/doc/ExpressivenessOfGo.pdf and /dev/null differ 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

-To build cgo packages, just use " +To build cgo packages, just use " go build" or -"go install +"go install " as usual. The go tool recognizes the special "C" import and automatically uses cgo for those files.

@@ -169,9 +169,8 @@ in the Go tree demonstrate more advanced concepts.

For a simple, idiomatic example of a cgo-based package, see Russ Cox's gosqlite. -Also, the Go Project Dashboard lists several other -cgo packages. +Also, the Go Community Wiki +lists many packages, some of which use cgo.

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 select statement to receive from either ch or timeout. If nothing arrives on ch after one second, the timeout case is selected and the attempt to read from -ch is abandoned. +ch is abandoned.

{{code "/doc/progs/timeout1.go" `/select {/` `/STOP/`}} @@ -64,7 +64,7 @@ could fail since no one is ready.

-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 race condition, but the fix is trivial. We just make sure to buffer the channel ch (by adding the buffer length as the second argument to make), 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:

(This is a slightly simplified version of some -actual code +actual code from the Camlistore project.)

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 goinstall command -(now replaced by go get) +(now replaced by go get) 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/`}}

-They can also be detailed like the gob package's -overview. That package uses another convention for packages +They can also be detailed like the gob +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, doc.go, which contains only those comments and a package clause. @@ -80,10 +80,10 @@ sentence will appear in godoc's package list.

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 "BUG(who)” are recognized as known bugs, and included in -the "Bugs” section of the package documentation. The "who” part should be the +the word "BUG(who)" 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 bytes package: +known issue from the bytes package:

@@ -93,7 +93,7 @@ known issue from the bytes package:
 

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 godoc documentation and its corresponding doc.go file. @@ -137,3 +137,9 @@ indexing via the -path flag or just by running "godoc ."godoc documentation for more details.

+ +

+Godoc recognizes example functions written according to the +testing package's naming +conventions and presents them appropriately. +

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 Rectangle is inclusive at the top-left and exclusive at the bottom-right. For a Point p and a Rectangle r, p.In(r) if and only if -r.Min.X <= p.X && p.X < r.Max.X, and similarly for Y. This is analagous to how +r.Min.X <= p.X && p.X < r.Max.X, and similarly for Y. This is analagous to how a slice s[i0:i1] is inclusive at the low end and exclusive at the high end. (Unlike arrays and slices, a Rectangle often has a non-zero origin.) @@ -193,8 +193,8 @@ way to iterate over an Image m's pixels looks like:
 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 Message
 {{code "/doc/progs/json1.go" `/m :=/`}}
 
 

-we can marshal a JSON-encoded version of m using json.Marshal: +we can marshal a JSON-encoded version of m using json.Marshal:

{{code "/doc/progs/json1.go" `/b, err :=/`}} @@ -82,8 +82,8 @@ is nil).

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.

@@ -130,7 +130,7 @@ preference):

  • -An exported field with a tag of "Foo" (see the +An exported field with a tag of `json:"Foo"` (see the Go spec for more on struct tags),
  • @@ -151,11 +151,11 @@ type?

    Unmarshal 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 Unmarshal. +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 Unmarshal.

    @@ -163,7 +163,7 @@ But what if you don't know the structure of your JSON data beforehand?

    -Generic JSON with interface{} +Generic JSON with interface{}

    @@ -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/`}} - +

    The json package uses map[string]interface{} and []interface{} values to store arbitrary JSON objects and arrays; it will happily unmarshal any valid JSON blob into a plain interface{} value. The default concrete Go types are: +

    • 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 -final changeset +final changeset was submitted.

      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 float64 variable x, not an interface value, to reflect.TypeOf. But it's there; as -godoc reports, the signature of +godoc reports, the signature of reflect.TypeOf includes an empty interface:

      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 @@ + + +

      Introduction

      + +

      +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 The Go Memory Model for details. +

      + +

      +Here is an example of a data race that can lead to crashes and memory corruption: +

      + +
      +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)
      +	}
      +}
      +
      + +

      Usage

      + +

      +Fortunately, Go includes a built-in data race detector. To use it, add the -race flag to the go command: +

      + +
      +$ 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
      +
      + +

      Report Format

      + +

      +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: +

      + +
      +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
      +
      + +

      Options

      + +

      +The GORACE environment variable sets race detector options. The format is: +

      + +
      +GORACE="option1=val1 option2=val2"
      +
      + +

      +The options are: +

      + +
        +
      • +log_path (default stderr): The race detector writes +its report to a file named log_path.pid. The special names stdout +and stderr cause reports to be written to standard output and +standard error, respectively. +
      • + +
      • +exitcode (default 66): The exit status to use when +exiting after a detected race. +
      • + +
      • +strip_path_prefix (default ""): Strip this prefix +from all reported file paths, to make reports more concise. +
      • + +
      • +history_size (default 1): The per-goroutine memory +access history is 32K * 2**history_size elements. Increasing this +value can avoid a "failed to restore the stack" error in reports, but at the +cost of increased memory usage. +
      • +
      + +

      +Example: +

      + +
      +$ GORACE="log_path=/tmp/race/report strip_path_prefix=/my/go/sources/" go test -race
      +
      + +

      Excluding Tests

      + +

      +When you build with -race flag, go command defines additional +build tag race. +You can use it to exclude some code/tests under the race detector. For example: +

      + +
      +// +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) {
      +	// ...
      +}
      +
      + +

      How To Use

      + +

      +To start, run your tests using the race detector (go test -race). +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 -race under a realistic +workload. +

      + +

      Typical Data Races

      + +

      +Here are some typical data races. All of them can be detected with the race detector. +

      + +

      Race on loop counter

      + +
      +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()
      +}
      +
      + +

      +The variable i 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: +

      + +
      +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()
      +}
      +
      + +

      Accidentally shared variable

      + +
      +// 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
      +}
      +
      + +

      +The fix is to introduce new variables in the goroutines (note :=): +

      + +
      +			...
      +			_, err := f1.Write(data)
      +			...
      +			_, err := f2.Write(data)
      +			...
      +
      + +

      Unprotected global variable

      + +

      +If the following code is called from several goroutines, it leads to bad races on the service map. +Concurrent reads and writes of a map are not safe: +

      + +
      +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]
      +}
      +
      + +

      +To make the code safe, protect the accesses with a mutex: +

      + +
      +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]
      +}
      +
      + +

      Primitive unprotected variable

      + +

      +Data races can happen on variables of primitive types as well (bool, int, int64, etc.), like in the following example: +

      + +
      +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)
      +			}
      +		}
      +	}()
      +}
      +
      + +

      +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. +

      + +

      +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 sync/atomic package. +

      + +
      +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)
      +			}
      +		}
      +	}()
      +}
      +
      + +

      Supported Systems

      + +

      +The race detector runs on darwin/amd64, linux/amd64, and windows/amd64. +

      + +

      Runtime Overhead

      + +

      +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. +

      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'}
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

-Create a file named wiki.go, open it in your favorite editor, and +Create a file named wiki.go, open it in your favorite editor, and add the following lines:

@@ -60,8 +60,8 @@ import (

-We import the fmt and ioutil packages from the Go -standard library. Later, as we implement additional functionality, we will +We import the fmt and ioutil packages from the Go +standard library. Later, as we implement additional functionality, we will add more packages to this import declaration.

@@ -77,7 +77,7 @@ the title and body. {{code "doc/articles/wiki/part1.go" `/^type Page/` `/}/`}}

-The type []byte means "a byte slice". +The type []byte means "a byte slice". (See Slices: usage and internals for more on slices.) The Body element is a []byte rather than @@ -86,8 +86,8 @@ libraries we will use, as you'll see below.

-The Page struct describes how page data will be stored in memory. -But what about persistent storage? We can address that by creating a +The Page struct describes how page data will be stored in memory. +But what about persistent storage? We can address that by creating a save method on Page:

@@ -96,11 +96,11 @@ But what about persistent storage? We can address that by creating a

This method's signature reads: "This is a method named save that takes as its receiver p, a pointer to Page . It takes -no parameters, and returns a value of type error." +no parameters, and returns a value of type error."

-This method will save the Page's Body to a text +This method will save the Page's Body to a text file. For simplicity, we will use the Title as the file name.

@@ -110,35 +110,37 @@ that is the return type of WriteFile (a standard library function that writes a byte slice to a file). The save method returns the error value, to let the application handle it should anything go wrong while writing the file. If all goes well, Page.save() will return -nil (the zero-value for pointers, interfaces, and some other +nil (the zero-value for pointers, interfaces, and some other types).

-The octal integer constant 0600, passed as the third parameter to +The octal integer literal 0600, passed as the third parameter to WriteFile, indicates that the file should be created with read-write permissions for the current user only. (See the Unix man page open(2) for details.)

-We will want to load pages, too: +In addition to saving pages, we will want to load pages, too:

{{code "doc/articles/wiki/part1-noerror.go" `/^func loadPage/` `/^}/`}}

The function loadPage constructs the file name from -Title, reads the file's contents into a new -Page, and returns a pointer to that new page. +the title parameter, reads the file's contents into a new +variable body, and returns two values: a pointer to a +Page literal constructed with the proper title and body +values and nil for the error value.

-Functions can return multiple values. The standard library function -io.ReadFile returns []byte and error. +Functions can return multiple values. The standard library function +io.ReadFile returns []byte and error. In loadPage, error isn't being handled yet; the "blank identifier" represented by the underscore (_) 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).

@@ -152,7 +154,7 @@ function to return *Page and error.

Callers of this function can now check the second parameter; if it is nil then it has successfully loaded a Page. If not, it will be an -error that can be handled by the caller (see the +error that can be handled by the caller (see the language specification for details).

@@ -172,7 +174,7 @@ printed to the screen.

-You can compile and run the program like this: +You can compile and run the program like this:

@@ -182,7 +184,7 @@ This is a sample page.
 

-(If you're using Windows you must type "wiki" without the +(If you're using Windows you must type "wiki" without the "./" to run the program.)

@@ -199,10 +201,10 @@ Here's a full working example of a simple web server: {{code "doc/articles/wiki/http-sample.go"}}

-The main function begins with a call to -http.HandleFunc, which tells the http package to -handle all requests to the web root ("/") with -handler. +The main function begins with a call to +http.HandleFunc, which tells the http package to +handle all requests to the web root ("/") with +handler.

@@ -219,20 +221,20 @@ its arguments.

-An http.ResponseWriter value assembles the HTTP server's response; by writing +An http.ResponseWriter value assembles the HTTP server's response; by writing to it, we send data to the HTTP client.

An http.Request is a data structure that represents the client -HTTP request. The string r.URL.Path is the path component -of the request URL. The trailing [1:] means -"create a sub-slice of Path from the 1st character to the end." +HTTP request. r.URL.Path is the path component +of the request URL. The trailing [1:] means +"create a sub-slice of Path from the 1st character to the end." This drops the leading "/" from the path name.

-If you run this program and access the URL: +If you run this program and access the URL:

http://localhost:8080/monkeys

@@ -249,13 +251,14 @@ To use the net/http package, it must be imported:

 import (
 	"fmt"
-	"net/http"
 	"io/ioutil"
+	"net/http"
 )
 

-Let's create a handler to view a wiki page: +Let's create a handler, viewHandler that will allow users to +view a wiki page. It will handle URLs prefixed with "/view/".

{{code "doc/articles/wiki/part2.go" `/^const lenPath/`}} @@ -264,28 +267,28 @@ Let's create a handler to view a wiki page:

First, this function extracts the page title from r.URL.Path, -the path component of the request URL. The global constant +the path component of the request URL. The global constant lenPath is the length of the leading "/view/" component of the request path. -The Path is re-sliced with [lenPath:] to drop the -first 6 characters of the string. This is because the path will invariably -begin with "/view/", which is not part of the page title. +The Path is re-sliced with [lenPath:] to drop the +first 6 characters of the string. This is because the path will invariably +begin with "/view/", which is not part of the page's title.

-The function then loads the page data, formats the page with a string of simple -HTML, and writes it to w, the http.ResponseWriter. +The function then loads the page data, formats the page with a string of simple +HTML, and writes it to w, the http.ResponseWriter.

-Again, note the use of _ to ignore the error +Again, note the use of _ to ignore the error return value from loadPage. This is done here for simplicity and generally considered bad practice. We will attend to this later.

-To use this handler, we create a main function that -initializes http using the viewHandler to handle +To use this handler, we rewrite our main function to +initialize http using the viewHandler to handle any requests under the path /view/.

@@ -310,6 +313,11 @@ $ go build wiki.go $ ./wiki +

+(If you're using Windows you must type "wiki" without the +"./" to run the program.) +

+

With this web server running, a visit to http://localhost:8080/view/test @@ -326,14 +334,14 @@ form.

-First, we add them to main(): +First, we add them to main():

{{code "doc/articles/wiki/final-noclosure.go" `/^func main/` `/^}/`}}

-The function editHandler loads the page -(or, if it doesn't exist, create an empty Page struct), +The function editHandler loads the page +(or, if it doesn't exist, create an empty Page struct), and displays an HTML form.

@@ -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.

- +

The html/template package

@@ -354,20 +362,20 @@ underlying Go code.

-First, we must add html/template to the list of imports: +First, we must add html/template to the list of imports. We +also won't be using fmt anymore, so we have to remove that.

 import (
 	"html/template"
-	"http"
 	"io/ioutil"
-	"os"
+	"net/http"
 )
 

-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 edit.html, and add the following lines:

@@ -381,8 +389,8 @@ HTML: {{code "doc/articles/wiki/final-noerror.go" `/^func editHandler/` `/^}/`}}

-The function template.ParseFiles will read the contents of -edit.html and return a *template.Template. +The function template.ParseFiles will read the contents of +edit.html and return a *template.Template.

@@ -405,12 +413,7 @@ HTML.

-Now that we've removed the fmt.Fprintf statement, we can remove -"fmt" from the import list. -

- -

-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 viewHandler called view.html:

@@ -428,28 +431,31 @@ handlers. Let's remove this duplication by moving the templating code to its own function:

+{{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/` `/^}/`}}

-The handlers are now shorter and simpler. +If we comment out the registration of our unimplemented save handler in +main, we can once again build and test our program. +Click here to view the code we've written so far.

Handling non-existent pages

What if you visit -/view/APageThatDoesntExist? The program will crash. This is -because it ignores the error return value from loadPage. Instead, -if the requested Page doesn't exist, it should redirect the client to the edit -Page so the content may be created: +/view/APageThatDoesntExist? You'll see a page containing +HTML. This is because it ignores the error return value from +loadPage 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:

-{{code "doc/articles/wiki/final-noclosure.go" `/^func viewHandler/` `/^}/`}} +{{code "doc/articles/wiki/part3-errorhandling.go" `/^func viewHandler/` `/^}/`}}

-The http.Redirect function adds an HTTP status code of +The http.Redirect function adds an HTTP status code of http.StatusFound (302) and a Location header to the HTTP response.

@@ -457,22 +463,24 @@ header to the HTTP response.

Saving Pages

-The function saveHandler will handle the form submission. +The function saveHandler will handle the submission of forms +located on the edit pages. After uncommenting the related line in +main, let's implement the the handler:

{{code "doc/articles/wiki/final-template.go" `/^func saveHandler/` `/^}/`}}

-The page title (provided in the URL) and the form's only field, -Body, are stored in a new Page. +The page title (provided in the URL) and the form's only field, +Body, are stored in a new Page. The save() method is then called to write the data to a file, and the client is redirected to the /view/ page.

The value returned by FormValue is of type string. -We must convert that value to []byte before it will fit into -the Page struct. We use []byte(body) to perform +We must convert that value to []byte before it will fit into +the Page struct. We use []byte(body) to perform the conversion.

@@ -481,9 +489,9 @@ the conversion.

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.

@@ -493,7 +501,7 @@ First, let's handle the errors in renderTemplate: {{code "doc/articles/wiki/final-parsetemplate.go" `/^func renderTemplate/` `/^}/`}}

-The http.Error function sends a specified HTTP response code +The http.Error 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.

@@ -502,18 +510,18 @@ Already the decision to put this in a separate function is paying off. Now let's fix up saveHandler:

-{{code "doc/articles/wiki/final-noclosure.go" `/^func saveHandler/` `/^}/`}} +{{code "doc/articles/wiki/part3-errorhandling.go" `/^func saveHandler/` `/^}/`}}

-Any errors that occur during p.save() will be reported +Any errors that occur during p.save() will be reported to the user.

Template caching

-There is an inefficiency in this code: renderTemplate calls -ParseFiles every time a page is rendered. +There is an inefficiency in this code: renderTemplate calls +ParseFiles every time a page is rendered. A better approach would be to call ParseFiles once at program initialization, parsing all templates into a single *Template. Then we can use the @@ -536,10 +544,11 @@ can't be loaded the only sensible thing to do is exit the program.

-A for loop is used with a range 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 ParseFiles 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 ParseFiles call's +arguments.

@@ -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/`}}

-The function regexp.MustCompile will parse and compile the -regular expression, and return a regexp.Regexp. +The function regexp.MustCompile will parse and compile the +regular expression, and return a regexp.Regexp. MustCompile is distinct from Compile in that it will panic if the expression compilation fails, while Compile returns -an error as a second parameter. +an error as a second parameter.

-Now, let's write a function that extracts the title string from the request -URL, and tests it against our TitleValidator expression: +Now, let's write a function, getTitle, that extracts the title +string from the request URL, and tests it against our +TitleValidator expression:

{{code "doc/articles/wiki/final-noclosure.go" `/func getTitle/` `/^}/`}}

If the title is valid, it will be returned along with a nil -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 errors +package.

@@ -604,10 +615,10 @@ Let's put a call to getTitle in each of the handlers:

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 -function -literals 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 +function +literals provide a powerful means of abstracting functionality that can help us here.

@@ -654,19 +665,19 @@ Now we can take the code from getTitle and use it here

The closure returned by makeHandler is a function that takes an http.ResponseWriter and http.Request (in other -words, an http.HandlerFunc). +words, an http.HandlerFunc). The closure extracts the title from the request path, and validates it with the TitleValidator regexp. If the title is invalid, an error will be written to the -ResponseWriter using the http.NotFound function. +ResponseWriter using the http.NotFound function. If the title is valid, the enclosed handler function fn will be called with the ResponseWriter, Request, and title as arguments.

-Now we can wrap the handler functions with makeHandler in -main, before they are registered with the http +Now we can wrap the handler functions with makeHandler in +main, before they are registered with the http package:

@@ -698,7 +709,7 @@ $ ./wiki

Visiting http://localhost:8080/view/ANewPage -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.

@@ -710,11 +721,11 @@ Here are some simple tasks you might want to tackle on your own: @@ -1676,7 +1676,7 @@ instead of a Visitor interface value. The WalkFunc 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 filepath.SkipDir +the function should return the value filepath.SkipDir

{{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 examples in +The examples in the documentation for text/template can provide guidance.

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 @@

Origins

@@ -54,6 +55,38 @@ By its design, Go proposes an approach for the construction of system software on multicore machines. +

+What is the status of the project?

+ +

+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 released +on March 28, 2012. +Go 1, which includes a language specification, +standard libraries, +and custom tools, +provides a stable foundation for creating reliable products, projects, and publications. +

+ +

+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 long-term stability. +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. +

+ +

+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. +

+ +

+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. +

+

What is the origin of the name?

@@ -175,12 +208,12 @@ easier to understand what happens when things combine.

Is Google using Go internally?

-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 http://golang.org. It's just the godoc document server running in a production configuration on -Google App Engine. +Google App Engine.

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() {}

-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.

@@ -890,6 +923,32 @@ See the document for more information about how to proceed.

+

+Why does the project use Mercurial and not git?

+ +

+The Go project, hosted by Google Code at +code.google.com/p/go, +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 +codereview.appspot.com. +

+ +

+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. +

+

Pointers and Allocation

@@ -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.

@@ -994,9 +1053,11 @@ Why is int 32 bits on 64 bit machines?

The sizes of int and uint 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 -int. Code that relies on a particular +For portability, code that relies on a particular size of value should use an explicitly sized type, like int64. +Prior to Go 1.1, the 64-bit Go compilers (both gc and gccgo) used +a 32-bit representation for int. As of Go 1.1 they use +a 64-bit representation. On the other hand, floating-point scalars and complex numbers are always sized: float32, complex64, etc., because programmers should be aware of precision when using @@ -1038,6 +1099,22 @@ analysis recognizes some cases when such variables will not live past the return from the function and can reside on the stack.

+

+Why does my Go process use so much virtual memory?

+ +

+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. +

+ +

+To find the amount of actual memory allocated to a Go process, use the Unix +top command and consult the RES (Linux) or +RSIZE (Mac OS X) columns. + +

+

Concurrency

@@ -1071,7 +1148,7 @@ Why doesn't my multi-goroutine program use multiple CPUs?

You must set the GOMAXPROCS shell environment variable or use the similarly-named function 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.

@@ -1084,7 +1161,7 @@ Why does using GOMAXPROCS > 1 sometimes make my program slower?

-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 } }

-One might mistakenly expect to see a, b, c as the output. -What you'll probably see instead is c, c, c. This is because +One might mistakenly expect to see a, b, c as the output. +What you'll probably see instead is c, c, c. This is because each iteration of the loop uses the same instance of the variable v, 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 v at the time fmt.Println is executed, -but v may have been modified since the goroutine was launched. +but v may have been modified since the goroutine was launched. +To help detect this and other problems before they happen, run +go vet.

-To bind the value of v to each closure as they are launched, one -could modify the inner loop to read: +To bind the current value of v 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:

@@ -1202,11 +1282,26 @@ could modify the inner loop to read:
 

-In this example, the value of v is passed as an argument to the +In this example, the value of v is passed as an argument to the anonymous function. That value is then accessible inside the function as the variable u.

+

+Even easier is just to create a new variable, using a declaration style that may +seem odd but works fine in Go: +

+ +
+    for _, v := range values {
+        v := v // create a new 'v'.
+        go func() {
+            fmt.Println(v)
+            done <- true
+        }()
+    }
+
+

Control flow

@@ -1264,7 +1359,7 @@ builds a test binary, and runs it.

See the How to Write Go Code document, the testing package -and the go test subcommand for more details. +and the go test subcommand for more details.

@@ -1383,7 +1478,7 @@ For these reasons, Go allows neither.

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.

@@ -1430,13 +1525,13 @@ Why does Go perform badly on benchmark X?

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 test/bench/shootout. 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 test/bench/shootout. The slowest depend on libraries +for which versions of comparable performance are not available in Go. For instance, pidigits.go depends on a multi-precision math package, and the C versions, unlike Go's, use GMP (which is -written in optimized assembler). +written in optimized assembler). Benchmarks that depend on regular expressions (regex-dna.go, for instance) are essentially comparing Go's native regexp package to @@ -1455,7 +1550,7 @@ indicate.

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.)

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 print.

If the channel were buffered (e.g., c = make(chan int, 1)) then the program would not be guaranteed to print -"hello, world". (It might print the empty string; -it cannot print "goodbye, universe", nor can it crash.) +"hello, world". (It might print the empty string, +crash, or do something else.)

Locks

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 @@ @@ -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 character to refer to a Unicode code point. +will use the unqualified term character to refer to a Unicode code point +in the source text.

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.

+

+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. +

Characters

@@ -113,7 +118,7 @@ unicode_digit = /* a Unicode code point classified as "Decimal Digit" */ .

-In The Unicode Standard 6.0, +In The Unicode Standard 6.2, 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 integer, floating-point, imaginary, - character, or + rune, or string literal @@ -360,13 +365,15 @@ imaginary_lit = (decimals | float_lit) "i" . -

Character literals

+

Rune literals

-A character literal represents a character constant, -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 rune constant, +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.

@@ -380,8 +387,8 @@ a literal a, Unicode U+0061, value 0x61, while a literal a-dieresis, U+00E4, value 0xe4.

-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: \x followed by exactly two hexadecimal digits; \u followed by exactly four hexadecimal digits; \U 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)

-All other sequences starting with a backslash are illegal inside character literals. +All other sequences starting with a backslash are illegal inside rune literals.

-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
 
@@ -453,7 +465,8 @@ raw string literals and interpreted string literals. Raw string literals are character sequences between back quotes ``. 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 "". 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 \' is illegal and -\" is legal). The three-digit octal (\nnn) +are in rune literals (except that \' is illegal and +\" is legal), with the same restrictions. +The three-digit octal (\nnn) and two-digit hexadecimal (\xnn) escapes represent individual bytes of the resulting string; all other escapes represent the (possibly multi-byte) UTF-8 encoding of individual characters. @@ -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

@@ -501,15 +517,15 @@ These examples all represent the same string:

 "日本語"                                 // 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
 

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.

@@ -518,7 +534,7 @@ literal.

Constants

There are boolean constants, -character constants, +rune constants, integer constants, floating-point constants, complex constants, and string constants. Character, integer, floating-point, @@ -528,7 +544,7 @@ collectively called numeric constants.

A constant value is represented by a -character, +rune, integer, floating-point, imaginary, @@ -622,14 +638,15 @@ expressions.

A type determines the set of values and operations specific to values of that -type. A type may be specified by a (possibly qualified) type name -(§Qualified identifier, §Type declarations) or a type literal, +type. A type may be specified by a +(possibly qualified) type name +(§Type declarations) or a type literal, which composes a new type from previously declared types.

 Type      = TypeName | TypeLit | "(" Type ")" .
-TypeName  = QualifiedIdent .
+TypeName  = identifier | QualifiedIdent .
 TypeLit   = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
 	    SliceType | MapType | ChannelType .
 
@@ -646,7 +663,7 @@ type literals. The static type (or just type) of a variable is the type defined by its declaration. Variables of interface type also have a distinct dynamic type, 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 assignable to the static type of the interface variable. For non-interface @@ -764,19 +781,21 @@ particular architecture.

A string type 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 string. +

-The elements of strings have type byte and may be -accessed using the usual indexing operations. It is -illegal to take the address of such an element; if -s[i] is the ith byte of a -string, &s[i] is invalid. The length of string -s can be discovered using the built-in function -len. The length is a compile-time constant if s -is a string literal. +The length of a string s (its size in bytes) can be discovered using +the built-in function len. +The length is a compile-time constant if the string is a constant. +A string's bytes can be accessed by integer indices +0 through len(s)-1. +It is illegal to take the address of such an element; if +s[i] is the i'th byte of a +string, &s[i] is invalid.

@@ -796,12 +815,13 @@ ElementType = Type .

-The length is part of the array's type and must be a -constant expression that evaluates to a non-negative -integer value. The length of array a can be discovered -using the built-in function len(a). -The elements can be indexed by integer -indices 0 through len(a)-1Indexes). +The length is part of the array's type; it must evaluate to a non- +negative constant representable by a value +of type int. +The length of array a can be discovered +using the built-in function len. +The elements can be addressed by integer indices +0 through len(a)-1. Array types are always one-dimensional but may be composed to form multi-dimensional types.

@@ -830,9 +850,9 @@ SliceType = "[" "]" ElementType .

Like arrays, slices are indexable and have a length. The length of a slice s can be discovered by the built-in function -len(s); unlike with arrays it may change during -execution. The elements can be addressed by integer indices 0 -through len(s)-1Indexes). The slice index of a +len; unlike with arrays it may change during +execution. The elements can be addressed by integer indices +0 through len(s)-1. The slice index of a given element may be less than the index of the same element in the underlying array.

@@ -981,7 +1001,7 @@ promoted methods are included in the method set of the struct as follows: T. The method set of *S also includes promoted methods with receiver *T. - +
  • If S contains an anonymous field *T, the method sets of S and *S 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 tag, which becomes an attribute for all the fields in the corresponding field declaration. The tags are made -visible through a reflection interface +visible through a reflection interface but are otherwise ignored.

    @@ -1046,8 +1066,11 @@ ParameterDecl = [ IdentifierList ] [ "..." ] Type .

    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-blank names in the signature +must be unique. +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.

    @@ -1232,10 +1255,10 @@ map[string]interface{}

    The number of map elements is called its length. For a map m, it can be discovered using the -built-in function len(m) +built-in function len and may change during execution. Elements may be added during execution using assignments and retrieved with -index expressions; they may be removed with the +index expressions; they may be removed with the delete built-in function.

    @@ -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.

  • -
  • The scope of an imported package identifier is the file block +
  • The scope of the package name of an imported package is the file block of the file containing the import declaration.
  • -
  • The scope of an identifier denoting a function parameter or - result variable is the function body.
  • +
  • The scope of an identifier denoting a method receiver, function parameter, + or result variable is the function body.
  • 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

    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-blank 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.

     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
     

    @@ -1969,8 +1993,15 @@ is visible only within selectors for that type.

    -For a base type, the non-blank names of -methods bound to it must be unique. +A non-blank receiver identifier must be +unique 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. +

    + +

    +For a base type, the non-blank names of methods bound to it must be unique. If the base type is a struct type, the non-blank method and field names must be distinct.

    @@ -1996,12 +2027,6 @@ with receiver type *Point, to the base type Point.

    -

    -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. -

    -

    The type of a method is the type of a function with the receiver as first argument. For instance, the method Scale has type @@ -2026,25 +2051,33 @@ operators and functions to operands.

    Operands

    -Operands denote the elementary values in an expression. +Operands denote the elementary values in an expression. An operand may be a +literal, a (possibly qualified) identifier +denoting a +constant, +variable, or +function, +a method expression yielding a function, +or a parenthesized expression.

    -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.
     
    -

    Qualified identifiers

    -A qualified identifier is a non-blank 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 +blank.

    -QualifiedIdent = [ PackageName "." ] identifier .
    +QualifiedIdent = PackageName "." identifier .
     

    @@ -2089,7 +2122,7 @@ The types of the expressions must be assignable 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:

    • A key must be a field name declared in the LiteralType.
    • -
    • A literal that does not contain any keys must +
    • 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.
    • If any element has a key, every element must have a key.
    • -
    • A literal that contains keys does not need to +
    • 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.
    • 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.
    • 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 T, elements that are themselves composite literals may elide the respective literal type if it is identical to the element type of T. Similarly, elements that are addresses of composite literals may elide -the &T when the the element type is *T. +the &T when the element type is *T.

      @@ -2315,7 +2348,6 @@ Point{1, 2} m["foo"] s[i : j + 1] obj.color -math.Sin f.p[i].x() @@ -2323,7 +2355,9 @@ f.p[i].x()

      Selectors

      -A primary expression of the form +For a primary expression x +that is not a package name, the +selector expression

      @@ -2331,17 +2365,20 @@ x.f
       

      -denotes the field or method f of the value denoted by x -(or sometimes *x; see below). The identifier f -is called the (field or method) -selector; it must not be the blank identifier. -The type of the expression is the type of f. +denotes the field or method f of the value x +(or sometimes *x; see below). +The identifier f is called the (field or method) selector; +it must not be the blank identifier. +The type of the selector expression is the type of f. +If x is a package name, see the section on +qualified identifiers.

      +

      A selector f may denote a field or method f of a type T, or it may refer -to a field or method f of a nested anonymous field of -T. +to a field or method f of a nested +anonymous field of T. The number of anonymous fields traversed to reach f is called its depth in T. The depth of a field or method f @@ -2350,9 +2387,11 @@ The depth of a field or method f declared in an anonymous field A in T is the depth of f in A plus one.

      +

      The following rules apply to selectors:

      +
      1. For a value x of type T or *T @@ -2364,18 +2403,26 @@ If there is not exactly one f< with shallowest depth, the selector expression is illegal.
      2. -For a variable x of type I -where I is an interface type, -x.f denotes the actual method with name f of the value assigned -to x if there is such a method. -If no value or nil was assigned to x, x.f is illegal. +For a variable x of type I where I +is an interface type, x.f denotes the actual method with name +f of the value assigned to x. +If there is no method with name f in the +method set of I, the selector +expression is illegal.
      3. In all other cases, x.f is illegal.
      4. +
      5. +If x is of pointer or interface type and has the value +nil, assigning to, evaluating, or calling x.f +causes a run-time panic. +
      +

      -Selectors automatically dereference pointers to structs. +Selectors automatically dereference +pointers to structs. If x is a pointer to a struct, x.y is shorthand for (*x).y; if the field y is also a pointer to a struct, x.y.z is shorthand @@ -2384,6 +2431,7 @@ If x contains an anonymous field of type *A, where A is also a struct type, x.f is a shortcut for (*x.A).f.

      +

      For example, given the declarations:

      @@ -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() @@ -2434,7 +2482,7 @@ TODO: Specify what happens to receivers. --> -

      Indexes

      +

      Index expressions

      A primary expression of the form @@ -2451,17 +2499,36 @@ The value x is called the rules apply:

      +

      +If a is not a map: +

      +
        +
      • the index x must be an integer value; it is in range if 0 <= x < len(a), + otherwise it is out of range
      • +
      • a constant index must be non-negative + and representable by a value of type int +
      +

      For a of type A or *A -where A is an array type, -or for a of type S where S is a slice type: +where A is an array type:

        -
      • x must be an integer value and 0 <= x < len(a)
      • +
      • a constant index must be in range
      • +
      • if a is nil or if x is out of range at run time, + a run-time panic occurs
      • a[x] is the array element at index x and the type of - a[x] is the element type of A
      • -
      • if a is nil or if the index x is out of range, - a run-time panic occurs
      • + a[x] is the element type of A +
      + +

      +For a of type S where S is a slice type: +

      +
        +
      • if the slice is nil or if x is out of range at run time, + a run-time panic occurs
      • +
      • a[x] is the slice element at index x and the type of + a[x] is the element type of S

      @@ -2469,12 +2536,13 @@ For a of type T where T is a string type:

        -
      • x must be an integer value and 0 <= x < len(a)
      • +
      • a constant index must be in range + if the string a is also constant
      • +
      • if x is out of range at run time, + a run-time panic occurs
      • a[x] is the byte at index x and the type of - a[x] is byte
      • + a[x] is byte
      • a[x] may not be assigned to
      • -
      • if the index x is out of range, - a run-time panic occurs

      @@ -2483,14 +2551,14 @@ where M is a map type:

      • x's type must be - assignable - to the key type of M
      • + assignable + to the key type of M
      • if the map contains an entry with key x, - a[x] is the map value with key x - and the type of a[x] is the value type of M
      • + a[x] is the map value with key x + and the type of a[x] is the value type of M
      • if the map is nil or does not contain such an entry, - a[x] is the zero value - for the value type of M
      • + a[x] is the zero value + for the value type of M

      @@ -2533,9 +2601,9 @@ a[low : high]

      -constructs a substring or slice. The index expressions low and +constructs a substring or slice. The indices low and high 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 high - low. After slicing the array a

      @@ -2556,7 +2624,7 @@ s[2] == 4

      -For convenience, any of the index expressions may be omitted. A missing low +For convenience, any of the indices may be omitted. A missing low index defaults to zero; a missing high index defaults to the length of the sliced operand:

      @@ -2568,9 +2636,15 @@ a[:] // same as a[0 : len(a)]

      -For arrays or strings, the indexes low and high must -satisfy 0 <= low <= high <= length; for -slices, the upper bound is the capacity rather than the length. +For arrays or strings, the indices low and high are +in range if 0 <= low <= high <= len(a), +otherwise they are out of range. +For slices, the upper index bound is the slice capacity cap(a) rather than the length. +A constant index must be non-negative and representable by a value of type +int. +If both indices +are constant, they must satisfy low <= high. If a is nil +or if the indices are out of range at run time, a run-time panic occurs.

      @@ -2601,19 +2675,33 @@ The notation x.(T) is called a type assertion. More precisely, if T is not an interface type, x.(T) asserts that the dynamic type of x is identical to the type T. +In this case, T must implement the (interface) type of x; +otherwise the type assertion is invalid since it is not possible for x +to store a value of type T. If T is an interface type, x.(T) asserts that the dynamic type -of x implements the interface TInterface types). +of x implements the interface T.

      If the type assertion holds, the value of the expression is the value stored in x and its type is T. If the type assertion is false, a run-time panic occurs. In other words, even though the dynamic type of x -is known only at run-time, the type of x.(T) is +is known only at run time, the type of x.(T) is known to be T in a correct program.

      + +
      +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
      +
      +

      -If a type assertion is used in an assignment or initialization of the form +If a type assertion is used in an assignment or initialization of the form

      @@ -2629,7 +2717,7 @@ otherwise, the expression returns (Z, false) where Z
       is the zero value for type T.
       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.  (§Assignments)
      +returning a value and a boolean indicating success.
       

      @@ -2677,13 +2765,14 @@ causes a run-time panic.

      -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 g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call -of f must contain no parameters other than the call of g. +of f must contain no parameters other than the call of g, +and g must have at least one return value. If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters. @@ -2834,8 +2923,8 @@ As a consequence, statement *p++ is the same as (*p)++

      There are five precedence levels for binary operators. Multiplication operators bind strongest, followed by addition -operators, comparison operators, && (logical and), -and finally || (logical or): +operators, comparison operators, && (logical AND), +and finally || (logical OR):

      @@ -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
       

      -If the divisor is zero, a run-time panic occurs. -If the dividend is positive and the divisor is a constant power of 2, +If the divisor is a constant, it must not be zero. +If the divisor is zero at run time, a run-time panic 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:

      @@ -2976,10 +3066,10 @@ follows:
       

      -For floating-point numbers, +For floating-point and complex numbers, +x is the same as x, while -x is the negation of x. -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 run-time panic occurs is implementation-specific.

      @@ -3142,9 +3232,9 @@ The right operand is evaluated conditionally.

      -&&    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"
       
      @@ -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, x may also be a +(possibly parenthesized) composite literal.

      @@ -3171,6 +3262,7 @@ will cause a run-time panic.

       &x
       &a[f(2)]
      +&Point{2, 3}
       *p
       *pf(x)
       
      @@ -3181,9 +3273,13 @@ will cause a run-time panic.

      For an operand ch of channel type, the value of the receive operation <-ch is the value received -from the channel ch. The type of the value is the element type of -the channel. The expression blocks until a value is available. +from the channel ch. 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 nil channel blocks forever. +Receiving from a closed channel always succeeds, +immediately returning the element type's zero +value.

      @@ -3204,11 +3300,11 @@ var x, ok = <-ch
       

      -yields an additional result. -The boolean variable ok indicates whether -the received value was sent on the channel (true) -or is a zero value returned -because the channel is closed and empty (false). +yields an additional result of type bool reporting whether the +communication succeeded. The value of ok is true +if the value received was delivered by a successful send operation to the +channel, or false if it is a zero value generated because the +channel is closed and empty.

      - -
      - -
      - -
      - - -
      - -
      -
      - -
      - -
      - -
      -
      -

      The Go Programming Language

      -
      -

      Russ Cox

      - -
      -

      Stanford University

      January 12, 2010

      -
      -
      - -
      -

      Go

      - -

      New

      -

      Experimental

      -

      Concurrent

      -

      Garbage-collected

      -

      Systems

      -

      Language

      -
      - -
      -

      Hello, world

      -
      -package main
      -
      -import "fmt"
      -
      -func main() {
      -	fmt.Printf("Hello, 世界\n")
      -}
      -
      -
      - -
      -

      History

      - -

      Design started in late 2007.

      -

      Implementation starting to work mid-2008.

      -

      Released as an open source project in November 2009.

      -

      Work continues.

      -

      Robert Griesemer, Ken Thompson, Rob Pike, Ian Lance Taylor, Russ Cox, many others

      -
      - -
      -

      Why?

      - -

      Go fast!

      -

      Make programming fun again.

      -
      - -
      -

      Why isn't programming fun?

      - -
      -

      Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:

      - -
        -
      • verbose, lots of repetition
      • -
      • too much focus on type hierarchy
      • -
      • types get in the way as much as they help
      • -
      • compiles take far too long
      • -
      -
      - -
      -

      Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:

      - -
        -
      • errors at run time that should be caught statically
      • -
      • no compilation means slow code
      • -
      -
      - -

      Can we combine the best of both?

      -
      - -
      -

      Go

      - -

      Make the language fast.

      -

      Make the tools fast.

      -
      - -
      -

      Go Approach: Static Types

      - -

      Static types, but declarations can infer type from expression:

      - -
      -var one, hi = 1, "hello"
      -
      -var double = func(x int) int { return x*2 }
      -
      - -

      Not full Hindley-Milner type inference.

      -
      - - -
      -

      Go Approach: Methods

      - -

      Methods can be defined on any type.

      - -
      -type Point struct {
      -	X, Y float64
      -}
      -
      -func (p Point) Abs() float64 {
      -	return math.Sqrt(p.X*p.X + p.Y*p.Y)
      -}
      -
      -
      - -
      -

      Go Approach: Methods

      - -

      Methods can be defined on any type.

      - -
      -type MyFloat float64
      -
      -func (f MyFloat) Abs() float64 {
      -	v := float64(f)
      -	if v < 0 {
      -		v = -v
      -	}
      -	return v
      -}
      -
      -
      - -
      -

      Go Approach: Abstract Types

      - -

      An interface type lists a set of methods. Any value with those methods satisfies the interface.

      - -
      -type Abser interface {
      -	Abs() float64
      -}
      -
      -func AbsPrinter(a Abser)
      -
      - -

      Can use Point or MyFloat (or ...):

      - -
      -p := Point{3, 4}
      -AbsPrinter(p)
      -
      -f := MyFloat(-10)
      -AbsPrinter(f)
      -
      - -

      Notice that Point never declared that it implements Abser. It just does. Same with MyFloat.

      -
      - -
      -

      Go Approach: Packages

      - -

      A Go program comprises one or more packages.

      -

      Each package is one or more source files compiled and imported as a unit.

      -
      -package draw
      -
      -type Point struct {
      -	X, Y int
      -}
      -
      - -
      -package main
      -
      -import "draw"
      -
      -var p draw.Point
      -
      -
      - -
      -

      Go Approach: Visibility

      - -

      Inside a package, all locally defined names are visible in all source files.

      - -

      When imported, only the upper case names are visible.

      - -
      -package draw
      -
      -type Point struct {
      -	X, Y int
      -	dist float64
      -}
      -
      -type cache map[Point] float64
      -
      - -

      Clients that import "draw" can use the black names only.

      - -

      “Shift is the new public.”

      -
      - -
      -

      Go Approach: Concurrency

      - -

      Cheap to create a new flow of control (goroutine):

      - -
      -func main() {
      -	go expensiveComputation(x, y, z)
      -	anotherExpensiveComputation(a, b, c)
      -}
      -
      - -

      Two expensive computations in parallel.

      -
      - -
      -

      Go Approach: Synchronization

      - -

      Use explicit messages to communicate and synchronize.

      - -
      -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)
      -}
      -
      -

      Notice communication of result in addition to synchronization.

      -
      - -
      -

      Go Fast: Language

      - -

      Static types: enough to compile well, but inferred much of the time.

      - -

      Methods: on any type, orthogonal to type system.

      - -

      Abstract types: interface values, relations inferred statically.

      - -

      Visibility: inferred from case of name.

      - -

      Concurrency: lightweight way to start new thread of control.

      - -

      Synchronization: explicit, easy message passing.

      - -
      - -

      Lightweight feel of a scripting language but compiled.

      -
      - -
      -

      Compile fast

      - -
      -

      Observation: much of the compile time for a source file is spent processing - other, often unrelated files.

      - -

      In C: a.c includes b.h, which includes c.h, which includes d.h. -

      - -

      Except that it's more often a tree instead of a chain.

      - -

      On my Mac (OS X 10.5.8, gcc 4.0.1):

      -
        -
      • C: #include <stdio.h> reads 360 lines from 9 files. -
      • C++: #include <iostream> reads 25,326 lines from 131 files. -
      • Objective C: #include <Carbon/Carbon.h> reads 124,730 lines from 689 files. -
      - -

      And we haven't done any real work yet!

      - -

      Same story in Java, Python, but reading binaries instead of source files.

      -
      -
      - -
      -

      Implementation: Summarize Dependencies

      - -
      -package gui
      -
      -import "draw"
      -
      -type Mouse struct {
      -	Loc draw.Point
      -	Buttons uint
      -}
      -
      -

      Compiled form of gui summarizes the necessary part of draw (just Point).

      - -
      - -
      -

      Implementation: Summarize Dependencies

      - -

      Compiled form of gui summarizes the necessary part of draw (just Point). Pseudo-object:

      - -
      -package gui
      -type draw.Point struct {
      -	X, Y int
      -}
      -type gui.Mouse struct {
      -	Loc draw.Point
      -	Buttons uint
      -}
      -
      - -

      A file that imports gui compiles without consulting draw or its dependencies.

      - -

      In Go: import "fmt" reads one file: 184 lines summarizing types from 7 packages.

      - -

      Tiny effect in this program but can be exponential in large programs.

      -
      - -
      -

      Compilation Demo

      - -

      Build all standard Go packages: ~120,000 lines of code.

      -
      - -
      -

      Go Status

      - -
      -
      -

      Open source:

      -
        -
      • released on November 10, 2009 -
      • regular releases (~ weekly) -
      • all development done in public Mercurial repository -
      • outside contributions welcome -
      -
      - -
      -

      Portable:

      -
        -
      • FreeBSD, Linux, OS X (x86, x86-64) -
      • (in progress) Linux arm, Native Client x86, Windows x86. -
      -
      - -
      -

      Still in progress, experimental. Yet to come:

      -
        -
      • mature garbage collector -
      • generics? -
      • exceptions? -
      • unions or sum types? -
      -
      -
      - -
      - -
      -

      Questions?

      -

      -
      - -
      -

      -
      - -
      -
      - - 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 @@ - - - -Go, Networked (January 21, 2010) - - - - - - - - -
      - -
      - -
      - - -
      - -
      -
      - -
      - -
      - -
      -
      -

      The Go Programming Language

      -
      -

      Russ Cox

      - -
      -

      CNS Winter Research Review

      January 21, 2010

      -
      -
      - -
      -
      - -
      -

      Go

      - -

      New

      -

      Experimental

      -

      Concurrent

      -

      Garbage-collected

      -

      Systems

      -

      Language

      -
      - -
      -

      Hello, world

      -
      -package main
      -
      -import "fmt"
      -
      -func main() {
      -	fmt.Printf("Hello, 世界\n")
      -}
      -
      -
      - -
      -

      History

      - -

      Design started in late 2007.

      -

      Implementation starting to work mid-2008.

      -

      Released as an open source project in November 2009.

      -

      Work continues.

      -

      Robert Griesemer, Ken Thompson, Rob Pike, Ian Lance Taylor, Russ Cox, many others

      -
      - -
      -

      Goals and Motivation

      - -

      Go fast!

      -

      Make programming fun again.

      -

      Targeted at systems software, broadly.

      -
      - -
      -

      Why isn't programming fun?

      - -
      -

      Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:

      - -
        -
      • verbose, lots of repetition
      • -
      • too much focus on type hierarchy
      • -
      • types get in the way as much as they help
      • -
      • compiles take far too long
      • -
      -
      - -
      -

      Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:

      - -
        -
      • errors at run time that should be caught statically
      • -
      • no compilation means slow code
      • -
      -
      - -

      Can we combine the best of both?

      -
      - -
      -

      Why a new language?

      - -
      -

      No new systems language in 10+ years.

      -

      Current languages designed before ...

      -

      ... rise of large-scale, networked and multicore computing

      -

      ... rise of Internet-scale distributed development (many libraries)

      -
      -
      - -
      -

      Go

      - -

      Make the language fast.

      -

      Make the tools fast.

      -
      - -
      -

      Compilation Demo

      - -

      Build all standard Go packages: ~120,000 lines of code.

      -
      - -
      -

      Go in one slide

      - -

      Lightweight syntax.

      - -

      Static types: enough to compile well, but inferred much of the time.

      - -

      Methods: on any type, orthogonal to type system.

      - -

      Abstract types: interface values, relations inferred statically.

      - -

      Visibility: inferred from case of name.

      - -

      First-class functions.

      - -

      Garbage collection.

      - -
      - -

      Lightweight feel of a scripting language but compiled.

      -
      - -
      -

      Go, concurrently

      - -

      Cheap to create a new flow of control (goroutine):

      - -
      -func main() {
      -	go expensiveComputation(x, y, z)
      -	anotherExpensiveComputation(a, b, c)
      -}
      -
      - -

      Two expensive computations in parallel.

      -
      - -
      -

      Go, concurrently

      - -

      Cheap to create a new flow of control (goroutine):

      - -
      -	for {
      -		rw := l.Accept()
      -		conn := newConn(rw, handler)
      -		go conn.serve()
      -	}
      -
      - -

      Concurrent web server.

      -

      Network connections multiplexed onto epoll.

      -
        -
      • many blocked Read calls != many blocked OS threads
      • -
      - -
      - -
      -

      Go, synchronized

      - -

      Use explicit messages to communicate and synchronize.

      - -
      -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)
      -}
      -
      -

      Notice communication of result in addition to synchronization.

      -
      - -
      -

      Go, synchronized

      - -

      RPC client

      - -
      -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
      -}
      -
      -
      - -
      -

      Go, synchronized

      - -

      RPC client demux

      - -
      -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
      -	}
      -}
      -
      -
      - -
      -

      Go, synchronized

      - -

      RPC client demux

      - -
      -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
      -	}
      -}
      -
      -

      Read response from network.

      - -
      -

      Go, synchronized

      - -

      RPC client demux

      - -
      -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
      -	}
      -}
      -
      -

      Look up request by sequence number.

      - -
      -

      Go, synchronized

      - -

      RPC client demux

      - -
      -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
      -	}
      -}
      -
      -

      Decode response fields from payload.

      - -
      -

      Go, synchronized

      - -

      RPC client demux

      - -
      -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
      -	}
      -}
      -
      -

      Tell client that it finished.

      - -
      -

      Go, synchronized

      - -

      RPC client demux

      - -
      -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
      -	}
      -}
      -
      - -

      Can create multiple Calls with same Done channel -and distinguish which finished by inspecting value sent on channel. -

      - -
      - -
      -

      Goroutine demo

      - -

      Chain together 100,000 goroutines connected by 100,001 channels.

      - -

      Send a value to one end of the chain.

      - -

      Each passes it along, increments.

      - -

      Receive value out the other end of the chain.

      -
      - - -
      -

      Go Status

      -
      - -
      -

      Go Status

      - -

      Open source:

      -
        -
      • released on November 10, 2009 -
      • regular releases (~ weekly) -
      • all development done in public Mercurial repository -
      • outside contributions welcome -
      • two independent compiler implementations -
      • XML, JSON, HTTP, TLS/SSL, native RPC, (network channels,) ... -
      -
      - -
      -

      Go Status

      - -

      Open source

      - -

      Portable:

      -
        -
      • FreeBSD, Linux, OS X (x86, x86-64) -
      • (in progress) Linux arm, Native Client x86, Windows x86. -
      -
      - -
      -

      Go Status

      - -

      Open source

      -

      Portable

      - -

      Still in progress, experimental. Yet to come:

      -
        -
      • production garbage collector -
      • generics? -
      • exceptions? -
      • unions or sum types? -
      -
      - -
      -

      Questions?

      -

      -
      - -
      -

      -
      - -
      -
      - - 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 @@ - - - -Go Tech Talk - - - - - - - - -
      - -
      - -
      - - -
      - -
      -
      -
      - -
      -

      The Go Programming Language

      -
      -
      -

      Sydney University

      March 23, 2010

      -
      -
      - -
      -

      Go

      - -

      New

      -

      Experimental

      -

      Concurrent

      -

      Garbage Collected

      -

      Systems Language

      -
      - -
      -

      Hello, world

      -
      -package main
      -
      -import "fmt"
      -
      -func main() {
      -	fmt.Printf("Hello, 世界\n")
      -}
      -
      -
      - -
      -

      Hello, world 2.0

      - -

      Serving http://localhost:8080/world

      -
      -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))
      -}
      -
      -
      - -
      -

      New

      - -

      It's about two years old:

      -
        -
      • Design started in late 2007
      • -
      • Implementation starting to work mid-2008
      • -
      • Released as an open source project in November 2009
      • -
      • Development continues with an active community
      • -
      - -

      Why invent a new language? Older languages weren't designed for concurrency, but modern software needs it:

      -
        -
      • Large scale, networked computing, such as Google web search
      • -
      • Multi-core hardware
      • -
      -
      - -
      -

      New

      - -

      Older languages are also frustrating on a day-to-day basis

      -

      Statically-typed languages (C, C++, Java) have issues:

      -
        -
      • Edit-Compile-Run cycle takes far too long
      • -
      • Type hierarchy can hurt as much as it helps
      • -
      -
      -
      -
      - -

      Dynamic languages (Python, JavaScript) fix some issues but introduce others:

      -
        -
      • No compilation means slow code
      • -
      • Runtime errors that should be caught statically
      • -
      - -

      Go has the lighter feel of a scripting language but is compiled

      -
      - -
      -

      New

      - -

      Large C++ programs (e.g. Firefox, OpenOffice, Chromium) have enormous build times:

      - - -

      On a Mac (OS X 10.5.8, gcc 4.0.1):

      -
        -
      • C: #include <stdio.h> reads 360 lines from 9 files
      • -
      • C++: #include <iostream> reads 25,326 lines from 131 files
      • -
      • Objective-C: #include <Carbon/Carbon.h> reads 124,730 lines from 689 files
      • -
      • We haven't done any real work yet!
      • -
      - -

      In Go: import "fmt" reads one file: 184 lines summarizing 7 packages

      -
      - -
      -

      New

      - -

      Compilation demo

      -
      - -
      -

      Experimental

      - -

      Go is still unproven

      -

      Language is still evolving

      -

      Package library is incomplete

      -

      Concurrent garbage collection is an active research problem

      -

      Reviving forgotten concepts:

      -
        -
      • Go's concurrency is strongly influenced by Communicating Sequential Processes (Hoare, 1978)
      • -
      • 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)
      • -
      -
      - -
      -

      Concurrent

      - -

      Unix philosophy: write programs that do one thing and do it well

      -

      Connect them with pipes:

      -
        -
      • How many lines of test code are there in the Go standard library?
      • -
      • find ~/go/src/pkg | grep _test.go$ | xargs wc -l
      • -
      - -

      Unlike other languages, Go makes it easy to:

      -
        -
      • Launch goroutines
      • -
      • Connect them with channels
      • -
      -
      - -
      -

      Concurrent

      - -

      Start a new flow of control with the go keyword

      -

      Parallel computation is easy:

      -
      -func main() {
      -	go expensiveComputation(x, y, z)
      -	anotherExpensiveComputation(a, b, c)
      -}
      -
      - -

      Roughly speaking, a goroutine is like a thread, but lighter weight:

      -
        -
      • Goroutines have segmented stacks, and typically smaller stacks
      • -
      • This requires compiler support. Goroutines can't just be a C++ library on top of a thread library
      • -
      -
      - -
      -

      Concurrent

      - -

      Consider web servers ("the C10k problem"):

      -
        -
      • "Thread per connection" approach is conceptually neat, but doesn't scale well in practice
      • -
      • What does scale well (event-driven callbacks, asynchronous APIs) are harder to understand, maintain, and debug
      • -
      • We think "goroutine per connection" can scale well, and is conceptually neat
      • -
      -
      -	for {
      -		rw := socket.Accept()
      -		conn := newConn(rw, handler)
      -		go conn.serve()
      -	}
      -
      -
      - -
      -

      Concurrent

      - -

      Let's look again at our simple parallel computation:

      -
      -func main() {
      -	go expensiveComputation(x, y, z)
      -	anotherExpensiveComputation(a, b, c)
      -}
      -
      - -

      This story is incomplete:

      -
        -
      • How do we know when the two computations are done?
      • -
      • What are their values?
      • -
      -
      - -
      -

      Concurrent

      - -

      Goroutines communicate with other goroutines via channels

      -
      -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)
      -}
      -
      - -
      - -
      -

      Concurrent

      - -

      In traditional concurrent programs, you communicate by sharing memory. In Go, you share memory by communicating:

      -
        -
      • Communication (the <- operator) is sharing and synchronization
      • -
      - -

      Threads and locks are concurrency primitives; CSP is a concurrency model:

      -
        -
      • Analogy: "Go To Statement Considered Harmful" (Dijsktra, 1968)
      • -
      • goto is a control flow primitive; structured programming (if statements, for loops, function calls) is a control flow model
      • -
      - -

      Learning CSP changes the way you think about concurrent programming:

      -
        -
      • Every language has its grain. If your Go program uses mutexes, you're probably working against the grain
      • -
      -
      - -
      -

      Garbage Collected

      - -

      Automatic memory management makes writing (and maintaining) programs easier

      -

      Especially in a concurrent world:

      -
        -
      • Who "owns" a shared piece of memory, and is responsible for destroying it?
      • -
      - -

      Large C++ programs usually end up with semi-automatic memory management anyway, via "smart pointers"

      -

      Mixing the two models can be problematic:

      -
        -
      • Browsers can leak memory easily; DOM elements are C++ objects, but JavaScript is garbage collected
      • -
      -
      - -
      -

      Garbage Collected

      - -

      Go is also a safer language:

      -
        -
      • Pointers but no pointer arithmetic
      • -
      • No dangling pointers
      • -
      • Variables are zero-initialized
      • -
      • Array access is bounds-checked
      • -
      - -

      No buffer overflow exploits

      -
      - -
      -

      Systems Language

      - -

      This just means you could write decently large programs in Go:

      -
        -
      • Web servers
      • -
      • Web browsers
      • -
      • Web crawlers
      • -
      • Search indexers
      • -
      • Databases
      • -
      • Word processors
      • -
      • Integrated Development Environments (IDEs)
      • -
      • Operating systems
      • -
      • ...
      • -
      -
      - -
      -

      Systems Language

      - -

      Garbage collection has a reputation for being "slower"

      -

      We're expecting Go to be slightly slower than optimized C, but faster than Java, depending on the task. Nonetheless:

      -
        -
      • Fast and buggy is worse than almost-as-fast and correct
      • -
      • It is easier to optimize a correct program than to correct an optimized program
      • -
      • Fundamentally, it's simply a trade-off we're willing to make
      • -
      - -

      Memory layout can drastically affect performance. These two designs are equivalent in Go, but significantly different in Java:

      -
      -type Point struct { X, Y int }
      -type Rect struct { P0, P1 Point }
      -
      -// or ...
      -
      -type Rect struct { X0, Y0, X1, Y1 int }
      -
      -
      - -
      -

      Systems Language

      - -

      Quote from http://loadcode.blogspot.com/2009/12/go-vs-java.html

      - -

      -"[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. -

      - -

      Shawn O. Pearce wrote on the git mailinglist:

      -
      • "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" -
      - -

      -Like C, Go does allow unsigned types and defining data structures -containing other data structures as continuous blocks of memory." -

      -
      - -
      -

      Go

      - -

      New

      -

      Experimental

      -

      Concurrent

      -

      Garbage Collected

      -

      Systems Language

      - -

      And more:

      -
        -
      • I haven't talked about the type system, interfaces, slices, closures, selects, ...
      • -
      • Documentation, mailing list, source code all online
      • -
      -
      - -
      -

      Questions?

      -

      -
      - -
      -
      - - diff --git a/doc/talks/gofrontend-gcc-summit-2010.pdf b/doc/talks/gofrontend-gcc-summit-2010.pdf deleted file mode 100644 index 157fd7676..000000000 Binary files a/doc/talks/gofrontend-gcc-summit-2010.pdf and /dev/null differ 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 deleted file mode 100644 index aff42c21d..000000000 Binary files a/doc/talks/io2010/talk.pdf and /dev/null differ diff --git a/doc/talks/io2011/Real_World_Go.pdf b/doc/talks/io2011/Real_World_Go.pdf deleted file mode 100644 index 2a187116b..000000000 Binary files a/doc/talks/io2011/Real_World_Go.pdf and /dev/null differ diff --git a/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf b/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf deleted file mode 100644 index ca4702ee9..000000000 Binary files a/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf and /dev/null differ diff --git a/doc/talks/java-typing.png b/doc/talks/java-typing.png deleted file mode 100644 index 54abf0186..000000000 Binary files a/doc/talks/java-typing.png and /dev/null differ 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. - // - // 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
      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
      -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
      -// 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, ">"); - - 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 ""; -} -- cgit v1.2.3