Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for empty interfaces in Go?

Tags:

interface

go

I am learning about empty interfaces. I find that while there are many explanations—also on Stackoverflow—on meaning of an empty interface and how they work, there's very little information on best-practices on when / why to use them, when to avoid, what the considerations are, and the pros and cons of chosing to use them.

In Go chatrooms I've read some talk about best to avoid using empty interfaces where possible, but without the proper arguments. Others proudly responding they had zero empty interfaces in their code design.

I am most interested in use for libraries and frameworks (intended to be reused / extended by others).

Right now I am reading a framework codebase with related libraries, that is full of emtpy interfaces in many locations. Some of this confuses me, and I wonder if all usages are warranted. Like the framework offers 'user management' and things like AppConfiguration and UserPreferences are empty interfaces. This while further on in the code (near the db layer) the user's email is technically treated as a user preference. Wouldn't it be better to be more specific in the interface definition?

like image 832
Arnold Schrijver Avatar asked Sep 01 '25 02:09

Arnold Schrijver


2 Answers

In Go chatrooms I've read some talk about best to avoid using empty interfaces where possible, but without the proper arguments. Others proudly responding they had zero empty interfaces in their code design.

The biggest problem is that you lose all typing; for example let's say I have a function that I want to operate on various types of numbers, so I write:

func AddOne(n interface{}) int64 {
    switch nn := n.(type) {
        case int:
            return nn + 1
        case int8:
            return nn + 1
        // ... etc...
    }
}

But what if I pass 0.42 (float64) to this function, or the string "asd"? If the function would accept an int64 (func AddOne(n int64) int64) then we would get a warning about this at compile time, but with interface{} you won't get anything since everything is valid.

The best you can do is handle this at run-time and either panic() or return an error; which is obviously a lot less clear than a compile-time error.

This is by far the biggest downside.


I'd have to see the details of those AppConfiguration and UserPreferences functions in particular, but there are some good reasons for using empty interfaces; for example when you want to accept some custom struct and then use reflection to set values on the struct based on some external data. This is essentially what packages such as encoding/json do, but it's also commonly used for parsing some config files, and so forth.

It sounds like AppConfiguration and UserPreferences may fit this, because the library/framework doesn't know what settings you need for your app's configuration, or what user preferences there are. But like I said, it's hard to be sure without details.

Another use case is when you really want to accept a wide variety of types; passing parameters to SQL queries is a common example, or fmt.Printf().


In general, avoiding interface{} is probably best, but if you find yourself bending over backwards for doing so then it's probably best to just use interface{} and live with the lack of typing.

like image 197
Martin Tournoij Avatar answered Sep 03 '25 08:09

Martin Tournoij


Empty named interface does not make sense in Go because unlike other languages like C# for example any type (class in C#) can be cast to a specific interface if it matches interface signature. So in Go "classes" (struct types) does not need to be inherited from an interfaces (e.g. to declare interface at time of type definition).

So the answer to your question:

Best practice for empty interfaces in Go is not to defined named empty interfaces in Go.

Update: Thanks to the comments below I've changed my mind and I agree there is can be limited use cases for usage of empty named interfaces for the sake of documentation and quicker navigation in IDEs.

like image 31
Alexander Trakhimenok Avatar answered Sep 03 '25 09:09

Alexander Trakhimenok