No. Some people's experience with Go. People that might not have much experience with generics to start with.
And if they think the rest are "doing it wrong", they are mistaken.
Well, I as someone who has professionally worked with C++ for over 5 years and used C++ templates quite a bit, I never ever needed generics in Go even once.
Why do you think is that so? Maybe because I do not force my C++ style of thinking onto what language features Go offers and instead write idiomatic Go code?
(n.b. I did more than just playing around with Go a bit, I wrote serious applications in Go some of which are in production use)
I agree that in most other cases, it turns out you can write a simpler API than Thing<OtherThing<Key, ? extends Value>>, and nobody wants to open the door to that mess. But for containers, they either need to dramatically multiply the number of built-in container classes (slice[] map[] are generic in a way), or create a way to write your own.
Using a functional programming approach, data processing is easy because you can create new data by taking old data and specifying a transformation process. With Go, I had to manually handle the iteration through the old data's container object.
Not a huge deal, but it felt like I was reinventing the wheel in every goroutine.
When you are writing an application, you can know all the types you are going to need, so that you can work around the limitations of Go's typing system. When writing a library, you definitely don't have all the information.
I found that in some languages (Haskell, OCaml, Scala), a common way to write applications is to write the different parts you are going to need as generic libraries and then combine them together. I don't think this is the common way Go programmers do thing.
Go's packages make the practice described above explicit, and many go programs are made up of generic libraries (packages) which define protocols (interfaces) for the types which are passed in, and need know nothing else of those types in advance. So what you describe above as what Go should be like is the normal approach to programming in Go, and many parts of apps (packages) are actually reusable in other apps without modification precisely because of this.
Are you saying that every one of the many serious engineers who miss generics when writing Go are just not thinking outside the generics box? Or are you willing to admit that, while Go without generics may be a great language for many applications, there clearly are applications where generics are the right language construct for the job?
Not to mention the fact that this makes it harder to reuse data structures and algorithms, which can have a much bigger impact on performance.
If I want to create a new wrapper class, the last thing I want to do is either make it hold an Object, or have to write a new version of it for every type it can hold.
Can't you solve this problem with an interface defining the behaviours your wrapper expects? The interface can then be passed in or held as a ptr without requiring a specific type, allowing a generic implementation. You can create a generic iterate or sort function for example which operates on slices of a given interface. Sorry if I've misunderstood, if so a code example might help clarify what you mean.
In C# I can define this once, and then any service can just return a Reply<string>, Reply<int>, Reply<Address>, etc. The calling method can check the associated reply status, and then unwrap the data if the call was successful, displaying any associated messages as needed.
Or, for a different example: If I want to store a long list of Customers in a dictionary, keyed on String, then in C# I'd create a Dictionary<string,Customer>, and know that it would always contain the types I'd expect.
How would I do either of those in Go?
1. Generic reply (for a good example of this in use see the way errors are used in go; errors are extensible and can contain info like that in your example).
http://blog.golang.org/2011/07/error-handling-and-go.html
For your example, you could have a reply interface, defining the requirements, then concrete types which conform: http://play.golang.org/p/e18n36Ub5u
There are probably shorter ways to do this, this is just an off the cuff example, but it's quite possible to have generic reply types which respond to any methods you want, and can be created easily and extended if necessary. You can also cast back to the original type.
2. Just use map[string]Customer - Customer could be an interface (duck typing) or a type.
Something like this: http://play.golang.org/p/ZoftbY8mQX
IMHO using an interface here is more interesting, as it lets you define your requirements, and forget all about the type system, while letting the compiler check that any uses will always work as they conform to the interface.
Here's what I think you want, written in (as far as I am able to) idiomatic Go:
That strikes me as terribly unmaintainable.
Yes, if you want it to actually be a Reply, it has to implement Reply.
That's acres of template code being duplicated all over the place
No, if you need to reuse code you can use other techniques like embedding (not shown in examples).
The features and restrictions differ from many other OO languages but I think the creators of Go deserve a little more credit than you are giving them - they do not produce unmaintainable code (see std lib for Go), worked on a large scale with C++ OOP previously, designed the forking Unix operating system, and are not unaware of the ramifications of the decisions taken.
Maybe I don't know what exactly you want.
The Foo and Bar in my example have quite different CheckStatus() methods because those two structs are quite different. If there were more similar, then you could share more code.
In the second example no, in the first example, if you want two types to conform to an interface, you need two types - Go interfaces require an implementation.
In real code this is not really a limitation - types require minimal boilerplate in Go, and the complete definition can be one line (e.g. type StringReply string). You can create them very easily, and wrap standard types in them (see the error type example NegativeSqrtError). I'm not too familiar with C# generics I'm afraid so am guessing as to what you want to do. Go already has support for generic maps and lists which can take any type or interface (as in your dictionary example), so that's not really a problem. Maybe someone else who knows both better will jump in.
If you wanted to treat two types (string and Customer) in Go as the same sort of thing (a Reply), you can do this with an interface. Then you can work with anything which conforms to that interface. Let's say you have this reply interface:
type Reply interface {
Reply() string
}
That requires a Reply method returning a string. You want to pass around both a string and a Customer (using say its name) as a reply? Define what each does when it replies - this is required so that the compiler knows you are passing the right sort of type, and so that you can actually use them as replies (NB you can't add to built-ins, so you have to add a new StringReply type): type Customer struct {Name string}
func (c *Customer) Reply() string {
return fmt.Sprintf("%s",c.Name)
}
type StringReply string
func (s StringReply) Reply() string {
return string(s)
}
http://play.golang.org/p/uLgSpbTx24so you could have a list []Reply or a map[string]Reply, or some custom collection type which can only have Replies added to it and nothing else.
If you want to reuse code between types, you can have helper methods or embedded types (NB only reusing code, not data, this is not inheritance).
Code above is trivial of course, and if you see code repeated in other examples it'll be because of these are little toy examples - you can use composition of types or helpers which act on interfaces to avoid repeating yourself. In real code you tend not to have quite such simple interfaces or types. If you feel we're not getting at what you want, posting a C# example of something you think would be impossible in Go would be helpful, otherwise you can assume that what most of what you can do in C# etc can easily be handled in Go as well even if the concepts don't map 1-1.
Reply<T>{
T ReplyData;
bool TheCallWorked;
string AssociatedMessage;
// other stuff here
}
and that's it - I can now have a reply that bundles up any type I like. My GetAddress function can return a Reply<Address>, my GetCustomerAge function can return a Reply<int>, etc.Whereas you're having me recreate that boilerplate for every different reply type - which means that if the information needed for a Reply changes, or I have to make a fix to the associated code, I need to change every instance of it.
You could reproduce your example above using a base reply type with ReplyData as an empty interface{} ptr (you'd have to wrap built-ins like int) and accessible fields. You could attach functions to that and only change them once and extend by embedding it in other special types of Reply if you wished. Typically though you'd have a base reply with bool and string say, and then extend that with other types of reply which make sense in certain situations rather than a generic payload which could be anything - so make ReplyData or a Reply type conform to an interface to ensure it does what your receiving methods want.
You can do the same things without them - but you have to write separate code for each type you deal with.
.NET has generics? I mean, actual generics, not simple first-order parametric polymorphism with type constructors of the kind (* -> *)? Can you write, say, a generic reader or a generic printer that will work with all types? How would you go about doing that?
Looking at the Parametric Polymorphism article on Wikipedia, that indicates that implementing it produces generic functions and generic datatypes, which is what I'm talking about here.
Sadly, beyond about the third sentence of that article I'm lost :->