News for hackers. Stuff that matters.
Re:Four years of Go by alok-g on Sunday November 10, 2013 @08:48PM (#6709480)
Those experienced in Go, do you miss generics?
Re:Four years of Go by burntsushi on Sunday November 10, 2013 @10:08PM (#6709711)
I enjoy writing Go and have done a lot of it over the past couple years, and there are occasions where I miss other kinds of polymorphism. Specifically, parametric and ad-hoc.

However, it doesn't impact whether I enjoy writing Go code or not. It tends to be mitigated by blessed built in types and functions with parametric polymorphism (e.g., `map`, `[]`, `append`, `delete`, etc.) in addition to Go's structural sub-typing and type embedding. First class functions help too.

Actually, this results in a really nice aspect of Go that I've come to appreciate: reading and writing Go code tends to have very little cognitive overhead. Things tend to be very straight-forward and clear. I'm not sure if this is because there aren't generics, but I have my suspicions that it is. The language itself and its semantics is very simple and can fit in your head easily. But this is my experience, YMMV.

Dirty little secret: sometimes I cheat a little when writing small commands in Go and sacrifice compile time type safety by using my `ty` package.[1]

[1] - http://blog.burntsushi.net/type-parametric-functions-golang

Re:Four years of Go by eonil on Monday November 11, 2013 @01:33AM (#6710274)
At first, I thought Generic is not that much desired. But after having some time with Go, I think Go really need generics.

The problem is Go lacks immutable data structure. I believe everybody know why immutable data structure is required. Go slice and map are all mutable-only, so to make some read-only data view, we need to write all the containers by hand. Amount of code increases exponentially.

It would be great if Go had such a immutable slice/map stuffs, but they decided not to have that due to legacy compatibility issue with existing []byte/string(which is actually just an immutable view on []byte) types.

So now the only hope is generics. I don't want to write hundreds of same list/map classes just to offer immutable views. That's all duplicated works, and I just want ability to write List<T> and Map<T>.

If you don't think immutable data structure or view is not important, Go is good enough to you. But that feature is crucial to me, and that's one of the biggest reason of why I stopped using Go.

Re:Four years of Go by shazow on Monday November 11, 2013 @05:22AM (#6710895)
One scenario I ran into is building a generic function call caching solution. Coming from Python, there tons of great libraries for memoizing and caching [0][1][2]. Even the Python 3 standard library has a simple one built in [3]. But building something similar in Golang proved to be near impossible.

I got a half-working solution [4] with a lot of interface{} and some reflection, but upon speaking with some of the Golang devs, the consensus was "this is not something you do in Go." From what I understand, you're expected to build a custom memoizing function for each set of datatypes you're expecting to use it for (which admittedly is not a ton of code), and generic helpers are not advised.

I can't say authoritatively whether "Go needs generics!" or not, but life has been much easier after porting my code back to Python—though a large part of it was because it was a fairly dynamic webapp which is still a pain point for Go. I hope to give Go another try soon, probably for a different project.

[0] https://pypi.python.org/pypi/dogpile.cache

[1] https://pypi.python.org/pypi?%3Aaction=search&term=cache&sub...

[2] https://pypi.python.org/pypi?%3Aaction=search&term=memoize&s...

[3] http://docs.python.org/dev/library/functools.html#functools....

[4] https://github.com/shazow/memoizer

Re:Four years of Go by dualogy on Sunday November 10, 2013 @09:52PM (#6709659)
Since Go has generics for slices (aka arrays), maps (aka dictionaries / hash-tables) and channels, I was pleasantly surprised how little I miss them in practice. Just some adaptation-of-thinking-habits mostly. Don't miss them anymore. I have a micro-codegen pre-build step (written in Go of course) for the very few use-cases where something akin to those (more generally, templated programming) does come in handy. But those are really far and few between.
Re:Four years of Go by yuushi on Sunday November 10, 2013 @10:42PM (#6709819)
I think interface{} is a horrible, horrible hack. For me, the answer is an emphatic yes.
Re:Four years of Go by Roboprog on Tuesday November 12, 2013 @09:30AM (#6717969)
"Object" is much better :-) (or perhaps you prefer "void *")
Re:Four years of Go by alok-g on Sunday November 10, 2013 @11:05PM (#6709892)
Could you please explain more? :-)
Re:Four years of Go by yuushi on Monday November 11, 2013 @08:49PM (#6715342)
Sure. Think of void * in C. interface{} in Go isn't really that different, there's just a bit more language support for testing if it satisfies a specific type or not. Add in type assertions, and it's basically as though you had a dynamic_cast in C++ that worked from void * to an interface type.

To me, it just seems ugly. I like a type system where I know what a type is at each point, and there isn't some ugly "catch all" type that you can use when you run out of other options, which effectively just throws away all type information (and this is what interface{} does, as everything implements it).

Re:Four years of Go by venuzr on Sunday November 10, 2013 @10:02PM (#6709690)
That was my initial struggle as well coming into Go (I have worked for several years in C# & Java). You learn to work around this limitation using interfaces for both function parameters and return types. Frankly, I have had to do a little more explicit typecasting that I would have liked (going from interfaces to the actual type) but it is ok.
Re:Four years of Go by grey-area on Monday November 11, 2013 @05:18AM (#6710884)
Isn't the idea behind interfaces that you add whatever methods you need to use to the interface? If that's the case you don't need or want to cast, you can just assume that the object given to you conforms to that interface...
Re:Four years of Go by alok-g on Sunday November 10, 2013 @11:09PM (#6709905)
Are you saying that making sure the type is correct (just before the cast) becomes the programmer's responsibility? How often does this happen?
Re:Four years of Go by venuzr on Monday November 11, 2013 @08:12AM (#6711391)
Nope. This mostly becomes a problem if you like to be DRY and try to replace generics (type T) kind of functionality with interfaces. For e.g., I have a method, which does the classic, lookup from cache first before hitting the actual db. In C#, you can use

  public T Get<T>(int id, string cacheKey) {

  }
When I consume it and say Get for User object, I expect an User object as I already know it's type.

In Go, you have to return an interface (and ideally an error)

Here would be the equivalent,

  v, err := s.Get(id int, cacheKey string)
  if err != nil {
           //Handle error here
  }
  if v == nil || v.(*models.User) == nil {
		return nil, http.StatusNotFound
  }
Its a bit more code, but on the flip side, it gets you thinking as a client of all the things that can go wrong with your code
Re:Four years of Go by quarterto on Monday November 11, 2013 @07:25AM (#6711243)
This is called a type assertion in Go. Whenever you ask for something as an interface but want to use the type's own method, you have to make a type assertion.

  interface Fooer {
    func Foo()
  }

  type Bar struct {}

  func (s Bar) Foo() {}
  func (s Bar) Baz() {}

  func DoFoo(f Fooer) {
    f.Foo() // fine
    // f.Baz() compile error
    f.(Bar).Baz() // fine
  }
Re:Four years of Go by grey-area on Monday November 11, 2013 @02:01PM (#6713234)
Isn't the entire point of an interface to communicate the behaviour expected by the function though?

If you want a Bar specifically (as the DoFoo code does above), it should take a Bar as an argument.

If you want to accept any struct that satisfies Fooer, add all the methods to Fooer that you need them to satisfy...

Doing otherwise is just subverting the type system and you might as well use a blank interface and effectively have no type checking on your input - if you require a Fooer and then typecast someone might pass a Fooer and get a nasty surprise when it doesn't work.

Re:Four years of Go by pjmlp on Monday November 11, 2013 @02:44AM (#6710478)
> Those experienced in Go, do you miss generics?

Yes, that is one of the reasons I eventually moved to D.