Description
As I noted in http://benhoyt.com/writings/learning-go/#general-quirks, one of the (few) language quirks I noticed when learning Go is that I couldn't take the address of a function result. For example, here's what I wrote at first and thought should work:
mystruct.TimePtr = &time.Now()
But of course it didn't because, according to the spec, the thing you're taking the address of needs to be "addressable" or, as a special case, a composite literal like &Point{2, 3}
.
It seems like this would be a backwards-compatible change to the Go language spec to allow this, and have the compiler figure out that it needs to create a temporary variable (on the heap or stack) to take the address of. The compiler could expand it to the equivalent of:
tmp := time.Now()
mystruct.TimePtr = &tmp
And it seems I'm not the only one who has run into this in slightly different ways -- see one, two, three, and four.
In particular, the Amazon AWS SDK has a whole bunch of helper functions like aws.String (docs here), just so you can use constants as "optional parameters" for pointer fields in input structs, eg:
input := &s3.PutObjectInput{
ACL: aws.String("public-read"),
Body: bytes.NewReader(data),
Bucket: aws.String("mybucket"),
ContentType: aws.String("image/jpeg"),
Key: &key,
}
_, err := s3ImageClient.PutObject(input)
Before they added this (see here), you'd have to do this in a very unwieldy way:
acl := "public-read"
bucket := "mybucket"
contentType := "image/jpeg"
input := &s3.PutObjectInput{
ACL: &acl,
Body: bytes.NewReader(data),
Bucket: &bucket,
ContentType: &contentType,
Key: &key,
}
With this proposal in place, not only could the AWS SDK get rid of all those aws.String
-style helpers, but there'd be an obvious, clean way to write this:
input := &s3.PutObjectInput{
ACL: &"public-read",
Body: bytes.NewReader(data),
Bucket: &"mybucket",
ContentType: &"image/jpeg",
Key: &key,
}
Obviously there are a couple of things to think about:
- Would it be added just for the things people seem to need, that is, function calls and constants? Or for arbitrary expressions like
&(x + 1234)
. I think it'd be nice and orthogonal if it allows arbitrary expressions, but if there's a good reason to be conservative, I think just allowing&functionCall()
and&constant
would be a great start. - Is the syntax fully backwards compatible? I'm not a syntax expert, but I think so, as this is simply an extension of the special case you can already do with
&Point{2, 3}
. - You couldn't take the address of multi-valued functions (this would be a compile-time error). But as multi-valued functions are already special in some ways, that seems fine.