-1

I am new to Go and I'm trying to find a convenient way from a developers perspective to get an address of an object after changing type.

Consider these two new types:

type specialString string
type nestedStruct struct {
    name *specialString
}

The canonical way I have found for filling in the nestedStruct is this:

str := "James"
specStr := specialString(str)
nested := nestedStruct{
    name: &specStr,
}

Is there a way to omit the declaration of specStr, which is then only used in one place? I tried this, but it triggers an syntax error (what is the logical reason for that?):

//Syntax error
nested := nestedStruct{
    name: &specialString(str),
}

Any help would be appreciated.

P.Brown
  • 11
  • 1
  • 6

2 Answers2

2

You cannot take the address of an arbitrary operation, including a type conversion. For details, see How can I store reference to the result of an operation in Go?; and Find address of constant in go.

You can omit one of the local variables if you convert the string literal:

specStr := specialString("James")
nested := nestedStruct{
    name: &specStr,
}

If you already have a variable of string type and you want to omit the second variable (of specialString type), then take the address of the existing string variable, and convert it to *specialString:

str := "James"
nested = nestedStruct{
    name: (*specialString)(&str),
}

Try these examples on the Go Playground.

If you want to omit the local variable, see this answer for options: How do I do a literal *int64 in Go?

icza
  • 389,944
  • 63
  • 907
  • 827
1

Use a function to eliminate the boilerplate at the point of initialization:

func specialStringPtr(s string) *specialString { 
     return (*specialString)(&s) 
}


nested := nestedStruct{
    name: specialStringPtr(str),
}
Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242
  • Wouldn't this copy the value of the `str` and thereby create an unnecessary performance overhead? Is there a way to write such function in a more general way so that it accepts multiple types and returns corresponding pointers? – P.Brown Apr 15 '19 at 14:31
  • 1
    This approach copies the string header (pointer, length), but not the backing array of bytes. The performance cost of copying the header is negligible. Any approach to solving this problem must copy string header to a variable. – Charlie Tumahai Apr 15 '19 at 14:35
  • Not to mention this simple function is most likely inlined by the compiler. – icza Apr 15 '19 at 14:37
  • See the [AWS value and pointer conversion utilities](https://godoc.org/github.com/aws/aws-sdk-go/aws#hdr-Value_and_Pointer_Conversion_Utilities) for one approach to handling multiple types. AWS provides a helper function for each type. – Charlie Tumahai Apr 15 '19 at 14:39
  • "Wouldn't this ... create an unnecessary performance overhead?" Maybe, maybe not, but there's no point in assuming it would. Write code that does what it's supposed to and makes sense to someone reading it. If you measure a performance problem, and profile to locate the source of the problem, then you can worry about optimization. – Adrian Apr 15 '19 at 14:43