Accepting variable types of arguments

For example, Go Stdlib’s Printf variadic func accepts any type of input params by using an empty interface type. You can use the empty interface to accept an unknown type and number of arguments in your own code as well.

func Printf(format string, a ...interface{}) (n int, err error) { /* this is a pass-through with a... */ return Fprintf(os.Stdout, format, a...)

} fmt.Printf("%d %s %f", 1, "string", 3.14) // output: "1 string 3.14"

Why does not Printf only accept just one variadic param?

When you look at the signature of Printf, it takes a string named as format and a variadic param.

func Printf(format string, a ...interface{})

This is because the format is a required param. Printf forces you to provide it or it will fail to compile.

If it was accepting all of its params through one variadic param, then the caller may not have supplied the necessary formatter param or it wouldn’t be as explicit as this one from the readability perspective. It clearly marks what Printf needs.

Also, when it’s not called with its variadic param: “a”, it will prevent Printf to create an unnecessary slice inside the func — passes a nil slice as we saw earlier. This may not be a clear win for Printf but it can be for you in your own code.

You can use the same pattern in your own code as well.

Beware the empty interface type

interface{} type is also called the empty interface type which means that it bypasses the Go’s static type checking semantics but itself. Using it unnecessarily will cause you more harm than good.

For example, it may force you to use reflection which is a run-time feature (instead of fast and safe — compile-time). You may need to find the type errors by yourself instead of depending on the compiler to find them for you.