go.talks/pkg/socket: fix go-tour non-main package wrong message

Fixes golang/go#5871.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/11200044
diff --git a/pkg/socket/socket.go b/pkg/socket/socket.go
index df573d7..87655bf 100644
--- a/pkg/socket/socket.go
+++ b/pkg/socket/socket.go
@@ -16,6 +16,9 @@
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
+	"go/parser"
+	"go/token"
 	"io"
 	"io/ioutil"
 	"log"
@@ -24,6 +27,7 @@
 	"path/filepath"
 	"runtime"
 	"strconv"
+	"strings"
 	"unicode/utf8"
 
 	"code.google.com/p/go.net/websocket"
@@ -190,6 +194,12 @@
 		cmd.Env = append(cmd.Env, "GOMAXPROCS=2")
 	}
 	if err := cmd.Start(); err != nil {
+		// If we failed to exec, that might be because they built
+		// a non-main package instead of an executable.
+		// Check and report that.
+		if name, err := packageName(body); err == nil && name != "main" {
+			return errors.New(`executable programs must use "package main"`)
+		}
 		return err
 	}
 	p.run = cmd
@@ -227,6 +237,15 @@
 	return cmd
 }
 
+func packageName(body string) (string, error) {
+	f, err := parser.ParseFile(token.NewFileSet(), "prog.go",
+		strings.NewReader(body), parser.PackageClauseOnly)
+	if err != nil {
+		return "", err
+	}
+	return f.Name.String(), nil
+}
+
 // messageWriter is an io.Writer that converts all writes to Message sends on
 // the out channel with the specified id and kind.
 type messageWriter struct {