reflect: support for struct tag use by multiple packages

Each package using struct field tags assumes that
it is the only package storing data in the tag.
This CL adds support in package reflect for sharing
tags between multiple packages.  In this scheme, the
tags must be of the form

        key:"value" key2:"value2"

(raw strings help when writing that tag in Go source).

reflect.StructField's Tag field now has type StructTag
(a string type), which has method Get(key string) string
that returns the associated value.

Clients of json and xml will need to be updated.
Code that says

        type T struct {
                X int "name"
        }

should become

        type T struct {
                X int `json:"name"`  // or `xml:"name"`
        }

Use govet to identify struct tags that need to be changed
to use the new syntax.

R=r, r, dsymonds, bradfitz, kevlar, fvbommel, n13m3y3r
CC=golang-dev
https://golang.org/cl/4645069
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go
index 94b0fb5..34d74b3 100644
--- a/src/pkg/reflect/all_test.go
+++ b/src/pkg/reflect/all_test.go
@@ -127,17 +127,17 @@
 	},
 	{struct {
 		x struct {
-			a int8 "hi there"
+			a int8 `reflect:"hi there"`
 		}
 	}{},
-		`struct { a int8 "hi there" }`,
+		`struct { a int8 "reflect:\"hi there\"" }`,
 	},
 	{struct {
 		x struct {
-			a int8 "hi \x00there\t\n\"\\"
+			a int8 `reflect:"hi \x00there\t\n\"\\"`
 		}
 	}{},
-		`struct { a int8 "hi \x00there\t\n\"\\" }`,
+		`struct { a int8 "reflect:\"hi \\x00there\\t\\n\\\"\\\\\"" }`,
 	},
 	{struct {
 		x struct {
@@ -423,7 +423,7 @@
 
 	// make sure tag strings are not part of element type
 	typ = TypeOf(struct {
-		d []uint32 "TAG"
+		d []uint32 `reflect:"TAG"`
 	}{}).Field(0).Type
 	testType(t, 14, typ, "[]uint32")
 }
@@ -1544,3 +1544,23 @@
 		t.Errorf("after Fprintf CallSlice: %q != %q", b.String(), "hello 42 world")
 	}
 }
+
+var tagGetTests = []struct {
+	Tag   StructTag
+	Key   string
+	Value string
+}{
+	{`protobuf:"PB(1,2)"`, `protobuf`, `PB(1,2)`},
+	{`protobuf:"PB(1,2)"`, `foo`, ``},
+	{`protobuf:"PB(1,2)"`, `rotobuf`, ``},
+	{`protobuf:"PB(1,2)" json:"name"`, `json`, `name`},
+	{`protobuf:"PB(1,2)" json:"name"`, `protobuf`, `PB(1,2)`},
+}
+
+func TestTagGet(t *testing.T) {
+	for _, tt := range tagGetTests {
+		if v := tt.Tag.Get(tt.Key); v != tt.Value {
+			t.Errorf("StructTag(%#q).Get(%#q) = %#q, want %#q", tt.Tag, tt.Key, v, tt.Value)
+		}
+	}
+}
diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go
index f774f73..a120da7 100644
--- a/src/pkg/reflect/type.go
+++ b/src/pkg/reflect/type.go
@@ -274,7 +274,7 @@
 
 // arrayType represents a fixed array type.
 type arrayType struct {
-	commonType "array"
+	commonType `reflect:"array"`
 	elem       *runtime.Type
 	slice      *runtime.Type
 	len        uintptr
@@ -282,14 +282,14 @@
 
 // chanType represents a channel type.
 type chanType struct {
-	commonType "chan"
+	commonType `reflect:"chan"`
 	elem       *runtime.Type
 	dir        uintptr
 }
 
 // funcType represents a function type.
 type funcType struct {
-	commonType "func"
+	commonType `reflect:"func"`
 	dotdotdot  bool
 	in         []*runtime.Type
 	out        []*runtime.Type
@@ -304,26 +304,26 @@
 
 // interfaceType represents an interface type.
 type interfaceType struct {
-	commonType "interface"
+	commonType `reflect:"interface"`
 	methods    []imethod
 }
 
 // mapType represents a map type.
 type mapType struct {
-	commonType "map"
+	commonType `reflect:"map"`
 	key        *runtime.Type
 	elem       *runtime.Type
 }
 
 // ptrType represents a pointer type.
 type ptrType struct {
-	commonType "ptr"
+	commonType `reflect:"ptr"`
 	elem       *runtime.Type
 }
 
 // sliceType represents a slice type.
 type sliceType struct {
-	commonType "slice"
+	commonType `reflect:"slice"`
 	elem       *runtime.Type
 }
 
@@ -338,7 +338,7 @@
 
 // structType represents a struct type.
 type structType struct {
-	commonType "struct"
+	commonType `reflect:"struct"`
 	fields     []structField
 }
 
@@ -696,12 +696,72 @@
 	PkgPath   string // empty for uppercase Name
 	Name      string
 	Type      Type
-	Tag       string
+	Tag       StructTag
 	Offset    uintptr
 	Index     []int
 	Anonymous bool
 }
 
+// A StructTag is the tag string in a struct field.
+//
+// By convention, tag strings are a concatenation of
+// optionally space-separated key:"value" pairs.
+// Each key is a non-empty string consisting of non-control
+// characters other than space (U+0020 ' '), quote (U+0022 '"'),
+// and colon (U+003A ':').  Each value is quoted using U+0022 '"'
+// characters and Go string literal syntax.
+type StructTag string
+
+// Get returns the value associated with key in the tag string.
+// If there is no such key in the tag, Get returns the empty string.
+// If the tag does not have the conventional format, the value
+// returned by Get is unspecified, 
+func (tag StructTag) Get(key string) string {
+	for tag != "" {
+		// skip leading space
+		i := 0
+		for i < len(tag) && tag[i] == ' ' {
+			i++
+		}
+		tag = tag[i:]
+		if tag == "" {
+			break
+		}
+
+		// scan to colon.
+		// a space or a quote is a syntax error
+		i = 0
+		for i < len(tag) && tag[i] != ' ' && tag[i] != ':' && tag[i] != '"' {
+			i++
+		}
+		if i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
+			break
+		}
+		name := string(tag[:i])
+		tag = tag[i+1:]
+
+		// scan quoted string to find value
+		i = 1
+		for i < len(tag) && tag[i] != '"' {
+			if tag[i] == '\\' {
+				i++
+			}
+			i++
+		}
+		if i >= len(tag) {
+			break
+		}
+		qvalue := string(tag[:i+1])
+		tag = tag[i+1:]
+
+		if key == name {
+			value, _ := strconv.Unquote(qvalue)
+			return value
+		}
+	}
+	return ""
+}
+
 // Field returns the i'th struct field.
 func (t *structType) Field(i int) (f StructField) {
 	if i < 0 || i >= len(t.fields) {
@@ -723,7 +783,7 @@
 		f.PkgPath = *p.pkgPath
 	}
 	if p.tag != nil {
-		f.Tag = *p.tag
+		f.Tag = StructTag(*p.tag)
 	}
 	f.Offset = p.offset
 	f.Index = []int{i}