1
0
mirror of https://github.com/golang/go synced 2024-11-21 17:44:40 -07:00

doc/talks: remove talks, refer to talks.golang.org instead

These talks have been moved to the go.talks sub-repository:
        https://code.google.com/p/go.talks

R=rsc, r
CC=gobot, golang-dev
https://golang.org/cl/6529052
This commit is contained in:
Andrew Gerrand 2012-09-21 14:38:22 -05:00
parent 413fbed341
commit 439183eb0a
17 changed files with 1 additions and 5100 deletions

View File

@ -164,7 +164,7 @@ A panel discussion with David Symonds, Robert Griesemer, Rob Pike, Ken Thompson,
A talk by Rob Pike and Andrew Gerrand presented at Google I/O 2011. A talk by Rob Pike and Andrew Gerrand presented at Google I/O 2011.
It walks through the construction and deployment of a simple web application It walks through the construction and deployment of a simple web application
and unveils the <a href="http://blog.golang.org/2011/05/go-and-google-app-engine.html">Go runtime for App Engine</a>. and unveils the <a href="http://blog.golang.org/2011/05/go-and-google-app-engine.html">Go runtime for App Engine</a>.
See the <a href="/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf">presentation slides</a>. See the <a href="http://talks.golang.org/2011/Writing_Web_Apps_in_Go.pdf">presentation slides</a>.
</p> </p>
<h3 id="go_programming"><a href="http://www.youtube.com/watch?v=jgVhBThJdXc">Go Programming</a><font color="red">*</font></h3> <h3 id="go_programming"><a href="http://www.youtube.com/watch?v=jgVhBThJdXc">Go Programming</a><font color="red">*</font></h3>

Binary file not shown.

View File

@ -1,411 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Go (January 12, 2010)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="font-size-adjustment" content="-1" />
<link rel="stylesheet" href="slidy.css"
type="text/css" media="screen, projection, print" />
<script src="slidy.js" type="text/javascript">
</script>
</head>
<body>
<!-- this defines the slide background -->
<div class="background">
<div class="header">
<!-- sized and colored via CSS -->
</div>
<div class="footer"></div>
</div>
<div class="slide titlepage">
<div style="height: 135px; width: 480px; overflow: hidden; position: fixed; top: auto; bottom: 10px; left: auto; right: 0; ">
<img src="../gordon/bumper480x270.png" style="margin: -135px 0 0 0;"/>
</div>
<!-- <img src="google.png" style="position: fixed; top: auto; bottom: 30px; left: 20px; right: auto;"/> -->
<br/>
<img src="../go-logo-white.png">
<br/>
<br/>
<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
<div style="color: #ffcc00;">
<h2>Russ Cox</h2>
<!-- <h3><i>rsc@google.com</i></h3> -->
<br/>
<h3>Stanford University<br/><br/>January 12, 2010</h3>
</div>
</div>
<div class="slide">
<h1>Go</h1>
<h2>New</h2>
<h2>Experimental</h2>
<h2>Concurrent</h2>
<h2>Garbage-collected</h2>
<h2>Systems</h2>
<h2>Language</h2>
</div>
<div class="slide">
<h1>Hello, world</h1>
<pre>
package main
import "fmt"
func main() {
fmt.Printf("Hello, 世界\n")
}
</pre>
</div>
<div class="slide">
<h1>History</h1>
<h2>Design started in late 2007.</h2>
<h2>Implementation starting to work mid-2008.</h2>
<h2>Released as an open source project in November 2009.</h2>
<h2>Work continues.<h2>
<h2>Robert&nbsp;Griesemer, Ken&nbsp;Thompson, Rob&nbsp;Pike, Ian&nbsp;Lance&nbsp;Taylor, Russ&nbsp;Cox, many others</h2>
</div>
<div class="slide">
<h1>Why?</h1>
<h2>Go fast!</h2>
<h2>Make programming fun again.</h2>
</div>
<div class="slide">
<h1>Why isn't programming fun?</h1>
<div class="incremental">
<h2>Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:</h2>
<ul>
<li>verbose, lots of repetition</li>
<li>too much focus on type hierarchy</li>
<li>types get in the way as much as they help</li>
<li>compiles take far too long</li>
</ul>
</div>
<div class="incremental">
<h2>Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:</h2>
<ul>
<li>errors at run time that should be caught statically</li>
<li>no compilation means slow code</li>
</ul>
</div>
<h2 class="incremental">Can we combine the best of both?</h2>
</div>
<div class="slide">
<h1>Go</h1>
<h2>Make the language fast.</h2>
<h2>Make the tools fast.</h2>
</div>
<div class="slide">
<h1>Go Approach: Static Types</h1>
<h2>Static types, but declarations can infer type from expression:</h2>
<pre>
var one, hi = 1, "hello"
var double = func(x int) int { return x*2 }
</pre>
<h2>Not full Hindley-Milner type inference.</h2>
</div>
<div class="slide">
<h1>Go Approach: Methods</h1>
<h2>Methods can be defined on any type.</h2>
<pre>
type Point struct {
X, Y float64
}
func (p Point) Abs() float64 {
return math.Sqrt(p.X*p.X + p.Y*p.Y)
}
</pre>
</div>
<div class="slide">
<h1>Go Approach: Methods</h1>
<h2>Methods can be defined on any type.</h2>
<pre>
type MyFloat float64
func (f MyFloat) Abs() float64 {
v := float64(f)
if v < 0 {
v = -v
}
return v
}
</pre>
</div>
<div class="slide">
<h1>Go Approach: Abstract Types</h1>
<h2>An interface type lists a set of methods. Any value with those methods satisfies the interface.</h2>
<pre>
type Abser interface {
Abs() float64
}
func AbsPrinter(a Abser)
</pre>
<h2>Can use Point or MyFloat (or ...):</h2>
<pre>
p := Point{3, 4}
AbsPrinter(p)
f := MyFloat(-10)
AbsPrinter(f)
</pre>
<h2>Notice that Point never declared that it implements Abser. It just does. Same with MyFloat.</h2>
</div>
<div class="slide">
<h1>Go Approach: Packages</h1>
<h2>A Go program comprises one or more packages.</h2>
<h2>Each package is one or more source files compiled and imported as a unit.</h2>
<pre>
package draw
type Point struct {
X, Y int
}
</pre>
<pre>
package main
import "draw"
var p draw.Point
</pre>
</div>
<div class="slide">
<h1>Go Approach: Visibility</h1>
<h2>Inside a package, all locally defined names are visible in all source files.</h2>
<h2>When imported, only the upper case names are visible.</h2>
<pre>
package draw
type <span style="color: black;">Point</span> struct {
<span style="color: black;">X</span>, <span style="color: black;">Y</span> int
dist float64
}
type cache map[Point] float64
</pre>
<h2>Clients that <code>import "draw"</code> can use the black names only.</h2>
<h2>&ldquo;Shift is the new <code>public</code>.&rdquo;</h2>
</div>
<div class="slide">
<h1>Go Approach: Concurrency</h1>
<h2>Cheap to create a new flow of control (goroutine):</h2>
<pre>
func main() {
go expensiveComputation(x, y, z)
anotherExpensiveComputation(a, b, c)
}
</pre>
<h2>Two expensive computations in parallel.</h2>
</div>
<div class="slide">
<h1>Go Approach: Synchronization</h1>
<h2>Use explicit messages to communicate and synchronize.</h2>
<pre>
func computeAndSend(ch chan int, x, y, z int) {
ch <- expensiveComputation(x, y, z)
}
func main() {
ch := make(chan int)
go computeAndSend(ch, x, y, z)
v2 := anotherExpensiveComputation(a, b, c)
v1 := <-ch
fmt.Println(v1, v2)
}
</pre>
<h2>Notice communication of result in addition to synchronization.</h2>
</div>
<div class="slide">
<h1>Go Fast: Language</h1>
<h2 class="incremental">Static types: enough to compile well, but inferred much of the time.</h2>
<h2 class="incremental">Methods: on any type, orthogonal to type system.</h2>
<h2 class="incremental">Abstract types: interface values, relations inferred statically.</h2>
<h2 class="incremental">Visibility: inferred from case of name.</h2>
<h2 class="incremental">Concurrency: lightweight way to start new thread of control.</h2>
<h2 class="incremental">Synchronization: explicit, easy message passing.</h2>
<br/>
<h2 class="incremental">Lightweight feel of a scripting language but compiled.</h2>
</div>
<div class="slide">
<h1>Compile fast</h1>
<div class="incremental">
<h2>Observation: much of the compile time for a source file is spent processing
other, often unrelated files.</h2>
<h2>In C: <code>a.c</code> includes <code>b.h</code>, which includes <code>c.h</code>, which includes <code>d.h</code>.
</h2>
<h2>Except that it's more often a tree instead of a chain.</h2>
<h2>On my Mac (OS X 10.5.8, gcc 4.0.1):</h2>
<ul>
<li>C: <code>#include &lt;stdio.h&gt;</code> reads 360 lines from 9 files.
<li>C++: <code>#include &lt;iostream&gt;</code> reads 25,326 lines from 131 files.
<li>Objective C: <code>#include &lt;Carbon/Carbon.h&gt;</code> reads 124,730 lines from 689 files.
</ul>
<h2>And we haven't done any real work yet!</h2>
<h2>Same story in Java, Python, but reading binaries instead of source files.</h2>
</div>
</div>
<div class="slide">
<h1>Implementation: Summarize Dependencies</h1>
<pre>
package gui
import "draw"
type Mouse struct {
Loc draw.Point
Buttons uint
}
</pre>
<h2>Compiled form of <code>gui</code> summarizes the necessary part of <code>draw</code> (just <code>Point</code>).</h2>
</div>
<div class="slide">
<h1>Implementation: Summarize Dependencies</h1>
<h2>Compiled form of <code>gui</code> summarizes the necessary part of <code>draw</code> (just <code>Point</code>). Pseudo-object:</h2>
<pre>
package gui
type draw.Point struct {
X, Y int
}
type gui.Mouse struct {
Loc draw.Point
Buttons uint
}
</pre>
<h2>A file that imports <code>gui</code> compiles without consulting <code>draw</code> or its dependencies.</h2>
<h2>In Go: <code>import "fmt"</code> reads <i>one</i> file: 184 lines summarizing types from 7 packages.</h2>
<h2>Tiny effect in this program but can be exponential in large programs.</h2>
</div>
<div class="slide">
<h1>Compilation Demo</h1>
<h2>Build all standard Go packages: ~120,000 lines of code.</h2>
</div>
<div class="slide">
<h1>Go Status</h1>
<div class="incremental">
<div>
<h2>Open source:</h2>
<ul>
<li>released on November 10, 2009
<li>regular releases (~ weekly)
<li>all development done in public Mercurial repository
<li>outside contributions welcome
</ul>
</div>
<div>
<h2>Portable:</h2>
<ul>
<li>FreeBSD, Linux, OS X (x86, x86-64)
<li>(in progress) Linux arm, Native Client x86, Windows x86.
</ul>
</div>
<div>
<h2>Still in progress, experimental. Yet to come:</h2>
<ul>
<li>mature garbage collector
<li>generics?
<li>exceptions?
<li>unions or sum types?
</ul>
</div>
</div>
</div>
<div class="slide titlepage">
<h1>Questions?</h1>
<br><br>
<center>
<img src="../gordon/bumper640x360.png">
</center>
<br><br>
<div style="color: #ffcc00;">
<!-- <h3><i>rsc@google.com</i></h3> -->
</div>
</div>
</body></html>

View File

@ -1,453 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Go, Networked (January 21, 2010)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="font-size-adjustment" content="-1" />
<link rel="stylesheet" href="slidy.css"
type="text/css" media="screen, projection, print" />
<script src="slidy.js" type="text/javascript">
</script>
</head>
<body>
<!-- this defines the slide background -->
<div class="background">
<div class="header">
<!-- sized and colored via CSS -->
</div>
<div class="footer"></div>
</div>
<div class="slide titlepage">
<div style="height: 135px; width: 480px; overflow: hidden; position: fixed; top: auto; bottom: 10px; left: auto; right: 0; ">
<img src="../gordon/bumper480x270.png" style="margin: -135px 0 0 0;"/>
</div>
<!-- <img src="../google.png" style="position: fixed; top: auto; bottom: 30px; left: 20px; right: auto;"/> -->
<br/>
<img src="../go-logo-white.png">
<br/>
<br/>
<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
<div style="color: #ffcc00;">
<h2>Russ Cox</h2>
<!-- <h3><i>rsc@google.com</i></h3> -->
<br/>
<h3>CNS Winter Research Review<br/><br/>January 21, 2010</h3>
<br/>
<br/>
<!--
<h4><i>click to start; then left/right arrow to change slides</i></h4> -->
</div>
</div>
<div class="slide">
<h1>Go</h1>
<h2>New</h2>
<h2>Experimental</h2>
<h2>Concurrent</h2>
<h2>Garbage-collected</h2>
<h2>Systems</h2>
<h2>Language</h2>
</div>
<div class="slide">
<h1>Hello, world</h1>
<pre>
package main
import "fmt"
func main() {
fmt.Printf("Hello, 世界\n")
}
</pre>
</div>
<div class="slide">
<h1>History</h1>
<h2>Design started in late 2007.</h2>
<h2>Implementation starting to work mid-2008.</h2>
<h2>Released as an open source project in November 2009.</h2>
<h2>Work continues.<h2>
<h2>Robert&nbsp;Griesemer, Ken&nbsp;Thompson, Rob&nbsp;Pike, Ian&nbsp;Lance&nbsp;Taylor, Russ&nbsp;Cox, many others</h2>
</div>
<div class="slide">
<h1>Goals and Motivation</h1>
<h2>Go fast!</h2>
<h2>Make programming fun again.</h2>
<h2>Targeted at systems software, broadly.</h2>
</div>
<div class="slide">
<h1>Why isn't programming fun?</h1>
<div class="incremental">
<h2>Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:</h2>
<ul>
<li>verbose, lots of repetition</li>
<li>too much focus on type hierarchy</li>
<li>types get in the way as much as they help</li>
<li>compiles take far too long</li>
</ul>
</div>
<div class="incremental">
<h2>Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:</h2>
<ul>
<li>errors at run time that should be caught statically</li>
<li>no compilation means slow code</li>
</ul>
</div>
<h2 class="incremental">Can we combine the best of both?</h2>
</div>
<div class="slide">
<h1>Why a new language?</h1>
<div class="incremental">
<h2>No new systems language in 10+ years.</h2>
<h2>Current languages designed before ...</h2>
<h3>... rise of large-scale, networked and multicore computing</h3>
<h3>... rise of Internet-scale distributed development (many libraries)</h3>
</div>
</div>
<div class="slide">
<h1>Go</h1>
<h2>Make the language fast.</h2>
<h2>Make the tools fast.</h2>
</div>
<div class="slide">
<h1>Compilation Demo</h1>
<h2>Build all standard Go packages: ~120,000 lines of code.</h2>
</div>
<div class="slide">
<h1>Go in one slide</h1>
<h2 class="incremental">Lightweight syntax.</h2>
<h2 class="incremental">Static types: enough to compile well, but inferred much of the time.</h2>
<h2 class="incremental">Methods: on any type, orthogonal to type system.</h2>
<h2 class="incremental">Abstract types: interface values, relations inferred statically.</h2>
<h2 class="incremental">Visibility: inferred from case of name.</h2>
<h2 class="incremental">First-class functions.</h2>
<h2 class="incremental">Garbage collection.</h2>
<br/>
<h2 class="incremental">Lightweight feel of a scripting language but compiled.</h2>
</div>
<div class="slide">
<h1>Go, concurrently</h1>
<h2>Cheap to create a new flow of control (goroutine):</h2>
<pre>
func main() {
go expensiveComputation(x, y, z)
anotherExpensiveComputation(a, b, c)
}
</pre>
<h2>Two expensive computations in parallel.</h2>
</div>
<div class="slide">
<h1>Go, concurrently</h1>
<h2>Cheap to create a new flow of control (goroutine):</h2>
<pre>
for {
rw := l.Accept()
conn := newConn(rw, handler)
go conn.serve()
}
</pre>
<h2>Concurrent web server.</h2>
<h2>Network connections multiplexed onto epoll.</h2>
<ul>
<li>many blocked Read calls != many blocked OS threads</li>
</ul>
</div>
<div class="slide">
<h1>Go, synchronized</h1>
<h2>Use explicit messages to communicate and synchronize.</h2>
<pre>
func computeAndSend(ch chan int, x, y, z int) {
ch <- expensiveComputation(x, y, z)
}
func main() {
ch := make(chan int)
go computeAndSend(ch, x, y, z)
v2 := anotherExpensiveComputation(a, b, c)
v1 := <-ch
fmt.Println(v1, v2)
}
</pre>
<h2>Notice communication of result in addition to synchronization.</h2>
</div>
<div class="slide">
<h1>Go, synchronized</h1>
<h2>RPC client</h2>
<pre>
func (client *Client) Call(method string, args, reply interface{}) os.Error {
// Send RPC message.
call := client.Go(method, args, reply, nil)
// Read reply from Done channel.
<-call.Done
return call.Error
}
</pre>
</div>
<div class="slide">
<h1>Go, synchronized</h1>
<h2>RPC client demux</h2>
<pre>
func (client *Client) input() {
for {
resp := client.readResponse()
client.mutex.Lock()
c := client.pending[resp.Seq]
client.pending[resp.Seq] = c, false
client.mutex.Unlock()
if resp.Error != "" {
c.Error = os.ErrorString(resp.error)
}
resp.Decode(c.Reply)
c.Done <- c
}
}
</pre>
</div>
<div class="slide">
<h1>Go, synchronized</h1>
<h2>RPC client demux</h2>
<pre>
func (client *Client) input() {
for {
<font style="color: black;">resp := client.readResponse()</font>
client.mutex.Lock()
c := client.pending[resp.Seq]
client.pending[resp.Seq] = c, false
client.mutex.Unlock()
if resp.Error != "" {
c.Error = os.ErrorString(resp.error)
}
resp.Decode(c.Reply)
c.Done <- c
}
}
</pre>
<h2>Read response from network.</h2
</div>
<div class="slide">
<h1>Go, synchronized</h1>
<h2>RPC client demux</h2>
<pre>
func (client *Client) input() {
for {
resp := client.readResponse()
<font style="color: black;">client.mutex.Lock()
c := client.pending[resp.Seq]
client.pending[resp.Seq] = c, false
client.mutex.Unlock()</font>
if resp.Error != "" {
c.Error = os.ErrorString(resp.error)
}
resp.Decode(c.Reply)
c.Done <- c
}
}
</pre>
<h2>Look up request by sequence number.</h2
</div>
<div class="slide">
<h1>Go, synchronized</h1>
<h2>RPC client demux</h2>
<pre>
func (client *Client) input() {
for {
resp := client.readResponse()
client.mutex.Lock()
c := client.pending[resp.Seq]
client.pending[resp.Seq] = c, false
client.mutex.Unlock()
<font style="color: black;">if resp.Error != "" {
c.Error = os.ErrorString(resp.error)
}
resp.Decode(c.Reply)</font>
c.Done <- c
}
}
</pre>
<h2>Decode response fields from payload.</h2
</div>
<div class="slide">
<h1>Go, synchronized</h1>
<h2>RPC client demux</h2>
<pre>
func (client *Client) input() {
for {
resp := client.readResponse()
client.mutex.Lock()
c := client.pending[resp.Seq]
client.pending[resp.Seq] = c, false
client.mutex.Unlock()
if resp.Error != "" {
c.Error = os.ErrorString(resp.error)
}
resp.Decode(c.Reply)
<font style="color: black;">c.Done <- c</font>
}
}
</pre>
<h2>Tell client that it finished.</h2
</div>
<div class="slide">
<h1>Go, synchronized</h1>
<h2>RPC client demux</h2>
<pre>
func (client *Client) input() {
for {
resp := client.readResponse()
client.mutex.Lock()
c := client.pending[resp.Seq]
client.pending[resp.Seq] = c, false
client.mutex.Unlock()
if resp.Error != "" {
c.Error = os.ErrorString(resp.error)
}
resp.Decode(c.Reply)
c.Done <- c
}
}
</pre>
<h2>Can create multiple Calls with same Done channel
and distinguish which finished by inspecting value sent on channel.
</h2>
</div>
<div class="slide">
<h1>Goroutine demo</h1>
<h2>Chain together 100,000 goroutines connected by 100,001 channels.</h2>
<h2>Send a value to one end of the chain.</h2>
<h2>Each passes it along, increments.</h2>
<h2>Receive value out the other end of the chain.</h2>
</div>
<div class="slide">
<h1>Go Status</h1>
</div>
<div class="slide">
<h1>Go Status</h1>
<h2>Open source:</h2>
<ul>
<li>released on November 10, 2009
<li>regular releases (~ weekly)
<li>all development done in public Mercurial repository
<li>outside contributions welcome
<li>two independent compiler implementations
<li>XML, JSON, HTTP, TLS/SSL, native RPC, (network channels,) ...
</ul>
</div>
<div class="slide">
<h1>Go Status</h1>
<h2>Open source</h2>
<h2>Portable:</h2>
<ul>
<li>FreeBSD, Linux, OS X (x86, x86-64)
<li>(in progress) Linux arm, Native Client x86, Windows x86.
</ul>
</div>
<div class="slide">
<h1>Go Status</h1>
<h2>Open source</h2>
<h2>Portable</h2>
<h2>Still in progress, experimental. Yet to come:</h2>
<ul>
<li>production garbage collector
<li>generics?
<li>exceptions?
<li>unions or sum types?
</ul>
</div>
<div class="slide titlepage">
<h1>Questions?</h1>
<br><br>
<center>
<img src="../gordon/bumper640x360.png">
</center>
<br><br>
<div style="color: #ffcc00;">
<!-- <h3><i>rsc@google.com</i></h3> -->
</div>
</div>
</body></html>

View File

@ -1,395 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Go Tech Talk</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="font-size-adjustment" content="-1" />
<link rel="stylesheet" href="slidy.css"
type="text/css" media="screen, projection, print" />
<script src="slidy.js" type="text/javascript">
</script>
</head>
<body>
<!-- this defines the slide background -->
<div class="background">
<div class="header">
<!-- sized and colored via CSS -->
</div>
<div class="footer"></div>
</div>
<div class="slide titlepage">
<br/>
<br/>
<img src="../go-logo-white.png" width="588px" height="217px">
<br/>
<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
<div style="color: #ffcc00;">
<br/>
<h3>Sydney University<br/><br/>March 23, 2010</h3>
</div>
</div>
<div class="slide">
<h1>Go</h1>
<h2>New</h2>
<h2>Experimental</h2>
<h2>Concurrent</h2>
<h2>Garbage Collected</h2>
<h2>Systems Language</h2>
</div>
<div class="slide">
<h1>Hello, world</h1>
<pre>
package main
import "fmt"
func main() {
fmt.Printf("Hello, 世界\n")
}
</pre>
</div>
<div class="slide">
<h1>Hello, world 2.0</h1>
<h2>Serving <a href="http://localhost:8080/world">http://localhost:8080/world</a></h2>
<pre>
package main
import (
"fmt"
"http"
)
func handler(c *http.Conn, r *http.Request) {
fmt.Fprintf(c, "Hello, %s.", r.URL.Path[1:])
}
func main() {
http.ListenAndServe(":8080",
http.HandlerFunc(handler))
}
</pre>
</div>
<div class="slide">
<h1>New</h1>
<h2>It's about two years old:</h2>
<ul>
<li>Design started in late 2007</li>
<li>Implementation starting to work mid-2008</li>
<li>Released as an open source project in November 2009</li>
<li>Development continues with an active community</li>
</ul>
<h2>Why invent a new language? Older languages weren't designed for concurrency, but modern software needs it:</h2>
<ul>
<li>Large scale, networked computing, such as Google web search</li>
<li>Multi-core hardware</li>
</ul>
</div>
<div class="slide">
<h1>New</h1>
<h2>Older languages are also frustrating on a day-to-day basis</h2>
<h2>Statically-typed languages (C, C++, Java) have issues:</h2>
<ul>
<li>Edit-Compile-Run cycle takes far too long</li>
<li>Type hierarchy can hurt as much as it helps</li>
</ul>
<div style="text-align:center">
<img src="java-typing.png" width="800px" height="90px"><br>
</div>
<h2>Dynamic languages (Python, JavaScript) fix some issues but introduce others:</h2>
<ul>
<li>No compilation means slow code</li>
<li>Runtime errors that should be caught statically</li>
</ul>
<h2>Go has the lighter feel of a scripting language but is compiled</h2>
</div>
<div class="slide">
<h1>New</h1>
<h2>Large C++ programs (e.g. Firefox, OpenOffice, Chromium) have enormous build times:</h2>
<ul>
<li>XKCD's #1 Programmer Excuse for Legitimately Slacking Off: &quot;<a href="http://xkcd.com/303/">My Code's Compiling</a>&quot;</li>
</ul>
<h2>On a Mac (OS X 10.5.8, gcc 4.0.1):</h2>
<ul>
<li>C: <code>#include &lt;stdio.h&gt;</code> reads 360 lines from 9 files</li>
<li>C++: <code>#include &lt;iostream&gt;</code> reads 25,326 lines from 131 files</li>
<li>Objective-C: <code>#include &lt;Carbon/Carbon.h&gt;</code> reads 124,730 lines from 689 files</li>
<li>We haven't done any real work yet!</li>
</ul>
<h2>In Go: <code>import "fmt"</code> reads <i>one</i> file: 184 lines summarizing 7 packages</h2>
</div>
<div class="slide">
<h1>New</h1>
<h2>Compilation demo</h2>
</div>
<div class="slide">
<h1>Experimental</h1>
<h2>Go is still unproven</h2>
<h2>Language is still evolving</h2>
<h2>Package library is incomplete</h2>
<h2>Concurrent garbage collection is an active research problem</h2>
<h2>Reviving forgotten concepts:</h2>
<ul>
<li>Go's concurrency is strongly influenced by <i>Communicating Sequential Processes</i> (Hoare, 1978)</li>
<li>Go has types and interfaces, but no inheritance. It is arguably more object-oriented than previously mentioned languages, being closer to the original Smalltalk meaning (1970s)</li>
</ul>
</div>
<div class="slide">
<h1>Concurrent</h1>
<h2>Unix philosophy: write <i>programs</i> that do one thing and do it well</h2>
<h2>Connect them with <i>pipes</i>:</h2>
<ul>
<li>How many lines of test code are there in the Go standard library?</li>
<li><code>find ~/go/src/pkg | grep _test.go$ | xargs wc -l</code></li>
</ul>
<h2>Unlike other languages, Go makes it easy to:</h2>
<ul>
<li>Launch <i>goroutines</i></li>
<li>Connect them with <i>channels</i></li>
</ul>
</div>
<div class="slide">
<h1>Concurrent</h1>
<h2>Start a new flow of control with the <code>go</code> keyword</h2>
<h2>Parallel computation is easy:</h2>
<pre>
func main() {
go expensiveComputation(x, y, z)
anotherExpensiveComputation(a, b, c)
}
</pre>
<h2>Roughly speaking, a goroutine is like a thread, but lighter weight:</h2>
<ul>
<li>Goroutines have segmented stacks, and typically smaller stacks</li>
<li>This requires compiler support. Goroutines can't just be a C++ library on top of a thread library</li>
</ul>
</div>
<div class="slide">
<h1>Concurrent</h1>
<h2>Consider web servers ("the C10k problem"):</h2>
<ul>
<li>"Thread per connection" approach is conceptually neat, but doesn't scale well in practice</li>
<li>What does scale well (event-driven callbacks, asynchronous APIs) are harder to understand, maintain, and debug</li>
<li>We think "goroutine per connection" can scale well, and is conceptually neat</li>
</ul>
<pre>
for {
rw := socket.Accept()
conn := newConn(rw, handler)
go conn.serve()
}
</pre>
</div>
<div class="slide">
<h1>Concurrent</h1>
<h2>Let's look again at our simple parallel computation:</h2>
<pre>
func main() {
go expensiveComputation(x, y, z)
anotherExpensiveComputation(a, b, c)
}
</pre>
<h2>This story is incomplete:</h2>
<ul>
<li>How do we know when the two computations are done?</li>
<li>What are their values?</li>
</ul>
</div>
<div class="slide">
<h1>Concurrent</h1>
<h2>Goroutines communicate with other goroutines via channels</h2>
<pre>
func computeAndSend(ch chan int, x, y, z int) {
ch &lt;- expensiveComputation(x, y, z)
}
func main() {
ch := make(chan int)
go computeAndSend(ch, x, y, z)
v2 := anotherExpensiveComputation(a, b, c)
v1 := &lt;-ch
fmt.Println(v1, v2)
}
</pre>
</div>
<div class="slide">
<h1>Concurrent</h1>
<h2>In traditional concurrent programs, you <i>communicate by sharing memory</i>. In Go, you <i>share memory by communicating</i>:</h2>
<ul>
<li>Communication (the <code>&lt;-</code> operator) is sharing and synchronization</li>
</ul>
<h2>Threads and locks are concurrency primitives; CSP is a concurrency model:</h2>
<ul>
<li>Analogy: &quot;Go To Statement Considered Harmful&quot; (Dijsktra, 1968)</li>
<li><code>goto</code> is a control flow primitive; structured programming (<code>if</code> statements, <code>for</code> loops, function calls) is a control flow model</li>
</ul>
<h2>Learning CSP changes the way you think about concurrent programming:</h2>
<ul>
<li>Every language has its grain. If your Go program uses mutexes, you're probably working against the grain</li>
</ul>
</div>
<div class="slide">
<h1>Garbage Collected</h1>
<h2>Automatic memory management makes writing (and maintaining) programs easier</h2>
<h2>Especially in a concurrent world:</h2>
<ul>
<li>Who &quot;owns&quot; a shared piece of memory, and is responsible for destroying it?</li>
</ul>
<h2>Large C++ programs usually end up with semi-automatic memory management anyway, via &quot;smart pointers&quot;</h2>
<h2>Mixing the two models can be problematic:</h2>
<ul>
<li>Browsers can leak memory easily; DOM elements are C++ objects, but JavaScript is garbage collected</li>
</ul>
</div>
<div class="slide">
<h1>Garbage Collected</h1>
<h2>Go is also a safer language:</h2>
<ul>
<li>Pointers but no pointer arithmetic</li>
<li>No dangling pointers</li>
<li>Variables are zero-initialized</li>
<li>Array access is bounds-checked</li>
</ul>
<h2>No buffer overflow exploits</h2>
</div>
<div class="slide">
<h1>Systems Language</h1>
<h2>This just means you could write decently large programs in Go:</h2>
<ul>
<li>Web servers</li>
<li>Web browsers</li>
<li>Web crawlers</li>
<li>Search indexers</li>
<li>Databases</li>
<li>Word processors</li>
<li>Integrated Development Environments (IDEs)</li>
<li>Operating systems</li>
<li>...</li>
</ul>
</div>
<div class="slide">
<h1>Systems Language</h1>
<h2>Garbage collection has a reputation for being &quot;slower&quot;</h2>
<h2>We're expecting Go to be slightly slower than optimized C, but faster than Java, depending on the task. Nonetheless:</h2>
<ul>
<li>Fast and buggy is worse than almost-as-fast and correct</li>
<li>It is easier to optimize a correct program than to correct an optimized program</li>
<li>Fundamentally, it's simply a trade-off we're willing to make</li>
</ul>
<h2>Memory layout can drastically affect performance. These two designs are equivalent in Go, but significantly different in Java:</h2>
<pre>
type Point struct { X, Y int }
type Rect struct { P0, P1 Point }
// or ...
type Rect struct { X0, Y0, X1, Y1 int }
</pre>
</div>
<div class="slide">
<h1>Systems Language</h1>
<h2>Quote from http://loadcode.blogspot.com/2009/12/go-vs-java.html</h2>
<h2>
&quot;[Git] is known to be very fast. It is written in C. A Java version
JGit was made. It was considerably slower. Handling of memory and lack
of unsigned types was some of the important reasons.
</h2>
<h2>Shawn O. Pearce wrote on the git mailinglist:</h2>
<ul><li>&quot;JGit struggles with not
having an efficient way to represent a SHA-1. C can just say &quot;unsigned
char[20]&quot; 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&quot;
</li></ul>
<h2>
Like C, Go does allow unsigned types and defining data structures
containing other data structures as continuous blocks of memory.&quot;
</h2>
</div>
<div class="slide">
<h1>Go</h1>
<h2>New</h2>
<h2>Experimental</h2>
<h2>Concurrent</h2>
<h2>Garbage Collected</h2>
<h2>Systems Language</h2>
<h2>And more:</h2>
<ul>
<li>I haven't talked about the type system, interfaces, slices, closures, selects, ...</li>
<li>Documentation, mailing list, source code all online</li>
</ul>
</div>
<div class="slide titlepage">
<h1>Questions?</h1>
<br><br>
<center>
<img src="../gordon/bumper640x360.png" width="640px" height="360px">
</center>
</div>
</body></html>

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

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

File diff suppressed because it is too large Load Diff