types/known/structpb: preallocate map in AsMap

Change-Id: I4fe676418959c23055e91d99a07ee3be8d466e25
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/460215
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Joseph Tsai <joetsai@digital-static.net>
Reviewed-by: Michael Stapelberg <stapelberg@google.com>
diff --git a/cmd/protoc-gen-go/internal_gengo/well_known_types.go b/cmd/protoc-gen-go/internal_gengo/well_known_types.go
index 696dddb..47c4fa1 100644
--- a/cmd/protoc-gen-go/internal_gengo/well_known_types.go
+++ b/cmd/protoc-gen-go/internal_gengo/well_known_types.go
@@ -208,8 +208,7 @@
  "google.golang.org/protobuf/encoding/protojson" package
  ensures that they will be serialized as their JSON equivalent.
 
-
- Conversion to and from a Go interface
+ # Conversion to and from a Go interface
 
  The standard Go "encoding/json" package has functionality to serialize
  arbitrary types to a large degree. The Value.AsInterface, Struct.AsMap, and
@@ -222,8 +221,7 @@
  forms back as Value, Struct, and ListValue messages, use the NewStruct,
  NewList, and NewValue constructor functions.
 
-
- Example usage
+ # Example usage
 
  Consider the following example JSON object:
 
@@ -282,7 +280,6 @@
 		... // handle error
 	}
 	... // make use of m as a *structpb.Value
-
 `
 	case genid.File_google_protobuf_field_mask_proto:
 		return ` Package fieldmaskpb contains generated types for ` + genid.File_google_protobuf_field_mask_proto + `.
@@ -656,8 +653,9 @@
 		g.P("// AsMap converts x to a general-purpose Go map.")
 		g.P("// The map values are converted by calling Value.AsInterface.")
 		g.P("func (x *Struct) AsMap() map[string]interface{} {")
-		g.P("	vs := make(map[string]interface{})")
-		g.P("	for k, v := range x.GetFields() {")
+		g.P("	f := x.GetFields()")
+		g.P("	vs := make(map[string]interface{}, len(f))")
+		g.P("	for k, v := range f {")
 		g.P("		vs[k] = v.AsInterface()")
 		g.P("	}")
 		g.P("	return vs")
@@ -693,8 +691,9 @@
 		g.P("// AsSlice converts x to a general-purpose Go slice.")
 		g.P("// The slice elements are converted by calling Value.AsInterface.")
 		g.P("func (x *ListValue) AsSlice() []interface{} {")
-		g.P("	vs := make([]interface{}, len(x.GetValues()))")
-		g.P("	for i, v := range x.GetValues() {")
+		g.P("	vals := x.GetValues()")
+		g.P("	vs := make([]interface{}, len(vals))")
+		g.P("	for i, v := range vals {")
 		g.P("		vs[i] = v.AsInterface()")
 		g.P("	}")
 		g.P("	return vs")
diff --git a/types/known/structpb/struct.pb.go b/types/known/structpb/struct.pb.go
index 882b0af..89bdf57 100644
--- a/types/known/structpb/struct.pb.go
+++ b/types/known/structpb/struct.pb.go
@@ -44,8 +44,7 @@
 // "google.golang.org/protobuf/encoding/protojson" package
 // ensures that they will be serialized as their JSON equivalent.
 //
-//
-// Conversion to and from a Go interface
+// # Conversion to and from a Go interface
 //
 // The standard Go "encoding/json" package has functionality to serialize
 // arbitrary types to a large degree. The Value.AsInterface, Struct.AsMap, and
@@ -58,8 +57,7 @@
 // forms back as Value, Struct, and ListValue messages, use the NewStruct,
 // NewList, and NewValue constructor functions.
 //
-//
-// Example usage
+// # Example usage
 //
 // Consider the following example JSON object:
 //
@@ -118,7 +116,6 @@
 //		... // handle error
 //	}
 //	... // make use of m as a *structpb.Value
-//
 package structpb
 
 import (
@@ -218,8 +215,9 @@
 // AsMap converts x to a general-purpose Go map.
 // The map values are converted by calling Value.AsInterface.
 func (x *Struct) AsMap() map[string]interface{} {
-	vs := make(map[string]interface{})
-	for k, v := range x.GetFields() {
+	f := x.GetFields()
+	vs := make(map[string]interface{}, len(f))
+	for k, v := range f {
 		vs[k] = v.AsInterface()
 	}
 	return vs
@@ -596,8 +594,9 @@
 // AsSlice converts x to a general-purpose Go slice.
 // The slice elements are converted by calling Value.AsInterface.
 func (x *ListValue) AsSlice() []interface{} {
-	vs := make([]interface{}, len(x.GetValues()))
-	for i, v := range x.GetValues() {
+	vals := x.GetValues()
+	vs := make([]interface{}, len(vals))
+	for i, v := range vals {
 		vs[i] = v.AsInterface()
 	}
 	return vs