goprotobuf: Handle a non-pointer being passed to MarshalText.

R=r
CC=golang-dev
http://codereview.appspot.com/5876065
diff --git a/proto/text.go b/proto/text.go
index d781c68..f7279ae 100644
--- a/proto/text.go
+++ b/proto/text.go
@@ -408,10 +408,16 @@
 	aw.complete = true
 	aw.compact = compact
 
+	// Reject non-pointer inputs (it's a bad practice to pass potentially large protos around by value).
 	v := reflect.ValueOf(pb)
-	// We should normally be passed a struct, or a pointer to a struct,
-	// and we don't want the outer < and > in that case.
+	if v.Kind() != reflect.Ptr {
+		w.Write([]byte("<struct-by-value>"))
+		return
+	}
+
+	// Dereference the received pointer so we don't have outer < and >.
 	v = reflect.Indirect(v)
+
 	if v.Kind() == reflect.Struct {
 		writeStruct(aw, v)
 	} else {
diff --git a/proto/text_test.go b/proto/text_test.go
index e720bdd..7d8adfb 100644
--- a/proto/text_test.go
+++ b/proto/text_test.go
@@ -53,11 +53,11 @@
 			Connected: proto.Bool(true),
 		},
 		Others: []*pb.OtherMessage{
-			&pb.OtherMessage{
+			{
 				Key:   proto.Int64(0xdeadbeef),
 				Value: []byte{1, 65, 7, 12},
 			},
-			&pb.OtherMessage{
+			{
 				Weight: proto.Float32(6.022),
 				Inner: &pb.InnerMessage{
 					Host: proto.String("lesha.mtv"),
@@ -221,3 +221,12 @@
 		}
 	}
 }
+
+func TestNonPtrMessage(t *testing.T) {
+	// Ensure we don't panic when we pass a non-pointer to MarshalText.
+	var buf bytes.Buffer
+	proto.MarshalText(&buf, pb.MyMessage{})
+	if s := buf.String(); s != "<struct-by-value>" {
+		t.Errorf("got: %q, want %q", s, "<struct-by-value>")
+	}
+}