in protoc-gen-go/generator/generator.go [1447:1559]
func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string {
optrepreq := ""
switch {
case isOptional(field):
optrepreq = "opt"
case isRequired(field):
optrepreq = "req"
case isRepeated(field):
optrepreq = "rep"
}
var defaultValue string
if dv := field.DefaultValue; dv != nil { // set means an explicit default
defaultValue = *dv
// Some types need tweaking.
switch *field.Type {
case descriptor.FieldDescriptorProto_TYPE_BOOL:
if defaultValue == "true" {
defaultValue = "1"
} else {
defaultValue = "0"
}
case descriptor.FieldDescriptorProto_TYPE_STRING,
descriptor.FieldDescriptorProto_TYPE_BYTES:
// Nothing to do. Quoting is done for the whole tag.
case descriptor.FieldDescriptorProto_TYPE_ENUM:
// For enums we need to provide the integer constant.
obj := g.ObjectNamed(field.GetTypeName())
if id, ok := obj.(*ImportedDescriptor); ok {
// It is an enum that was publicly imported.
// We need the underlying type.
obj = id.o
}
enum, ok := obj.(*EnumDescriptor)
if !ok {
log.Printf("obj is a %T", obj)
if id, ok := obj.(*ImportedDescriptor); ok {
log.Printf("id.o is a %T", id.o)
}
g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName()))
}
defaultValue = enum.integerValueAsString(defaultValue)
case descriptor.FieldDescriptorProto_TYPE_FLOAT:
if def := defaultValue; def != "inf" && def != "-inf" && def != "nan" {
if f, err := strconv.ParseFloat(defaultValue, 32); err == nil {
defaultValue = fmt.Sprint(float32(f))
}
}
case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
if def := defaultValue; def != "inf" && def != "-inf" && def != "nan" {
if f, err := strconv.ParseFloat(defaultValue, 64); err == nil {
defaultValue = fmt.Sprint(f)
}
}
}
defaultValue = ",def=" + defaultValue
}
enum := ""
if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
// We avoid using obj.GoPackageName(), because we want to use the
// original (proto-world) package name.
obj := g.ObjectNamed(field.GetTypeName())
if id, ok := obj.(*ImportedDescriptor); ok {
obj = id.o
}
enum = ",enum="
if pkg := obj.File().GetPackage(); pkg != "" {
enum += pkg + "."
}
enum += CamelCaseSlice(obj.TypeName())
}
packed := ""
if (field.Options != nil && field.Options.GetPacked()) ||
// Per https://developers.google.com/protocol-buffers/docs/proto3#simple:
// "In proto3, repeated fields of scalar numeric types use packed encoding by default."
(message.proto3() && (field.Options == nil || field.Options.Packed == nil) &&
isRepeated(field) && isScalar(field)) {
packed = ",packed"
}
fieldName := field.GetName()
name := fieldName
if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
// We must use the type name for groups instead of
// the field name to preserve capitalization.
// type_name in FieldDescriptorProto is fully-qualified,
// but we only want the local part.
name = *field.TypeName
if i := strings.LastIndex(name, "."); i >= 0 {
name = name[i+1:]
}
}
if json := field.GetJsonName(); field.Extendee == nil && json != "" && json != name {
// TODO: escaping might be needed, in which case
// perhaps this should be in its own "json" tag.
name += ",json=" + json
}
name = ",name=" + name
if message.proto3() {
name += ",proto3"
}
oneof := ""
if field.OneofIndex != nil {
oneof = ",oneof"
}
return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s",
wiretype,
field.GetNumber(),
optrepreq,
packed,
name,
enum,
oneof,
defaultValue))
}