cannot register generic function with template.Funcs

234 views
Skip to first unread message

Rory Campbell-Lange

unread,
Mar 6, 2023, 4:44:02 PM3/6/23
to golan...@googlegroups.com
Hi. I have a generic function

func slicerG[A any](s []A, i int) []A {
fmt.Println(len(s), i)
if i > len(s) {
return s
}
return s[0:i]
}

When I try to register this in a template's FuncMap, it fails with

"cannot use generic function slicerG without instantiation"

https://go.dev/play/p/KpvrbbcTaM2

I guess this makes sense if the compiler is converting the function to function variants of particular types based on instantiation, but is there any way around this?

Thanks,
Rory

Bruno Albuquerque

unread,
Mar 6, 2023, 4:50:13 PM3/6/23
to Rory Campbell-Lange, golan...@googlegroups.com
You can easily get it to work, but not in a useful way I guess.

https://go.dev/play/p/mq0O8OhJ1-a

You could have a different template for each type you use I guess.

-Bruno


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/ZAZelXNTAEaXy0cs%40campbell-lange.net.

Rory Campbell-Lange

unread,
Mar 6, 2023, 4:59:42 PM3/6/23
to Bruno Albuquerque, golan...@googlegroups.com
On 06/03/23, Bruno Albuquerque (b...@gmail.com) wrote:
> You can easily get it to work, but not in a useful way I guess.
>
> https://go.dev/play/p/mq0O8OhJ1-a
>
> You could have a different template for each type you use I guess.

Thanks for that solution. I guess I could do

t.Funcs(template.FuncMap{
"slicerInt" : slicerG[int],
"slicerStr" : slicerG[string],
...
})

which is at least better than rewriting the function for each type.

Thanks again,
Rory

Axel Wagner

unread,
Mar 6, 2023, 5:13:18 PM3/6/23
to Rory Campbell-Lange, golan...@googlegroups.com
No, Go generics do not exist at runtime, so there is no way for this to possibly work in generality.
The best you can do is make a function that takes an `any` or a `reflect.Value` and use `reflect` to type-check at runtime, returning an error if type-checking fails: https://go.dev/play/p/c0jgBMxGdGq
Given that templates are necessarily type-checked at runtime and have to be rendered by the template using reflect anyways, the only downside is that the code is somewhat less readable.


Reply all
Reply to author
Forward
0 new messages