Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Go generics: where would I use any instead of interface{}?

As generics have been released in Go 1.18 pretty recently, I’ve started learning them. I generally get the concept, because I have some Java experience from the past. But I don’t get some implementation specifics.

For instance: when it’s more suitable to use any instead of interface{}? Here’s an example:

func printInterface(foo interface{}) {
    fmt.Printf("%v\n", foo)
}

func printAny[T any](foo T) {
    fmt.Printf("%v\n", foo)
}

func (suite *TestSuite) TestString() {
    printInterface("foo")
    printAny("foo")
}

Both implementations work. However, if I try to print nil with any-version, I’ll get a compile-time error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

cannot infer T.

https://go.dev/play/p/0gmU4rhhaOP

And I won’t get this error if I try to print nil with interface{}-version.

So what’s the use-case for any? When and which benefits does it bring, compared to simply using interface{}?

I’m asking to provide a specific example, where one implementation is objectively more suitable than another and/or where there is a specific benefit that can be evaluated.

>Solution :

any is an alias for interface{}. Spec: Interface types:

For convenience, the predeclared type any is an alias for the empty interface.

Since it is an alias, it doesn’t matter which one you use. They are one and the same. They are interchangeable. You can replace one with the other, the code will mean the same.

any is shorter and clearer, but only works from Go 1.18.

Since they are interchangeable, this also works:

func printInterface(foo any) {
    fmt.Printf("%v\n", foo)
}

The reason why printAny() doesn’t work is due to it being a generic function with a type parameter. To use it, it must be instantiated (its type parameter must be assigned with a known type). Trying to call it with nil carries no type information, so instantiation cannot happen, type inference won’t work.

If you call it with a nil value that carries type info, it’ll work, or if you specify the type param explicitly (try it on the Go Playground):

printAny((*int)(nil))
printAny[*int](nil)
// Or
var r io.Reader
printAny(r)

And as said, any is interchangeable with interface{}, so you’ll have the same code if you swap both occurrences (try this one on the Go Playground):

func printInterface(foo any) {
    fmt.Printf("%v\n", foo)
}

func printAny[T interface{}](foo T) {
    fmt.Printf("%v\n", foo)
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading