Repository: goadesign/goa (go)

Issue:
Generated gRPC comments are merged with prior closing brace
In several places this results in the comment for the next section becoming a trailing comment on the prior syntax. For example in gen/grpc/*/client/client.go, diffed against the output from an embarassingly old version of goa:

```diff
@@ -20,27 +20,23 @@ import (
 type Client struct {
        grpccli some_servicepb.SomeServiceClient
        opts    []grpc.CallOption
-}
-
-// NewClient instantiates gRPC client for all the SomeService service servers.
+} // NewClient instantiates gRPC client for all the SomeService service servers.
```

I believe this is due to missing newlines at the end of the template files. (The http client_init.go.tpl ends in `7d` `0a`; the grpc client_init.go.tpl ends in `7d`.)

```console
% xxd http/codegen/templates/client_init.go.tpl | tail -n 3
00000310: 0909 636f 6e66 6967 7572 6572 3a20 6366  ..configurer: cf
00000320: 6e2c 0a09 097b 7b2d 2065 6e64 207d 7d0a  n,...{{- end }}.
00000330: 097d 0a7d 0a                             .}.}.

% xxd grpc/codegen/templates/client_init.go.tpl | tail -n 3
00000110: 6365 496e 6974 207d 7d28 6363 292c 0a09  ceInit }}(cc),..
00000120: 096f 7074 733a 206f 7074 732c 0a09 7d0a  .opts: opts,..}.
00000130: 7d
```

I'm unclear why the current templates have a mix of present and missing final newlines. I suspect they should at least be more similar between http and grpc, if not just always have them. Alternately, perhaps readTemplate should ensure a trailing newline.

```console
# (Note that the root codegen also has several templates without newlines.)
% find http grpc -name \*.tpl -print0 | xargs -0 -L1 bash -c 'test $(xxd -p -s -1 "$0") != 0a && echo "$0: no newline"'
http/codegen/templates/path_init.go.tpl: no newline
http/codegen/templates/request_init.go.tpl: no newline
http/codegen/templates/partial/client_type_conversion.go.tpl: no newline
http/codegen/templates/partial/query_slice_conversion.go.tpl: no newline
http/codegen/templates/partial/response.go.tpl: no newline
http/codegen/templates/partial/header_conversion.go.tpl: no newline
http/codegen/templates/partial/websocket_upgrade.go.tpl: no newline
http/codegen/templates/partial/single_response.go.tpl: no newline
http/codegen/templates/partial/query_type_conversion.go.tpl: no newline
http/codegen/templates/partial/slice_item_conversion.go.tpl: no newline
http/codegen/templates/partial/element_slice_conversion.go.tpl: no newline
http/codegen/templates/partial/client_map_conversion.go.tpl: no newline
http/codegen/templates/partial/query_map_conversion.go.tpl: no newline
http/codegen/templates/partial/path_conversion.go.tpl: no newline
http/codegen/templates/response_decoder.go.tpl: no newline
http/codegen/templates/path.go.tpl: no newline
http/codegen/templates/server_start.go.tpl: no newline
http/codegen/templates/append_fs.go.tpl: no newline
http/codegen/templates/cli_end.go.tpl: no newline
grpc/codegen/templates/request_encoder.go.tpl: no newline
grpc/codegen/templates/client_init.go.tpl: no newline
grpc/codegen/templates/do_grpc_cli.go.tpl: no newline
grpc/codegen/templates/partial/convert_string_to_type.go.tpl: no newline
grpc/codegen/templates/partial/convert_type_to_string.go.tpl: no newline
grpc/codegen/templates/client_struct.go.tpl: no newline
grpc/codegen/templates/response_decoder.go.tpl: no newline
grpc/codegen/templates/remote_method_builder.go.tpl: no newline
```

Pull request:
Always end template files in a newline
For most templates this works fine. For a few templates, this throws off whitespace.

- Address several by tweaking the partial meta-template in http/codegen/templates.go to trim leading and trailing whitespace. For reasons unexplored, this does not appear to be necessary in grpc or root templates.
- Address some more by stripping trailing whitespace in the template itself
- Address remainder by tweaking golden expectations around main (add empty lines before var(){} blocks)

fixes #3681

Patch:
diff --git a/codegen/example/templates/client_end.go.tpl b/codegen/example/templates/client_end.go.tpl
index 1dc5a4bf..21b99bc2 100644
--- a/codegen/example/templates/client_end.go.tpl
+++ b/codegen/example/templates/client_end.go.tpl
@@ -10,4 +10,4 @@
 		m, _ := json.MarshalIndent(data, "", "    ")
 		fmt.Println(string(m))
 	}
-}
\ No newline at end of file
+}
diff --git a/codegen/example/templates/client_endpoint_init.go.tpl b/codegen/example/templates/client_endpoint_init.go.tpl
index dc078c3c..c98f4fe2 100644
--- a/codegen/example/templates/client_endpoint_init.go.tpl
+++ b/codegen/example/templates/client_endpoint_init.go.tpl
@@ -1,5 +1,5 @@
 
-var(
+	var(
 		endpoint goa.Endpoint
 		payload any
 		err error
@@ -22,4 +22,4 @@ var(
 		fmt.Fprintln(os.Stderr, err.Error())
 		fmt.Fprintln(os.Stderr, "run '"+os.Args[0]+" --help' for detailed usage.")
 		os.Exit(1)
-}	
\ No newline at end of file
+	}
diff --git a/codegen/example/templates/client_start.go.tpl b/codegen/example/templates/client_start.go.tpl
index c3c59db4..a39b8b66 100644
--- a/codegen/example/templates/client_start.go.tpl
+++ b/codegen/example/templates/client_start.go.tpl
@@ -11,4 +11,4 @@ func main() {
 		timeoutF = flag.Int("timeout", 30, "Maximum number of seconds to wait for response")
 	)
 	flag.Usage = usage
-	flag.Parse()
\ No newline at end of file
+	flag.Parse()
diff --git a/codegen/example/templates/client_var_init.go.tpl b/codegen/example/templates/client_var_init.go.tpl
index a973146f..65f0430c 100644
--- a/codegen/example/templates/client_var_init.go.tpl
+++ b/codegen/example/templates/client_var_init.go.tpl
@@ -51,4 +51,4 @@ var (
 		}
 		scheme = u.Scheme
 		host = u.Host
-	}	
\ No newline at end of file
+	}
diff --git a/codegen/example/templates/server_end.go.tpl b/codegen/example/templates/server_end.go.tpl
index 8581650d..8cc3cf1b 100644
--- a/codegen/example/templates/server_end.go.tpl
+++ b/codegen/example/templates/server_end.go.tpl
@@ -8,4 +8,4 @@
 
 	wg.Wait()
 	log.Printf(ctx, "exited")
-}
\ No newline at end of file
+}
diff --git a/codegen/example/templates/server_endpoints.go.tpl b/codegen/example/templates/server_endpoints.go.tpl
index 97be6436..e0587e27 100644
--- a/codegen/example/templates/server_endpoints.go.tpl
+++ b/codegen/example/templates/server_endpoints.go.tpl
@@ -17,4 +17,4 @@
 		{{- end }}
 	{{- end }}
 	}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/codegen/example/templates/server_handler.go.tpl b/codegen/example/templates/server_handler.go.tpl
index 06ca75e1..d9214c21 100644
--- a/codegen/example/templates/server_handler.go.tpl
+++ b/codegen/example/templates/server_handler.go.tpl
@@ -51,4 +51,4 @@
 {{- end }}
 	default:
 		log.Fatal(ctx, fmt.Errorf("invalid host argument: %q (valid hosts: {{ join .Server.AvailableHosts "|" }})", *hostF))
-	}	
\ No newline at end of file
+	}
diff --git a/codegen/example/templates/server_interceptors.go.tpl b/codegen/example/templates/server_interceptors.go.tpl
index c2b09fca..cdb973dc 100644
--- a/codegen/example/templates/server_interceptors.go.tpl
+++ b/codegen/example/templates/server_interceptors.go.tpl
@@ -16,4 +16,4 @@
 	{{- end }}
 	}
 	{{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/codegen/example/templates/server_interrupts.go.tpl b/codegen/example/templates/server_interrupts.go.tpl
index 38afb745..ec3b3f78 100644
--- a/codegen/example/templates/server_interrupts.go.tpl
+++ b/codegen/example/templates/server_interrupts.go.tpl
@@ -13,4 +13,4 @@
 	}()
 
 	var wg sync.WaitGroup
-	ctx, cancel := context.WithCancel(ctx)
\ No newline at end of file
+	ctx, cancel := context.WithCancel(ctx)
diff --git a/codegen/example/templates/server_logger.go.tpl b/codegen/example/templates/server_logger.go.tpl
index 1afad381..0ee52dd8 100644
--- a/codegen/example/templates/server_logger.go.tpl
+++ b/codegen/example/templates/server_logger.go.tpl
@@ -10,4 +10,4 @@
 		ctx = log.Context(ctx, log.WithDebug())
 		log.Debugf(ctx, "debug logs enabled")
 	}
-	log.Print(ctx, log.KV{K: "http-port", V: *httpPortF})
\ No newline at end of file
+	log.Print(ctx, log.KV{K: "http-port", V: *httpPortF})
diff --git a/codegen/example/templates/server_services.go.tpl b/codegen/example/templates/server_services.go.tpl
index 3385b77a..2de51097 100644
--- a/codegen/example/templates/server_services.go.tpl
+++ b/codegen/example/templates/server_services.go.tpl
@@ -15,4 +15,4 @@
 		{{- end }}
 	{{- end }}
 	}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/codegen/example/templates/server_start.go.tpl b/codegen/example/templates/server_start.go.tpl
index 8a8def4f..0e722ae8 100644
--- a/codegen/example/templates/server_start.go.tpl
+++ b/codegen/example/templates/server_start.go.tpl
@@ -13,4 +13,4 @@ func main() {
 		secureF = flag.Bool("secure", false, "Use secure scheme (https or grpcs)")
 		dbgF  = flag.Bool("debug", false, "Log request and response bodies")
 	)
-	flag.Parse()
\ No newline at end of file
+	flag.Parse()
diff --git a/codegen/service/templates/return_type_init.go.tpl b/codegen/service/templates/return_type_init.go.tpl
index 9009ca65..28e7a51b 100644
--- a/codegen/service/templates/return_type_init.go.tpl
+++ b/codegen/service/templates/return_type_init.go.tpl
@@ -37,4 +37,4 @@
 		}
 	{{- end }}
 	return {{ .ReturnVar }}
-{{- end }}
\ No newline at end of file
+{{- end -}}
diff --git a/codegen/service/templates/service_endpoint_stream_struct.go.tpl b/codegen/service/templates/service_endpoint_stream_struct.go.tpl
index 3c9c1850..04a4ae33 100644
--- a/codegen/service/templates/service_endpoint_stream_struct.go.tpl
+++ b/codegen/service/templates/service_endpoint_stream_struct.go.tpl
@@ -8,4 +8,4 @@ type {{ .ServerStream.EndpointStruct }} struct {
 {{- end }}
 	{{ printf "Stream is the server stream used by the %q method to send data." .Name | comment }}
 	Stream {{ .ServerStream.Interface }}
-}
\ No newline at end of file
+}
diff --git a/codegen/service/templates/service_endpoints_init.go.tpl b/codegen/service/templates/service_endpoints_init.go.tpl
index 3f46fc4d..b1c9e6c4 100644
--- a/codegen/service/templates/service_endpoints_init.go.tpl
+++ b/codegen/service/templates/service_endpoints_init.go.tpl
@@ -22,4 +22,4 @@ func New{{ .VarName }}(s {{ .ServiceVarName }}{{ if .HasServerInterceptors }}, s
 	{{- end }}
 	return endpoints
 {{- end }}
-}
\ No newline at end of file
+}
diff --git a/codegen/service/templates/service_endpoints_use.go.tpl b/codegen/service/templates/service_endpoints_use.go.tpl
index 47af027b..0539583d 100644
--- a/codegen/service/templates/service_endpoints_use.go.tpl
+++ b/codegen/service/templates/service_endpoints_use.go.tpl
@@ -5,4 +5,4 @@ func (e *{{ .VarName }}) Use(m func(goa.Endpoint) goa.Endpoint) {
 {{- range .Methods }}
 	e.{{ .VarName }} = m(e.{{ .VarName }})
 {{- end }}
-}
\ No newline at end of file
+}
diff --git a/grpc/codegen/templates/client_init.go.tpl b/grpc/codegen/templates/client_init.go.tpl
index e1d24910..0f4ad98a 100644
--- a/grpc/codegen/templates/client_init.go.tpl
+++ b/grpc/codegen/templates/client_init.go.tpl
@@ -4,4 +4,4 @@ func New{{ .ClientStruct }}(cc *grpc.ClientConn, opts ...grpc.CallOption) *{{ .C
 		grpccli: {{ .ClientInterfaceInit }}(cc),
 		opts: opts,
 	}
-}
\ No newline at end of file
+}
diff --git a/grpc/codegen/templates/client_struct.go.tpl b/grpc/codegen/templates/client_struct.go.tpl
index 8d51a5e0..e167dd41 100644
--- a/grpc/codegen/templates/client_struct.go.tpl
+++ b/grpc/codegen/templates/client_struct.go.tpl
@@ -2,4 +2,4 @@
 type {{ .ClientStruct }} struct {
 	grpccli {{ .PkgName }}.{{ .ClientInterface }}
 	opts []grpc.CallOption
-}
\ No newline at end of file
+}
diff --git a/grpc/codegen/templates/do_grpc_cli.go.tpl b/grpc/codegen/templates/do_grpc_cli.go.tpl
index bdc52ca3..777a0b18 100644
--- a/grpc/codegen/templates/do_grpc_cli.go.tpl
+++ b/grpc/codegen/templates/do_grpc_cli.go.tpl
@@ -26,4 +26,4 @@ func grpcUsageCommands() string {
 func grpcUsageExamples() string {
 	return cli.UsageExamples()
 }
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/grpc/codegen/templates/parse_endpoint.go.tpl b/grpc/codegen/templates/parse_endpoint.go.tpl
index 538dad47..54d923a3 100644
--- a/grpc/codegen/templates/parse_endpoint.go.tpl
+++ b/grpc/codegen/templates/parse_endpoint.go.tpl
@@ -22,7 +22,7 @@ func ParseEndpoint(
 			c := {{ .PkgName }}.NewClient(cc, opts...)
 			switch epn {
 		{{- $pkgName := .PkgName }}
-		{{ range .Subcommands }}
+		{{- range .Subcommands }}
 			case "{{ .Name }}":
 				endpoint = c.{{ .MethodVarName }}()
 			{{- if .Interceptors }}
diff --git a/grpc/codegen/templates/partial/convert_string_to_type.go.tpl b/grpc/codegen/templates/partial/convert_string_to_type.go.tpl
index 0724711f..4585e467 100644
--- a/grpc/codegen/templates/partial/convert_string_to_type.go.tpl
+++ b/grpc/codegen/templates/partial/convert_string_to_type.go.tpl
@@ -156,4 +156,4 @@
 	{{- else }}
 		// unsupported type {{ .Type.Name }} for var {{ .VarName }}
 	{{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/grpc/codegen/templates/partial/convert_type_to_string.go.tpl b/grpc/codegen/templates/partial/convert_type_to_string.go.tpl
index 94e4d33d..78d7da6f 100644
--- a/grpc/codegen/templates/partial/convert_type_to_string.go.tpl
+++ b/grpc/codegen/templates/partial/convert_type_to_string.go.tpl
@@ -26,4 +26,4 @@
 	{{- else }}
 		// unsupported type {{ .Type.Name }} for field {{ .FieldName }}
 	{{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/grpc/codegen/templates/remote_method_builder.go.tpl b/grpc/codegen/templates/remote_method_builder.go.tpl
index 949f604b..7eb47901 100644
--- a/grpc/codegen/templates/remote_method_builder.go.tpl
+++ b/grpc/codegen/templates/remote_method_builder.go.tpl
@@ -9,4 +9,4 @@ func Build{{ .Method.VarName }}Func(grpccli {{ .PkgName }}.{{ .ClientInterface }
 		}
 		return grpccli.{{ .ClientMethodName }}(ctx{{ if not .Method.StreamingPayload }}, &{{ .Request.ClientConvert.TgtName }}{}{{ end }}, opts...)
 	}
-}
\ No newline at end of file
+}
diff --git a/grpc/codegen/templates/request_encoder.go.tpl b/grpc/codegen/templates/request_encoder.go.tpl
index ea895126..59a0bd03 100644
--- a/grpc/codegen/templates/request_encoder.go.tpl
+++ b/grpc/codegen/templates/request_encoder.go.tpl
@@ -43,4 +43,4 @@ func Encode{{ .Method.VarName }}Request(ctx context.Context, v any, md *metadata
 {{- else }}
 	return nil, nil
 {{- end }}
-}
\ No newline at end of file
+}
diff --git a/grpc/codegen/templates/response_decoder.go.tpl b/grpc/codegen/templates/response_decoder.go.tpl
index d34fcfb6..e116fcec 100644
--- a/grpc/codegen/templates/response_decoder.go.tpl
+++ b/grpc/codegen/templates/response_decoder.go.tpl
@@ -116,4 +116,4 @@ func Decode{{ .Method.VarName }}Response(ctx context.Context, v any, hdr, trlr m
 			}
 		{{- end }}
 	{{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/http/codegen/templates.go b/http/codegen/templates.go
index f8bd8e97..e1326528 100644
--- a/http/codegen/templates.go
+++ b/http/codegen/templates.go
@@ -21,7 +21,7 @@ func readTemplate(name string, partials ...string) string {
 				panic("failed to read partial template " + partial + ": " + err.Error()) // Should never happen, bug if it does
 			}
 			partialDefs = append(partialDefs,
-				fmt.Sprintf("{{ define \"partial_%s\" }}\n%s{{ end }}", partial, string(tmpl)))
+				fmt.Sprintf("{{- define \"partial_%s\" }}\n%s{{- end }}", partial, string(tmpl)))
 		}
 		prefix = strings.Join(partialDefs, "\n")
 	}
diff --git a/http/codegen/templates/append_fs.go.tpl b/http/codegen/templates/append_fs.go.tpl
index 0be80c6f..0ae3643c 100644
--- a/http/codegen/templates/append_fs.go.tpl
+++ b/http/codegen/templates/append_fs.go.tpl
@@ -21,4 +21,4 @@ func (s appendFS) Open(name string) (http.File, error) {
 // before delegating to the provided embed.FS.
 func appendPrefix(fsys http.FileSystem, prefix string) http.FileSystem {
 	return appendFS{prefix: prefix, fs: fsys}
-}
\ No newline at end of file
+}
diff --git a/http/codegen/templates/cli_end.go.tpl b/http/codegen/templates/cli_end.go.tpl
index 31c52c9e..1a006c4c 100644
--- a/http/codegen/templates/cli_end.go.tpl
+++ b/http/codegen/templates/cli_end.go.tpl
@@ -26,4 +26,4 @@ return cli.ParseEndpoint(
 	{{- end }}
 {{- end }}
 	)
-}
\ No newline at end of file
+}
diff --git a/http/codegen/templates/partial/client_map_conversion.go.tpl b/http/codegen/templates/partial/client_map_conversion.go.tpl
index 3701289c..d8578842 100644
--- a/http/codegen/templates/partial/client_map_conversion.go.tpl
+++ b/http/codegen/templates/partial/client_map_conversion.go.tpl
@@ -20,4 +20,4 @@ for k{{ if not (eq .Type.KeyType.Type.Name "string") }}Raw{{ end }}, value := ra
 			{{ template "partial_client_type_conversion" (typeConversionData .Type.ElemType.Type .FieldType.ElemType.Type "valueStr" "value") }}
 			values.Add(key, valueStr)
 		{{- end }}
-	}
\ No newline at end of file
+	}
diff --git a/http/codegen/templates/partial/client_type_conversion.go.tpl b/http/codegen/templates/partial/client_type_conversion.go.tpl
index 824ff527..d4382c02 100644
--- a/http/codegen/templates/partial/client_type_conversion.go.tpl
+++ b/http/codegen/templates/partial/client_type_conversion.go.tpl
@@ -24,4 +24,4 @@
     {{ .VarName }} := fmt.Sprintf("%v", {{ .Target }})
   {{- else }}
     // unsupported type {{ .Type.Name }} for field {{ .FieldName }}
-  {{- end }}
\ No newline at end of file
+  {{- end }}
diff --git a/http/codegen/templates/partial/element_slice_conversion.go.tpl b/http/codegen/templates/partial/element_slice_conversion.go.tpl
index 1ae66b04..c9658f58 100644
--- a/http/codegen/templates/partial/element_slice_conversion.go.tpl
+++ b/http/codegen/templates/partial/element_slice_conversion.go.tpl
@@ -1,4 +1,4 @@
 	{{ .VarName }} = make({{ goTypeRef .Type }}, len({{ .VarName }}Raw))
 	for i, rv := range {{ .VarName }}Raw {
 		{{- template "partial_slice_item_conversion" . }}
-	}
\ No newline at end of file
+	}
diff --git a/http/codegen/templates/partial/header_conversion.go.tpl b/http/codegen/templates/partial/header_conversion.go.tpl
index 7c8da3fa..e1c430d2 100644
--- a/http/codegen/templates/partial/header_conversion.go.tpl
+++ b/http/codegen/templates/partial/header_conversion.go.tpl
@@ -35,4 +35,4 @@
 		{{- end }}
 	{{- else }}
 		// unsupported type {{ .Type.Name }} for header field {{ .FieldName }}
-	{{- end }}
\ No newline at end of file
+	{{- end }}
diff --git a/http/codegen/templates/partial/path_conversion.go.tpl b/http/codegen/templates/partial/path_conversion.go.tpl
index 508c2f29..80fa0a64 100644
--- a/http/codegen/templates/partial/path_conversion.go.tpl
+++ b/http/codegen/templates/partial/path_conversion.go.tpl
@@ -6,4 +6,4 @@
 		}
 	{{- else }}
 		{{- template "partial_query_type_conversion" . }}
-	{{- end }}
\ No newline at end of file
+	{{- end }}
diff --git a/http/codegen/templates/partial/query_map_conversion.go.tpl b/http/codegen/templates/partial/query_map_conversion.go.tpl
index 6b3bfcc5..c99ba86a 100644
--- a/http/codegen/templates/partial/query_map_conversion.go.tpl
+++ b/http/codegen/templates/partial/query_map_conversion.go.tpl
@@ -40,4 +40,4 @@
 			{{- template "partial_query_type_conversion" (conversionData (printf "val%s" .Loop) "query" .Type.ElemType.Type) }}
 		}
 		{{ .VarName }}[key{{ .Loop }}] = val{{ .Loop }}
-	{{- end }}
\ No newline at end of file
+	{{- end }}
diff --git a/http/codegen/templates/partial/query_slice_conversion.go.tpl b/http/codegen/templates/partial/query_slice_conversion.go.tpl
index fdeeb0bd..2cad6fd0 100644
--- a/http/codegen/templates/partial/query_slice_conversion.go.tpl
+++ b/http/codegen/templates/partial/query_slice_conversion.go.tpl
@@ -8,4 +8,4 @@
 	{{- else if eq . "boolean" }} strconv.FormatBool(v)
 	{{- else if eq . "bytes" }} url.QueryEscape(string(v))
 	{{- else }} url.QueryEscape(fmt.Sprintf("%v", v))
-	{{- end }}
\ No newline at end of file
+	{{- end }}
diff --git a/http/codegen/templates/partial/query_type_conversion.go.tpl b/http/codegen/templates/partial/query_type_conversion.go.tpl
index 1bfd143e..9765e1e1 100644
--- a/http/codegen/templates/partial/query_type_conversion.go.tpl
+++ b/http/codegen/templates/partial/query_type_conversion.go.tpl
@@ -81,4 +81,4 @@
 		{{ if and (ne .TypeRef nil) (and (ne .TypeRef "bool") (ne .TypeRef "*bool")) }}{{ .VarName }} = ({{.TypeRef}})({{ if .Pointer }}&{{ end }}v){{ else }}{{ .VarName }} = {{ if .Pointer }}&{{ end }}v{{ end }}
 	{{- else }}
 		// unsupported type {{ .Type.Name }} for var {{ .VarName }}
-	{{- end }}
\ No newline at end of file
+	{{- end }}
diff --git a/http/codegen/templates/partial/request_elements.go.tpl b/http/codegen/templates/partial/request_elements.go.tpl
index 0e490ede..37615baa 100644
--- a/http/codegen/templates/partial/request_elements.go.tpl
+++ b/http/codegen/templates/partial/request_elements.go.tpl
@@ -345,4 +345,4 @@ qp := r.URL.Query()
 		{{ .Validate }}
 	{{- end }}
 {{- end }}
-{{- end -}}
+{{- end }}
diff --git a/http/codegen/templates/partial/response.go.tpl b/http/codegen/templates/partial/response.go.tpl
index 26f8033e..895c3551 100644
--- a/http/codegen/templates/partial/response.go.tpl
+++ b/http/codegen/templates/partial/response.go.tpl
@@ -116,4 +116,4 @@
 	{{- if .ErrorHeader }}
 	w.Header().Set("goa-error", res.GoaErrorName())
 	{{- end }}
-	w.WriteHeader({{ .StatusCode }})
\ No newline at end of file
+	w.WriteHeader({{ .StatusCode }})
diff --git a/http/codegen/templates/partial/single_response.go.tpl b/http/codegen/templates/partial/single_response.go.tpl
index acf24de1..76444620 100644
--- a/http/codegen/templates/partial/single_response.go.tpl
+++ b/http/codegen/templates/partial/single_response.go.tpl
@@ -184,4 +184,4 @@
 				return nil, goahttp.ErrValidationError("{{ $.ServiceName }}", "{{ $.Method.Name }}", err)
 			}
 	{{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/http/codegen/templates/partial/slice_item_conversion.go.tpl b/http/codegen/templates/partial/slice_item_conversion.go.tpl
index a15211df..ece04575 100644
--- a/http/codegen/templates/partial/slice_item_conversion.go.tpl
+++ b/http/codegen/templates/partial/slice_item_conversion.go.tpl
@@ -60,4 +60,4 @@
 			{{ .VarName }}[i] = rv
 		{{- else }}
 			// unsupported slice type {{ .Type.ElemType.Type.Name }} for var {{ .VarName }}
-		{{- end }}
\ No newline at end of file
+		{{- end }}
diff --git a/http/codegen/templates/partial/websocket_upgrade.go.tpl b/http/codegen/templates/partial/websocket_upgrade.go.tpl
index ded14162..65997fd0 100644
--- a/http/codegen/templates/partial/websocket_upgrade.go.tpl
+++ b/http/codegen/templates/partial/websocket_upgrade.go.tpl
@@ -30,4 +30,4 @@
 	})
 	if err != nil {
 		return {{ if eq .Function "Recv" }}rv, {{ end }}err
-	}
\ No newline at end of file
+	}
diff --git a/http/codegen/templates/path.go.tpl b/http/codegen/templates/path.go.tpl
index 8469dad9..30d0663e 100644
--- a/http/codegen/templates/path.go.tpl
+++ b/http/codegen/templates/path.go.tpl
@@ -2,4 +2,4 @@
 func {{ .PathInit.Name }}({{ range .PathInit.ServerArgs }}{{ .VarName }} {{ .TypeRef }}, {{ end }}) {{ .PathInit.ReturnTypeRef }} {
 {{- .PathInit.ServerCode }}
 }
-{{ end }}
\ No newline at end of file
+{{ end }}
diff --git a/http/codegen/templates/path_init.go.tpl b/http/codegen/templates/path_init.go.tpl
index c69a21dd..543dba86 100644
--- a/http/codegen/templates/path_init.go.tpl
+++ b/http/codegen/templates/path_init.go.tpl
@@ -15,4 +15,4 @@
 	{{- end }}, {{ end }})
 {{- else }}
 	return "{{ .PathFormat }}"
-{{- end }}
\ No newline at end of file
+{{- end -}}
diff --git a/http/codegen/templates/request_init.go.tpl b/http/codegen/templates/request_init.go.tpl
index 284f7aed..09e19138 100644
--- a/http/codegen/templates/request_init.go.tpl
+++ b/http/codegen/templates/request_init.go.tpl
@@ -63,4 +63,5 @@
 		req = req.WithContext(ctx)
 	}
 
-	return req, nil
\ No newline at end of file
+	return req, nil
+{{- /* strip extra newline */ -}}
diff --git a/http/codegen/templates/response_decoder.go.tpl b/http/codegen/templates/response_decoder.go.tpl
index 38aa7fc5..17ea5eea 100644
--- a/http/codegen/templates/response_decoder.go.tpl
+++ b/http/codegen/templates/response_decoder.go.tpl
@@ -109,4 +109,4 @@ func {{ .ResponseDecoder }}(decoder func(*http.Response) goahttp.Decoder, restor
 			return nil, goahttp.ErrInvalidResponse({{ printf "%q" .ServiceName }}, {{ printf "%q" .Method.Name }}, resp.StatusCode, string(body))
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/http/codegen/templates/server_start.go.tpl b/http/codegen/templates/server_start.go.tpl
index d1f8eb9b..c7203a78 100644
--- a/http/codegen/templates/server_start.go.tpl
+++ b/http/codegen/templates/server_start.go.tpl
@@ -1,2 +1,2 @@
 {{ comment "handleHTTPServer starts configures and starts a HTTP server on the given URL. It shuts down the server if any error is received in the error channel." }}
-func handleHTTPServer(ctx context.Context, u *url.URL{{ range $.Services }}{{ if .Service.Methods }}, {{ .Service.VarName }}Endpoints *{{ .Service.PkgName }}.Endpoints{{ end }}{{ end }}, wg *sync.WaitGroup, errc chan error, dbg bool) {
\ No newline at end of file
+func handleHTTPServer(ctx context.Context, u *url.URL{{ range $.Services }}{{ if .Service.Methods }}, {{ .Service.VarName }}Endpoints *{{ .Service.PkgName }}.Endpoints{{ end }}{{ end }}, wg *sync.WaitGroup, errc chan error, dbg bool) {


Test patch:
diff --git a/codegen/example/testdata/client-no-server.golden b/codegen/example/testdata/client-no-server.golden
index 84c0fe7f..5e2034ff 100644
--- a/codegen/example/testdata/client-no-server.golden
+++ b/codegen/example/testdata/client-no-server.golden
@@ -9,6 +9,7 @@ func main() {
 	)
 	flag.Usage = usage
 	flag.Parse()
+
 	var (
 		addr    string
 		timeout int
@@ -42,6 +43,7 @@ func main() {
 		scheme = u.Scheme
 		host = u.Host
 	}
+
 	var (
 		endpoint goa.Endpoint
 		payload  any
diff --git a/codegen/example/testdata/client-single-server-multiple-hosts-with-variables.golden b/codegen/example/testdata/client-single-server-multiple-hosts-with-variables.golden
index 9958fe9e..192f4c0d 100644
--- a/codegen/example/testdata/client-single-server-multiple-hosts-with-variables.golden
+++ b/codegen/example/testdata/client-single-server-multiple-hosts-with-variables.golden
@@ -12,6 +12,7 @@ func main() {
 	)
 	flag.Usage = usage
 	flag.Parse()
+
 	var (
 		addr    string
 		timeout int
@@ -63,6 +64,7 @@ func main() {
 		scheme = u.Scheme
 		host = u.Host
 	}
+
 	var (
 		endpoint goa.Endpoint
 		payload  any
diff --git a/codegen/example/testdata/client-single-server-multiple-hosts.golden b/codegen/example/testdata/client-single-server-multiple-hosts.golden
index d4afe1cc..93626da6 100644
--- a/codegen/example/testdata/client-single-server-multiple-hosts.golden
+++ b/codegen/example/testdata/client-single-server-multiple-hosts.golden
@@ -9,6 +9,7 @@ func main() {
 	)
 	flag.Usage = usage
 	flag.Parse()
+
 	var (
 		addr    string
 		timeout int
@@ -44,6 +45,7 @@ func main() {
 		scheme = u.Scheme
 		host = u.Host
 	}
+
 	var (
 		endpoint goa.Endpoint
 		payload  any
diff --git a/codegen/example/testdata/client-single-server-single-host-with-variables.golden b/codegen/example/testdata/client-single-server-single-host-with-variables.golden
index 8583ff6e..247561c8 100644
--- a/codegen/example/testdata/client-single-server-single-host-with-variables.golden
+++ b/codegen/example/testdata/client-single-server-single-host-with-variables.golden
@@ -18,6 +18,7 @@ func main() {
 	)
 	flag.Usage = usage
 	flag.Parse()
+
 	var (
 		addr    string
 		timeout int
@@ -60,6 +61,7 @@ func main() {
 		scheme = u.Scheme
 		host = u.Host
 	}
+
 	var (
 		endpoint goa.Endpoint
 		payload  any
diff --git a/codegen/example/testdata/client-single-server-single-host.golden b/codegen/example/testdata/client-single-server-single-host.golden
index f839fed6..6acfbeca 100644
--- a/codegen/example/testdata/client-single-server-single-host.golden
+++ b/codegen/example/testdata/client-single-server-single-host.golden
@@ -9,6 +9,7 @@ func main() {
 	)
 	flag.Usage = usage
 	flag.Parse()
+
 	var (
 		addr    string
 		timeout int
@@ -42,6 +43,7 @@ func main() {
 		scheme = u.Scheme
 		host = u.Host
 	}
+
 	var (
 		endpoint goa.Endpoint
 		payload  any
diff --git a/grpc/codegen/testdata/endpoint-endpoint-with-interceptors.golden b/grpc/codegen/testdata/endpoint-endpoint-with-interceptors.golden
index 4899bed5..52577e2c 100644
--- a/grpc/codegen/testdata/endpoint-endpoint-with-interceptors.golden
+++ b/grpc/codegen/testdata/endpoint-endpoint-with-interceptors.golden
@@ -117,7 +117,6 @@ func ParseEndpoint(
 		case "service-with-interceptors":
 			c := servicewithinterceptorsc.NewClient(cc, opts...)
 			switch epn {
-
 			case "method-a":
 				endpoint = c.MethodA()
 				endpoint = servicewithinterceptors.WrapMethodAClientEndpoint(endpoint, inter)