> The benefit is that I don't have to write these boring, but necessary pieces.
The "boring, but necessary pieces" are usually just a call to a constructor. In my opinion it's almost never worth using a DI system that obfuscates dependency resolution and usually can't be checked at compile time just to avoid that.
Agreed. It seems silly to call "invoking constructors" "boring" but doing all of the same work in XML is somehow more interesting? It seems like you're just adding in a layer of indirection that does nothing besides exchange Go/Java/etc for XML/Groovy/etc at the expense that one must be familiar with the DI framework to understand how the DI files are loaded, linked together, and mapped to your application code.
The main benefit of constructing objects and tying them together via DI is to allow polymorphic handling of responsibilities.
It is more complex than simply "I just make an interface and make everyone agree on that interfere". Everyone agreeing on the interface to use is very unlikely.
The underlying data in different implementations will be different. This is something Golang fails terribly at because it doesn't have polymorphism.
This is, I believe, why there are so few DI systems for Golang, and most of them are of the sort you are referring to as silly.
The way Golang works, and the reccomended patterns for Golang are somewhat anti-DI.
> The main benefit of constructing objects and tying them together via DI is to allow polymorphic handling of responsibilities.
This is already provided by interfaces, as previously discussed. To be clear, dependency injection makes sense; however, dependency injection frameworks don’t make sense to me.
> The underlying data in different implementations will be different. This is something Golang fails terribly at because it doesn't have polymorphism.
Go definitely has always had polymorphism; that’s the whole point of interfaces.
> The way Golang works, and the reccomended patterns for Golang are somewhat anti-DI.
DI (assemble your object graph in main() instead of distributing it across dozens of constructors a la OOP) is idiomatic Go; DI frameworks are not.
Interfaces don't allow polymorphism, because they don't allow you to change the underlying data. The main problem is that you can't ( or at least aren't supposed to ) use any pointers and especially not pointers that point to different data types in different situations.
This sort of behavior is core to polymorphism. It can be done in three ways in Golang ( and probably more too... ):
1. Use serialized messages in channels to do all messages to objects ( disgusting imo... ) It would though at least let one emulate the behavior of message passing / routing languages ( pursuant to original visions of smalltalk etc )
2. Use "unsafe pointers" and just do everything the pay you would in C, deliberately going against the way Golang authors want you to do things.
3. Use reflection and messy if/else in combination with code-generation at compile time. ( this is what a bunch of Golang DI systems do :( )
I don't think you understand polymorphism very well.
I don't give a shit what people are calling DI frameworks these days. I also don't much care for things that simply instantiate a bunch of objects and tie them together. That is only a very elementary variety of metaprogramming.
Essentially, what I am claiming is the Golang is a bad language for metaprogramming, and that in other languages the DI systems they have have become a type of metaprogramming that I think is respectable.
Interfaces absolutely express a type of polymorphism: any concrete type that satisfies the interface can be used in its place. What makes you think otherwise?
> Essentially, what I am claiming is the Golang is a bad language for metaprogramming
That's definitely true, and an explicit choice. Thank goodness!
There is no "either-or" data type in Golang. That's why.
It can only be accomplished by inefficient functional hackery.
In C, you just make a struct, have a type present in the struct, and then cast the struct pointer to extended object types to gain additional functionality.
In this way you can easily accomplish all sorts of fun things like inheritance. Message passing type designs can easily be accomplished also in C.
In Golang? Well... no. You are essentially forbidden from doing any simple casting or extension. You are essentially stuck with hardcoding the crap out of everything or making your own vcall like system build out of Golang types... which you can't really use in the way you want unless you use reflection.
What I can't understand is why anything thinks that Golang does support polymorphism. They admit it themselves. They are working on it. Only the new alpha test versions have a solution for it. The current released version is not polymorphism no matter how much you want to fucking label it that way.
You can't just go "hey it supports a little bit of what everyone knows as polymorphism". That's like saying alcohol is like orange juice because they are both bitter in some cases.
Go lacks parametric ("generics") polymorphism but has interface ("duck typing") and effectively, via the syntactic sugar for embedding, also has subtype ("virtual methods") polymorphism.
It's 30 years too late to complain about three unrelated approaches to dynamic dispatch having the same name.
I think you’re probably trying to make a substantial point but you seem to be mistaken about several things with respect to Go and polymorphism and interfaces such that I can’t figure out what your actual, substantial point is.
> Go is a bad language for metaprogramming
You’re absolutely right here.
> There is no "either-or" data type in Golang. That's why.
Correct here too, Go doesn’t have sum types. If you want sum types, you have to emulate them via interfaces. But I don’t see how that relates since all of this DI stuff seems to be dynamically typed anyway (errors at runtime) assuming you’re not taking a codegen approach anyway.
> In C, you just make a struct, have a type present in the struct, and then cast the struct pointer to extended object types to gain additional functionality.
I don’t understand what you’re trying to do here. First of all, this only works for the first field (and obviously isn’t memory/type safe).
> In Golang? Well... no. You are essentially forbidden from doing any simple casting or extension. You are essentially stuck with hardcoding the crap out of everything or making your own vcall like system build out of Golang types... which you can't really use in the way you want unless you use reflection.
As a general rule of thumb you can do almost anything in Go that you can do in C if only by delving into the unsafe package; however, “unsafe” is almost never necessary—interfaces typically suffice. You certainly can emulate inheritance if you don’t care about type-safety, just like in C. Unfortunately I can’t say more until you clarify your objective.
> What I can't understand is why anything thinks that Golang does support polymorphism. They admit it themselves. They are working on it. Only the new alpha test versions have a solution for it. The current released version is not polymorphism no matter how much you want to fucking label it that way.
I think you must mean some other word because interfaces are the canonical example of polymorphism and Go has the best interfaces in the business. :) I’ve never heard the Go maintainers claim they lack polymorphism (Go does lack type-safe generics and sum types, but so does C). In an earlier post you argued that interfaces weren’t polymorphism because they don’t let you modify the underlying data, which is patently false—this is the whole point of interfaces. In Go:
var r io.Reader // nil
r = someFile // *os.File
r = stringReader // *strings.Reader
The "boring, but necessary pieces" are usually just a call to a constructor. In my opinion it's almost never worth using a DI system that obfuscates dependency resolution and usually can't be checked at compile time just to avoid that.