Skip to content

Non-intuitive handling of pointers to primitive types #34331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
michaelsafyan opened this issue Sep 16, 2019 · 1 comment
Closed

Non-intuitive handling of pointers to primitive types #34331

michaelsafyan opened this issue Sep 16, 2019 · 1 comment

Comments

@michaelsafyan
Copy link

What version of Go are you using (go version)?

Whatever version of Go is built into Blaze at build ID:

8b915454-f908-47e0-9d29-326c7e863ed5

Does this issue reproduce with the latest release?

Not sure (not certain what version of Go is being used).

What operating system and processor architecture are you using?

gLinux

What did you do?

type IncidentID uint64

func ParseIncidentID(id string) (*IncidentID, error) {
	segments := strings.Split(id, ".")
	if len(segments) != 2 {
		return nil, fmt.Errorf("invalid incident ID: %q; wrong number of dotted segments", id)
	}
	if segments[0] != "0" {
		return nil, fmt.Errorf("invalid incident ID: %q; expected prefix '0.'", id)
	}

	value, err := strconv.ParseUint(segments[1], 36, 64)
	if err != nil {
		return nil, fmt.Errorf("invalid incident ID: %q; could not parse %q as 64-bit, base36 unsigned integer", id, segments[1])
	}

	return &IncidentID{value}, nil
}

This returns an error related to the expression &IncidentID{value}. The weird thing here is that this kind of syntax works perfectly fine with non-primitive types; elsewhere, there is a struct that aliases time.Time (providing slightly different behavior for the default String() operation), where a similar method has the syntax return &Time{t}, nil and works fine.

This behavior is really frustrating, since essentially Go is revealing the seems between primitives and non-primitive types. There should be consistent syntax here.

Other attempts to make this work include:

    result := &IncidentID{}
    *result = value
    return result, nil

And:

    var result IncidentID
    result = value
    return &result, nil

None of these syntaxes work.

What did you expect to see?

I expected syntax to be more consistent between types.

I also expected errors to be meaningful/helpful; the error message related to composite literal types is totally gibberish to me and doesn't guide me in the direction of correct syntax.

What did you see instead?

An error as well as very obviously inconsistent syntax.

@ianlancetaylor
Copy link
Member

Thanks for the bug report. Sorry it is confusing.

The &T{} syntax is supported whenever T is a struct, array, slice, or map type: see https://golang.org/ref/spec#Composite_literals. It is not supported for other kinds of types. The distinction is not primitive or non-primitive; it is aggregate or non-aggregate. The T{} syntax permits setting the components of an aggregate type. The &T{} is a syntactic extension that both sets the components and returns the address of the resulting value.

Supporting a simple expression to take the address of a non-aggregate value is #9097. Closing this issue as a dup of that one.

@golang golang locked and limited conversation to collaborators Sep 15, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants