BulkInsert(db *sql.DB, objs []interface{})
This unfortunately meant that any time you had []Foo.. you had to allocate a new []interface{} and copy over the items. Now a function like that can look like: BulkInsert[T any](db *sql.DB, objs []T)
And we're not wasting CPU cycles to copy the slice of []Foo. I'm struggling to see how that's code smell or less excellent than using []interface{} or duplicating the code for BulkInsert for every insertable type in our application.Generics are definitely better for you. But I would say the overall pattern you're employing of bulk inserting different kinds of data structures with one function is the problem. Of course, I don't know your code so I'm sure you have a good reason for choosing what you did, but a BulkInsert of Any certainly made me raise my eyebrow.
Nevertheless I feel like I'm getting lost in the weeds of this example. Obviously DRY and less duplication is good. However, you have to strike a balance between being clever and being clear. And frankly I would prefer 3 lines of clear code to 1 line of hard-to-read code.
Any reference for this ?
I though there was a pretty strong connection between the total number of line of code and the number of bug... That's the whole point of DRY.
Why prematurely optimize for differences that may not (and in practice aren't really likely to) happen?
Keep in mind that the tradeoff with generics is usually not 3 lines of clear or 1 line of hard to read, it's one line of clear code (T -> T), one line of unclear code (Interface{} -> Interface{} + casts), or n lines of complex code (concretely reimplementing the function for your particular case).
If you are inserting an object, you should insert it, rather than create complicated generic insert methods that morph themselves based on the object being inserted. That is idiomatic Go.
Now Golang is saved, with Generics it's actually an Awesome Incredible PL.
Funny though that I did get triggered by it. Out of the Go community I've heard way too often "you don't really need xyz", when they mean "we're not going to support xyz, here's why, and if you disagree, we respectfully ask you to look elsewhere".
Who needs data structures right?
I guess you have never written a library. It's extremely useful there, stuff like "generic function that runs a channel thru X workers doing f() on it" is now easily possible with full type safety.
> Nevertheless I think people implementing them in their own projects is basically code smell and they are a symptom of poorly thought-out code rather than excellent code.
You can say that about literally any feature used by the incompetent.
But overall yes, they are far more useful for writing libraries than actual applications
What power?
I can't think of any other less confrontational way to say/ask , but beside GO which other language have you used ?
Because the above statement is so far remove from my experiences and understand of programming that i suspect we don't we really use the same day to day tools/languages in general.
As a Go programmer I always thought the generics complaint was kind of silly in practice — complicated code should be simplified and made more concrete, not more generic.
I’m glad generics were implemented, if only to silence the chorus of people who didn’t even use Go but whined about the lack of them. Their inclusion has simplified the stdlib and led to some cool new functions. Nevertheless I think people implementing them in their own projects is basically code smell and they are a symptom of poorly thought-out code rather than excellent code.
Anyway. This was a good initial post and a good follow-up. Go is my favorite language out there right now for its clarity, power, and ease-of-use. And with loop variable capture coming (the biggest remaining foot gun in the language in my experience) the language is only getting better.