Skip to content

proposal: Go 2: allow taking the address of a function result value or constant #22647

Closed
@benhoyt

Description

@benhoyt

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:

  1. 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.
  2. 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}.
  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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions