{`protobuf:"PB(1,2)"`, `rotobuf`, ``},
{`protobuf:"PB(1,2)" json:"name"`, `json`, `name`},
{`protobuf:"PB(1,2)" json:"name"`, `protobuf`, `PB(1,2)`},
+ {`k0:"values contain spaces" k1:"and\ttabs"`, "k0", "values contain spaces"},
+ {`k0:"values contain spaces" k1:"and\ttabs"`, "k1", "and\ttabs"},
}
func TestTagGet(t *testing.T) {
// If the tag does not have the conventional format, the value
// returned by Get is unspecified.
func (tag StructTag) Get(key string) string {
+ // When modifying this code, also update the validateStructTag code
+ // in golang.org/x/tools/cmd/vet/structtag.go.
+
for tag != "" {
- // skip leading space
+ // Skip leading space.
i := 0
for i < len(tag) && tag[i] == ' ' {
i++
break
}
- // scan to colon.
- // a space or a quote is a syntax error
+ // Scan to colon. A space, a quote or a control character is a syntax error.
+ // Strictly speaking, control chars include the range [0x7f, 0x9f], not just
+ // [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
+ // as it is simpler to inspect the tag's bytes than the tag's runes.
i = 0
- for i < len(tag) && tag[i] != ' ' && tag[i] != ':' && tag[i] != '"' {
+ for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
i++
}
- if i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
+ if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
break
}
name := string(tag[:i])
tag = tag[i+1:]
- // scan quoted string to find value
+ // Scan quoted string to find value.
i = 1
for i < len(tag) && tag[i] != '"' {
if tag[i] == '\\' {
tag = tag[i+1:]
if key == name {
- value, _ := strconv.Unquote(qvalue)
+ value, err := strconv.Unquote(qvalue)
+ if err != nil {
+ break
+ }
return value
}
}