DEV Community

Jacob Hummer
Jacob Hummer

Posted on β€’ Edited on β€’ Originally published at jcbhmr.me

Fix "cannot take address of {value}" in Go

This is a summary of my Googling for future me or anyone else.

fmt.Println(&"Hello")
fmt.Println(&true)
fmt.Println(&15)
fmt.Println(&fmt.Sprint(123))
Enter fullscreen mode Exit fullscreen mode
./prog.go:8:15: invalid operation: cannot take address of "Hello" (untyped string constant)
./prog.go:9:15: invalid operation: cannot take address of true (untyped bool constant)
./prog.go:10:15: invalid operation: cannot take address of 15 (untyped int constant)
./prog.go:11:15: invalid operation: cannot take address of fmt.Sprint(123) (value of type string)
Enter fullscreen mode Exit fullscreen mode

You currently can't get the address of literals or function return values in Go. You can, however, get the address of function parameters which means you can create a helper ptr() function to turn any value into a pointer. πŸ˜‰

func ptr[T any](value T) *T {
  return &value
}
Enter fullscreen mode Exit fullscreen mode
func ptr[T any](value T) *T {
  return &value
}
func main() {
  fmt.Println(ptr("Hello"))
  fmt.Println(ptr(true))
  fmt.Println(ptr(15))
  fmt.Println(ptr(fmt.Sprint(123)))
}
Enter fullscreen mode Exit fullscreen mode

Of course, you could always stuff these values into a variable and &theVariable. πŸ™„ But who wants to clutter their code with extra one-time intermediary variables?

a := "Hello"
fmt.Println(&a)
b := true
fmt.Println(&b)
c := 15
fmt.Println(&c)
d := fmt.Sprint(123)
fmt.Println(&d)
Enter fullscreen mode Exit fullscreen mode

Further reading πŸ“š

Judging from the past 1.5 years, I appear to be writing this function about once every second month, when I need it in a new package. The need especially arise with pointers to strings in unit test files, I've noticed.

Admittedly, I work a lot with code generated from API specifications. That code tend to use *string a lot, since it can't be certain that nil and empty string are equivalent (and rightly so, they aren't).

It's not very annoying, but does feel a bit like I'm littering my packages with this function, so not having to write it would be welcome. I do realise I can put it in a package I import, but that also seems overkill for a one-liner.

β€” @perj in golang/go#45624 (comment)

Hey reader!

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Okay let's go

Community matters

Top comments (1)

Collapse
 
ccoveille profile image
Christophe Colombier β€’

Yes, Go was struggling with situation like this.

I faced it so many times in unit tests πŸ˜…

I would like to suggest you this lib that tries to address many issues of the Go language with generics.

GitHub logo samber / lo

πŸ’₯ A Lodash-style Go library based on Go 1.18+ Generics (map, filter, contains, find...)

lo - Iterate over slices, maps, channels...

tag Go Version GoDoc Build Status Go report Coverage Contributors License

✨ samber/lo is a Lodash-style Go library based on Go 1.18+ Generics.

This project started as an experiment with the new generics implementation. It may look like Lodash in some aspects. I used to code with the fantastic "go-funk" package, but "go-funk" uses reflection and therefore is not typesafe.

As expected, benchmarks demonstrate that generics are much faster than implementations based on the "reflect" package. Benchmarks also show similar performance gains compared to pure for loops. See below.

In the future, 5 to 10 helpers will overlap with those coming into the Go standard library (under package names slices and maps). I feel this library is legitimate and offers many more valuable abstractions.

See also:

  • samber/do: A dependency injection toolkit based on Go 1.18+ Generics
  • samber/mo: Monads based on Go 1.18+ Generics (Option, Result, Either...)

Why this name?

I…

Here is your pointer helper for example
pkg.go.dev/github.com/samber/lo#Fr...

Please note Go core developers are aware of these, and try adding things. slice packages is a great recent addition.

pkg.go.dev/slices

πŸ‘‹ Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay