In your examples there, am I not having to create a new type per case? So a Reply<String> and a Reply<Customer> will require me to create two classes?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.