If it's not and sacrificing type safety, then why is it there? If it's there, why using it is considered bad.? Isn't it just like an "any" type in many languages (except there is a nil
in Go).
I've heard arguments about this being a bad practices only from the community at large, but never from the Go official documentations or the core team itself. Why?
评论:
peterbourgon:
gac_web:You can't make a single, general statement like
interface{} is acceptable
orinterface{} is bad
. It's a tool that can be used. It's often overused by folks new to the language. To say more requires context.
hipone:interface {}, 99% of the time implies reflection, which means no compiler optimization so a radical hit in performance, and obviously the compile time type safety is thrown out of the window. Don't get me started on Go reflection which is so leaky it hurts ( it leaks Go internals ).
Now it depends on your background :
if you come from C/Ruby/Python/JS/PHP and co : you might not even know what a generic or a type class is, so you might not even care about type correctness at compile time.
if you come from C#,C++,Java or any ML language(Ocaml, F#) , it definitely feels extremely nasty,especially when using a library based on interface {} when you are used to types documenting the code. At the same time you'll figure out soon enough you can't write compile time type safe abstractions in Go, especially when it involves containers.
Go maintainers definitely belong to the first camp,as they throw in more API with interface {}.
I've heard arguments about this being a bad practices only from the community at large
At the end of the day it only matters if you publish open-source libraries and can't take a criticism from random people on the internet. You should care only about what works for you and your team not what pundit X or Z has to say. Go maintainers don't have a problem using interface {} or reflection for convenience. Just know the cost of interface {}.
TheMerovius:Use of interface{} does not involve reflection in regular code, mostly type assertions.
ar1819:Go maintainers definitely belong to the first camp,as they throw in more API with interface {}.
Now, they come from C++. If you read the Google C++ style guide, you'll find that undeniable, it's essentially "go without garbage collection".
hipone:Go maintainers tend to pick interface{} when there is no other options available (like Pool) or when they make sense (like Marshal family of functions). The former comes not powerful enough typesystem. The latter id just a label for
any
.
nstratos:Use of interface{} does not involve reflection in regular code, mostly type assertions.
The_Sly_Marbo:
binaryblade:I'd say it's only acceptable where you want to handle anything. The only time I can think of where that is clearly true is with
Printf
-like functions and general purpose encoders likejson.Marshal
, where you want to be able to represent anything.
quiI:It has a terrible code smell, but in the absence of generics, nessecary at times.
As with most things in programming, there arent usually simple rules, just stuff that is generally good practice but there's always exceptions.
It's important to understand the tradeoffs of using interface
- Losing type safety
- Less performant
- Your API becomes harder to use (i cant just look at the type signature)
That said, because Go's type system isn't very rich it is sometimes needed to get around that.
You'll find most of the time people criticising interface when it is patching up a lazy/bad design. You should generally prefer an implementation not using interface if it's reasonably possible.
TheMerovius:IMHO: It's perfectly fine where it's useful, that is, mostly containers and encoding/decoding. I agree with static type-checks being very useful, but do not believe that you are going to get into any actual trouble in practice, if you are missing it in container-APIs. In practice, every container you use will have a clearly distinguished responsibility which determines the type stored in it and while doing
someHeap.Pop().(*myType)
might look somewhat ugly and inconvenient and could in theory panic, I don't believe it's in any sense a buzz-kill. And for en-/decoding, you already don't want to rely on any type info; so taking aninterface{}
very accurately expresses the type you are handling.Just… don't use it as a "general value". Don't use it as
java.lang.Object
. Use it, where the loss of type-information either makes sense or is tolerably limited.
