diff options
Diffstat (limited to 'content')
-rw-r--r-- | content/playground.article | 87 |
1 files changed, 42 insertions, 45 deletions
diff --git a/content/playground.article b/content/playground.article index d82ce19..1b3910b 100644 --- a/content/playground.article +++ b/content/playground.article @@ -6,20 +6,20 @@ Andrew Gerrand * Introduction -In September 2010 we [[http://blog.golang.org/introducing-go-playground][introduced the Go Playground]], +In September 2010 we [[https://blog.golang.org/introducing-go-playground][introduced the Go Playground]], a web service that compiles and executes arbitrary Go code and returns the program output. If you're a Go programmer then you have probably already used the playground -by using the [[http://play.golang.org][Go Playground]] directly, -taking the [[http://tour.golang.org][Go Tour]], -or running [[http://golang.org/pkg/strings/#pkg-examples][executable examples]] +by using the [[https://play.golang.org][Go Playground]] directly, +taking the [[https://tour.golang.org][Go Tour]], +or running [[https://golang.org/pkg/strings/#pkg-examples][executable examples]] from the Go documentation. You may also have used it by clicking one of the "Run" buttons in a slide -deck on [[http://talks.golang.org/][talks.golang.org]] or a post on this +deck on [[https://talks.golang.org/][talks.golang.org]] or a post on this very blog -(such as the [[http://blog.golang.org/strings][recent article on Strings]]). +(such as the [[https://blog.golang.org/strings][recent article on Strings]]). In this article we will take a look at how the playground is implemented and integrated with these services. @@ -35,7 +35,7 @@ programming using Go. The playground service has three parts: - A back end that runs on Google's servers. It receives RPC requests, compiles the user program using the gc tool chain, executes the user program, and returns the program output (or compilation errors) as the RPC response. -- A front end that runs on [[https://developers.google.com/appengine/][Google App Engine]]. It receives HTTP requests from the client and makes corresponding RPC requests to the back end. It also does some caching. +- A front end that runs on [[https://cloud.google.com/appengine/docs/go/][Google App Engine]]. It receives HTTP requests from the client and makes corresponding RPC requests to the back end. It also does some caching. - A JavaScript client that implements the user interface and makes HTTP requests to the front end. @@ -52,11 +52,8 @@ them under [[https://developers.google.com/native-client/][Native Client]] x86 programs inside web browsers. The back end uses a special version of the gc tool chain that generates NaCl executables. -(This special tool chain will be merged into the core for Go 1.3. -To learn more, read the [[http://golang.org/s/go13nacl][design document]]. -If you want to play with NaCl before then, you can -[[https://code.google.com/r/rsc-go13nacl/source/checkout][check out a fork]] -that has all the changes.) +(This special tool chain was merged into Go 1.3. +To learn more, read the [[https://golang.org/s/go13nacl][design document]].) NaCl limits the amount of CPU and RAM a program may consume, and it prevents programs from accessing the network or file system. @@ -91,10 +88,10 @@ Limiting the run time of each playground program makes our service more predictable and defends us against denial of service attacks. But these restrictions become stifling when running code that uses time. -The [[http://talks.golang.org/2012/concurrency.slide][Go Concurrency Patterns]] +The [[https://talks.golang.org/2012/concurrency.slide][Go Concurrency Patterns]] talk demonstrates concurrency with examples that use timing functions like -[[http://golang.org/pkg/time/#Sleep][`time.Sleep`]] and -[[http://golang.org/pkg/time/#After][`time.After`]]. +[[https://golang.org/pkg/time/#Sleep][`time.Sleep`]] and +[[https://golang.org/pkg/time/#After][`time.After`]]. When run under early versions of the playground, these programs' sleeps would have no effect and their behavior would be strange (and sometimes wrong). @@ -122,7 +119,7 @@ earliest timer and then wakes the timer goroutine. Execution continues and the program believes that time has passed, when in fact the sleep was nearly instantaneous. -These changes to the scheduler can be found in [[https://code.google.com/r/rsc-go13nacl/source/diff?spec=svnc9a5be0fa2db5edcf8f8788da9f7eed323df6c07&r=c9a5be0fa2db5edcf8f8788da9f7eed323df6c07&format=side&path=/src/pkg/runtime/proc.c#sc_svn35d5bae6aac826e6db1851ea14fe9f8da95088a8_2314][`proc.c`]] and [[https://code.google.com/r/rsc-go13nacl/source/diff?spec=svnc9a5be0fa2db5edcf8f8788da9f7eed323df6c07&r=c9a5be0fa2db5edcf8f8788da9f7eed323df6c07&format=side&path=/src/pkg/runtime/time.goc#sc_svnc9a5be0fa2db5edcf8f8788da9f7eed323df6c07_178][`time.goc`]]. +These changes to the scheduler can be found in [[https://golang.org/cl/73110043][`proc.c`]] and [[https://golang.org/cl/73110043][`time.goc`]]. Fake time fixes the issue of resource exhaustion on the back end, but what about the program output? It would be odd to see a program that sleeps run to @@ -141,7 +138,7 @@ correct timing, so that the output appears just as if the program were running locally. The playground's `runtime` package provides a special -[[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/runtime/sys_nacl_amd64p32.s?r=1f01be1a1dc2#54][`write` function]] +[[https://github.com/golang/go/blob/go1.3/src/pkg/runtime/sys_nacl_amd64p32.s#L54][`write` function]] that includes a small "playback header" before each write. The playback header comprises a magic string, the current time, and the length of the write data. A write with a playback header has this structure: @@ -201,24 +198,24 @@ system as usual, but when the process exits any changes to the file system are lost. There is also a provision to load a zip file into the file system at init time -(see [[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/unzip_nacl.go][`unzip_nacl.go`]]). +(see [[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/unzip_nacl.go][`unzip_nacl.go`]]). So far we have only used the unzip facility to provide the data files required to run the standard library tests, but we intend to provide playground programs with a set of files that can be used in documentation examples, blog posts, and the Go Tour. The implementation can be found in the -[[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/fs_nacl.go][`fs_nacl.go`]] and -[[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/fd_nacl.go][`fd_nacl.go`]] files +[[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/fs_nacl.go][`fs_nacl.go`]] and +[[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/fd_nacl.go][`fd_nacl.go`]] files (which, by virtue of their `_nacl` suffix, are built into package `syscall` only when `GOOS` is set to `nacl`). The file system itself is represented by the -[[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/fs_nacl.go?r=5317d308abe4078f68aecc14fd5fb95303d62a06#25][`fsys` struct]], +[[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/fs_nacl.go#L25][`fsys` struct]], of which a global instance (named `fs`) is created during init time. The various file-related functions then operate on `fs` instead of making the actual system call. -For instance, here is the [[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/fs_nacl.go?r=1f01be1a1dc2#467][`syscall.Open`]] function: +For instance, here is the [[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/fs_nacl.go#L467][`syscall.Open`]] function: func Open(path string, openmode int, perm uint32) (fd int, err error) { fs.mu.Lock() @@ -231,13 +228,13 @@ For instance, here is the [[https://code.google.com/r/rsc-go13nacl/source/browse } File descriptors are tracked by a global slice named -[[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/fd_nacl.go?r=1f01be1a1dc2#16][`files`]]. -Each file descriptor corresponds to a [[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/fd_nacl.go?r=1f01be1a1dc2#22][`file`]] -and each `file` provides a value that implements the [[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/fd_nacl.go?r=1f01be1a1dc2#29][`fileImpl`]] interface. +[[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/fd_nacl.go#L16][`files`]]. +Each file descriptor corresponds to a [[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/fd_nacl.go#L24][`file`]] +and each `file` provides a value that implements the [[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/fd_nacl.go#L29][`fileImpl`]] interface. There are several implementations of the interface: -- regular files and devices (such as `/dev/random`) are represented by [[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/fs_nacl.go?r=1f01be1a1dc2#58][`fsysFile`]], -- standard input, output, and error are instances of [[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/fd_nacl.go?r=1f01be1a1dc2#209][`naclFile`]], which uses system calls to interact with the actual files (these are a playground program's only way to interact with the outside world), +- regular files and devices (such as `/dev/random`) are represented by [[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/fs_nacl.go#L57][`fsysFile`]], +- standard input, output, and error are instances of [[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/fd_nacl.go#L215][`naclFile`]], which uses system calls to interact with the actual files (these are a playground program's only way to interact with the outside world), - network sockets have their own implementation, discussed in the next section. @@ -259,8 +256,8 @@ implementation of the fake network is larger and more complex than the fake file system. It must simulate read and write timeouts, different address types and protocols, and so on. -The implementation can be found in [[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/net_nacl.go?r=1f01be1a1dc2][`net_nacl.go`]]. -A good place to start reading is [[https://code.google.com/r/rsc-go13nacl/source/browse/src/pkg/syscall/net_nacl.go?r=1f01be1a1dc2#419][`netFile`]], the network socket implementation of the `fileImpl` interface. +The implementation can be found in [[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/net_nacl.go][`net_nacl.go`]]. +A good place to start reading is [[https://github.com/golang/go/blob/go1.3/src/pkg/syscall/net_nacl.go#L428][`netFile`]], the network socket implementation of the `fileImpl` interface. * The front end @@ -269,7 +266,7 @@ The playground front end is another simple program (shorter than 100 lines). It receives HTTP requests from the client, makes RPC requests to the back end, and does some caching. -The front end serves an HTTP handler at `http://golang.org/compile`. +The front end serves an HTTP handler at `https://golang.org/compile`. The handler expects a POST request with a `body` field (the Go program to run) and an optional `version` field (for most clients this should be `"2"`). @@ -279,7 +276,7 @@ When the front end receives a compilation request it first checks to see if it has cached the results of a previous compilation of that source. If found, it returns the cached response. The cache prevents popular programs such as those on the -[[http://golang.org/][Go home page]] from overloading the back ends. +[[https://golang.org/][Go home page]] from overloading the back ends. If there is no cached response, the front end makes an RPC request to the back end, stores the response in memcache, parses the playback events, and returns a JSON object to the client as the HTTP response (as described above). @@ -292,37 +289,37 @@ code for setting up the user interface (the code and output boxes, the run button, and so on) and communicating with the playground front end. This implementation is in the file -[[https://code.google.com/p/go/source/browse/godoc/static/playground.js?repo=tools][`playground.js`]] +[[https://github.com/golang/tools/blob/release-branch.go1.3/godoc/static/playground.js][`playground.js`]] in the `go.tools` repository, which can be imported from the -[[http://godoc.org/code.google.com/p/go.tools/godoc/static][`go.tools/godoc/static`]] package. +[[https://godoc.org/golang.org/x/tools/godoc/static][`golang.org/x/tools/godoc/static`]] package. Some of it is clean and some is a bit crufty, as it is the result of consolidating several divergent implementations of the client code. -The [[https://code.google.com/p/go/source/browse/godoc/static/playground.js?repo=tools#226][`playground`]] +The [[https://github.com/golang/tools/blob/release-branch.go1.3/godoc/static/playground.js#L226][`playground`]] function takes some HTML elements and turns them into an interactive playground widget. You should use this function if you want to put the playground on your own site (see 'Other clients' below). -The [[https://code.google.com/p/go/source/browse/godoc/static/playground.js?repo=tools#6][`Transport`]] +The [[https://github.com/golang/tools/blob/release-branch.go1.3/godoc/static/playground.js#L6][`Transport`]] interface (not formally defined, this being JavaScript) abstracts the user interface from the means of talking to the web front end. -[[https://code.google.com/p/go/source/browse/godoc/static/playground.js?repo=tools#43][`HTTPTransport`]] +[[https://github.com/golang/tools/blob/release-branch.go1.3/godoc/static/playground.js#L43][`HTTPTransport`]] is an implementation of `Transport` that speaks the HTTP-based protocol described earlier. -[[https://code.google.com/p/go/source/browse/godoc/static/playground.js?repo=tools#115][`SocketTransport`]] +[[https://github.com/golang/tools/blob/release-branch.go1.3/godoc/static/playground.js#L115][`SocketTransport`]] is another implementation that speaks WebSocket (see 'Playing offline' below). -To comply with the [[http://en.wikipedia.org/wiki/Same-origin_policy][same-origin policy]], +To comply with the [[https://en.wikipedia.org/wiki/Same-origin_policy][same-origin policy]], the various web servers (godoc, for instance) proxy requests to -`/compile` through to the playground service at `http://golang.org/compile`. -The common [[http://godoc.org/code.google.com/p/go.tools/playground][`go.tools/playground`]] +`/compile` through to the playground service at `https://golang.org/compile`. +The common [[https://godoc.org/golang.org/x/tools/playground][`golang.org/x/tools/playground`]] package does this proxying. * Playing offline -Both the [[http://tour.golang.org][Go Tour]] and the -[[http://godoc.org/code.google.com/p/go.talks/present][Present Tool]] can be +Both the [[https://tour.golang.org][Go Tour]] and the +[[https://godoc.org/golang.org/x/tools/present][Present Tool]] can be run offline. This is great for people with limited internet connectivity or presenters at conferences who cannot (and _should_ not) rely on a working internet connection. @@ -333,8 +330,8 @@ aforementioned modifications and uses a WebSocket to communicate with the client. The WebSocket back end implementation can be found in the -[[http://godoc.org/code.google.com/p/go.tools/playground/socket][`go.tools/playground/socket`]] package. -The [[http://talks.golang.org/2012/insidepresent.slide#1][Inside Present]] talk discusses this code in detail. +[[https://godoc.org/golang.org/x/tools/playground/socket][`golang.org/x/too/playground/socket`]] package. +The [[https://talks.golang.org/2012/insidepresent.slide#1][Inside Present]] talk discusses this code in detail. * Other clients @@ -359,5 +356,5 @@ With Native Client support scheduled for Go 1.3, we look forward to seeing what the community can do with it. _This_article_is_part_12_of_the_ -[[http://blog.gopheracademy.com/go-advent-2013][Go Advent Calendar]], +[[https://blog.gopheracademy.com/go-advent-2013][Go Advent Calendar]], _a_series_of_daily_blog_posts_throughout_December_._ |