Silly question about parentheses

178 views
Skip to first unread message

Raphael Clancy

unread,
Jan 31, 2023, 11:56:02 AM1/31/23
to golang-nuts
Hey all, I figured it was time to move to a "modern" language and I thought I'd give go a try. So far, I'm really enjoying it. I'm just getting started and I had a question about parentheses. Though, I guess it's really about how go parses lines of code and what counts as a delimiter.

Anyway, in the get started section on error handling, why are parentheses required around string and error here:

func Hello(name string) (string, error) {...

but not around message and nil here:

return message, nil

I tried searching a bit but I couldn't come up with anything about such a basic topic.

Thanks!

Axel Wagner

unread,
Jan 31, 2023, 2:38:46 PM1/31/23
to Raphael Clancy, golang-nuts
I'm not sure there really is a "reason", per se. The language could just as well have been designed not to require parentheses around the return types (at least I see no parsing ambiguity with that, though there might be) or designed to require parentheses in the return statement. It probably just felt more intuitive and readable to the designers at the time.

FWIW I find it more interesting that `func() T` requires no parentheses, but `func() (S, T)` does.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/b49dc8c2-26ea-46bc-b76a-708a2537207cn%40googlegroups.com.

p...@morth.org

unread,
Feb 1, 2023, 9:29:53 AM2/1/23
to golang-nuts
It would actually be ambiguous in the very place they're required.

Consider this not completely unreasonable example: https://go.dev/play/p/OL0uOnPZXju

Also, with generics it could be ambiguous in type parameters.
To summarize, parentheses are needed around the return types because otherwise anywhere a list of types is used, it would be ambiguous.

Regards,
Per Johansson

Axel Wagner

unread,
Feb 1, 2023, 10:13:10 AM2/1/23
to p...@morth.org, golang-nuts
Good point, didn't think of that

Raphael Clancy

unread,
Feb 1, 2023, 11:04:48 AM2/1/23
to golang-nuts
This is really helpful! Thank you!

At first I assumed that it was down to 'go fmt' letting you be fairly loose with your syntax and that you could omit parentheses where the meaning wouldn't be ambiguous.  But on closer examination, there must be something else going on because 'return a, b' works fine and 'return (a, b)' generates an error. But, both 'func(a string) string {}' and  'func(a string) (string){}' work fine.

Maybe it's because 'return' isn't really a function call and has it's own syntax?

Chris Burkert

unread,
Feb 1, 2023, 11:22:51 AM2/1/23
to Raphael Clancy, golang-nuts
Looking into the spec:

https://go.dev/ref/spec#Return_statements
ReturnStmt = "return" [ ExpressionList ] .
ExpressionList = Expression { "," Expression } .
... no () here

FunctionType   = "func" Signature .
Signature      = Parameters [ Result ] .
Result         = Parameters | Type .
Parameters     = "(" [ ParameterList [ "," ] ] ")" .
ParameterList  = ParameterDecl { "," ParameterDecl } .
ParameterDecl  = [ IdentifierList ] [ "..." ] Type .
... a Type does not need () but Parameters needs them.

But now I am puzzled. I can actually omit the variable name for the arguments: https://play.golang.com/p/g4Sz8rh06QW.

This seems to be useless, but it is actually allowed, right?

David Finkel

unread,
Feb 1, 2023, 12:10:34 PM2/1/23
to Chris Burkert, Raphael Clancy, golang-nuts
On Wed, Feb 1, 2023 at 11:22 AM Chris Burkert <burker...@gmail.com> wrote:
Looking into the spec:

https://go.dev/ref/spec#Return_statements
ReturnStmt = "return" [ ExpressionList ] .
ExpressionList = Expression { "," Expression } .
... no () here

FunctionType   = "func" Signature .
Signature      = Parameters [ Result ] .
Result         = Parameters | Type .
Parameters     = "(" [ ParameterList [ "," ] ] ")" .
ParameterList  = ParameterDecl { "," ParameterDecl } .
ParameterDecl  = [ IdentifierList ] [ "..." ] Type .
... a Type does not need () but Parameters needs them.

But now I am puzzled. I can actually omit the variable name for the arguments: https://play.golang.com/p/g4Sz8rh06QW.

This seems to be useless, but it is actually allowed, right?
 
It's not useless because sometimes you need to take a specific parameter-list to satisfy an interface, but that specific implementation doesn't need that input.
Similarly, when defining a method in an interface, sometimes the type says it all, so there's no value in defining a name for the argument.

Note: I'm not saying that one should never name variables in interface definitions, so much that in some cases, it's clearer with just types.
          There are definitely many interface definitions that are underspecified without argument-names)

Reply all
Reply to author
Forward
0 new messages