11 ms·
I have decided to get proficient in Go about 3 years ago and I am glad I did. One of the discoveries in the process was that Go enables you to do things that pr
by gtrubetskoy 10y ago
I have decided to get proficient in Go about 3 years ago and I am glad I did. One of the discoveries in the process was that Go enables you to do things that previously were extremely difficult and you'd typically not even consider as options.
Many of the "old" ways of thinking do not apply to Go, and I had to get over the phase of looking for an ORM or webapp or testing frameworks - they don't exist because they are not necessary, and those that do aren't any good really.
I ended up inventing my own challenge - a time-series database backed by PostgreSQL (http://github.com/tgres/tgres http://github.com/tgres/tgres), because I needed a difficult problem. Tgres is still not fully baked, but what it does couldn't possibly be done in e.g. Python, and not in C in as little time (even though it's been two years in development).
Contrary to what the blogs say, Go is _not_ an easy language to learn. Interfaces, goroutines, channels, selects, etc. will take a long while to become second nature, and if you're not using them then you're not really getting anything out of Go.
With respect to all the criticism Go is getting out there, e.g. lack of generics - I honestly can't say there is anything that bugs me at all. Some things may take getting used to, but usually in the end you're glad to have done so.
As someone who has done a lot of programming in my life (in Python, C (remember mod_python?) and also Ruby, and (with displeasure) Java) I can say that Go is a big deal in the language landscape and will not long from now be as big as Python - in fact I think it is Python developers who are most likely to switch over to Go for their next project.
- tptacek 10y agoStrong, strong disagree on the idea that ORMs aren't necessary because of some property of Golang itself. Lack of decent ORMs is probably my biggest complaint about Go, and I think if you look at a lot of large web app packages you'll find people are all writing their own 40-60% of an ORM.
- sethammons 10y agoOne of my biggest complaints about ORMs is that I often know the exact query I need to write, and it is a pain to compose it with the ORM. Simple CRUD, sure, maybe. Beyond that though... Arguably one of the biggest benefits of an ORM is sanitization. You get that for free with Go. I've done quite a bit of work with DBs and Go, and I've not seen the need for an ORM, just some library helpers.
- aikah 10y ago> You get that for free with Go You get that for free in any language that allows you to pass parameters to a query. There is nothing Go specific. > One of my biggest complaints about ORMs is that I often know the exact query I need to write, and it is a pain to compose it with the ORM. I agree that ORMs are often their own DSL one has to learn, when SQL is already there. In that sense they are opaque. Yet ORM still deal with relationships that have to be manually wired with queries, since AFAIK SQL query are still 2 dimensional. In my opinion query builders are often a nice trade-off between a fully featured ORM and raw SQL : you get SQL abstraction thus query reuse at minimal cost without the complexity. An other alternative is Jooq style code generation/scaffolding but each time a tool like that is added to a compilation pipeline it is yet another dependency to manage. Code generation is opaque in its own ways. Finally there is the nuclear option in shape of HQL but it sounds like a half baked farce to go back to "SQL" to avoid SQL. I myself chose to go with query builders, in fact i'm porting Doctrine DBAL to Go as we speak.
- thewhitetulip 10y agoI have written a small webapp in Go while learning it and I didn't use an ORM, but the feedback I got from reddit is that at some point in time I'd need to use an ORM. What are your thoughts on the usage of ORM? +ve points vs -ve points?
- oelmekki 10y agoWhen I started using go (coming from rails), ORM was really the thing I missed the most. And this made me realize I actually didn't know much about postgres. I started using pg functions, views, triggers, etc and found it extremely convenient. Now, my sql strings in go are mostly `SELECT * FROM func_name(<$params>)` and I'm happy with that. I'm not saying ORMs are useless (active_record is an incredibly cool tool), but it's been surprisingly way easier to live without them that I'd thought.
- tptacek 10y agoEven writing Postgres functions, you're still writing the same basic SQL statements (for the 80% of your database interactions that are essentially CRUD) over and over again. People used to defend writing things in assembly language for similar reasons, as a way of getting more machine sympathy. I'm not buying it.
- oelmekki 10y ago> People used to defend writing things in assembly language for similar reasons, as a way of getting more machine sympathy. I'm not buying it. I have to assume those people did not first learn and use C, then went to assembly, but rather the opposite ;) So, the comparaison does not apply, here. > you're still writing the same basic SQL statements (for the 80% of your database interactions that are essentially CRUD) It's not the case, actually. My functions are way more expressive that the crud I did with orms. With PL/pgSQL, I group several queries in a same pg function, I always do more that a simple insert or update. I also fine tune my returned fields - which most of the time are composite from several tables / computations. This is really outsourcing all data manipulation to the database, the comparison that applies is more with a presenter/serializer than with an orm model.
- neospice 10y agoWhat are the typical trade-offs of outsourcing all the data manipulation & lookups to the DB. Are there cases when this is absolutely what you don't want to do? I realize this is a very general and vague question but it's something I've been pondering about.
- vram22 10y ago>Strong, strong disagree on the idea that ORMs aren't necessary because of some property of Golang itself. Might be interesting to hear reasons - by both you and the parent commenter.
- randomdata 10y agoIn my experience there is one property of Go that minimizes the need for a good ORM, and that is that the problem domain Go excels in does not have great overlap with the problem domain that ORMs excel in. What interfacing with a relational database does come up is of the nature that does not fit well into the ORM model anyway. Of course, you can write software in the same domain where ORMs excel in Go, but I am not sure it is the best tool for that job. A good ORM would go a long way to making that less true, but I'm not sure even that would put Go at the same level as tools that are geared towards that type of problem. Go, like all tools, is still targeted at a certain class of problems.
- weberc2 10y agoWhat domain are you referring to?
- ben_jones 10y agoNot GP but my view is that Go excels in "split-backends" where you kind of have a front-end server and a back-end server where the front-end is taking in requests and passing them to a queue or interacting with services representing the "backend's backend". In this regard you're usually building for scale and high optimizing your code to be incredibly concise and to the point. An ORM doesn't belong here because you've already decided software quality > developer productivity within such an important capacity-driven system.
- didip 10y agoWrapper functions are not the same as full blown ORM. For every heavily used ORM features, there's an opportunity to fall into a trap, e.g N+1, because the surface area of an ORM is wide. In contrast, wrapper functions are low cost, easy to write, and recognizable because you write them yourself.
- deleted 10y ago[deleted]
- pcwalton 10y ago> In contrast, wrapper functions are low cost, easy to write, and recognizable because you write them yourself. Isn't saying that you should use functions that are "recognizable because you write them yourself" basically saying "you shouldn't use libraries?" This seems like the obvious NIH fallacy.
- fauigerzigerk 10y agoNot necessarily. It could also mean that these functions are more specific, have names that make sense in the concrete context and don't have any unnecessary parameters you need to think about. When it comes to ORMs it's even worse. They are often not libraries but frameworks with tons of non-local settings and state you need to know about (or else...). Not invented here also means not invented for the specific task at hand but for a much more general set of use cases. In my view it's a trade-off, not a fallacy.
- sethammons 10y agoI find the majority of what you contribute to HN very insightful; I appreciate your activity here! I've yet to use an ORM that I've found added much or any value, and usually I have to fight it. I find "select id from user where email='foo@example.com'" much easier to work with than some odd query build that requires some DSL that made sense to some developer for their particular use case, like user.Get(id).Where().Email("foo@example.com). My most recent case of growing disdain for ORMs being SQLAlchemy. What ORMs do you find (in any language) that you like and what is it about them that helps you?
- aikah 10y ago> Many of the "old" ways of thinking do not apply to Go Whatever. Just because the language is effectively broken doesn't make practices in other languages irrelevant. And it's funny when you talk about the "old" ways of thinking in language that basically promotes C styles errors and bad macros through go gen. When I say the language is broken, look at Go type system, then look at how Go reflection makes the language look a dynamically typed one. It would have been smarter to tone down the reflection and make it unnecessary with a smarter type system. If it is there then it is because it was necessary for Go designers. If it had not been, then Go would not need that insane reflection. Now Go back to your Go code and remember all tricks you need to learn when working with arrays : https://github.com/golang/go/wiki/SliceTricks https://github.com/golang/go/wiki/SliceTricks Just because : > A weakness of Go is that any generic-type operations must be provided by the run-time https://blog.golang.org/slices https://blog.golang.org/slices Now what was your point about the "old" ways of thinking again ?
- defgeneric 10y agoWhile I'd like to have generics in go, one of the upsides of the lack of generics is that your code becomes less idiosyncratic and more idiomatic. Too often in C++ for example, I find myself frustrated reading code where templates are unintentionally over-used because the programmer needlessly introduced an abstraction where the concrete would have sufficed. There is a certain pleasure in moving from the concrete to the abstract and finding the inner connection between things, but this can also get in the way or distract from the immediate problem. The same issue comes up in Common Lisp where you find a codebase with heavy use of macros which effectively build a DSL within the program. Working alone, this can be fun, and can produce elegant code, but it means anyone new to a project needs to first familiarize themselves with the world you've built. When many people work on a project it helps if everyone speaks the Queen's English, as it were. Still, generics would be nice.
- lomnakkus 10y ago> While I'd like to have generics in go, one of the upsides of the lack of generics is that your code becomes less idiosyncratic and more idiomatic. That sounds like a deepity[1] if ever I've heard one. Just to add something a little more substantive: It may not be obvious at first sight (esp. in e.g. C++ or Java), but 'generics'/'parametric polymorphism' can actually incredibly powerful at restricting what your program can do and thus actually restrict the set of valid programs which will still satisfy the type checker. This is used to great effect in e.g. ML or Haskell and can be used somewhat effectively in Java/Scala code with subtype bounds. Of course in Haskell, being a language from the 1990s[2], you can use this to effectively restrict the types of effects used by any given function (database I/O, arbitrary I/O, networking, etc.). [1] https://en.wiktionary.org/wiki/deepity#English https://en.wiktionary.org/wiki/deepity#English [2] Ok, this is slightly exaggerated since monads-for-IO were discovered quite a bit after 1990, but still... parametric polymorphism is crucial for this use case.
- richard_todd 10y agoI miss generics, not because I would write new generic functions all the time, but because a few key generics provide infrastructure that increases the beauty of programs dramatically. The tupled (T, error) return types are a key area I think generics would help. The error-tuples themselves aren't the problem, but rather Go's inability to cleanly handle them. Threading error state around requires repetitive glue code (if err != nil). In some languages, you hide the glue code in monads. In some languages, you hide the glue code in macros. In some languages, generics reduce the glue to chained methods on helper objects. In Go, once in a while you can hand-write a lambda function to manage a closed-over error variable and clean things up a bit, but that's about all you get.
- weberc2 10y agoI don't mind the repetitive glue code. It might be nice to clean it up a bit, but it's the least of my concerns with Go. When I miss generics, it's usually for some tree-like structure, but the cases where I need a high-performance tree structure and can't take the performance hit of `interface{}` are few and far between.
- AsyncAwait 10y ago> it's usually for some tree-like structure, but the cases where I need a high-performance tree structure and can't take the performance hit of `interface{}` are few and far between. The problem with interface{} is that it makes it pretty much worthless to have a type system at all.
- junke 10y ago> I have decided to get proficient in Go about 3 years ago and I am glad I did. One of the discoveries in the process was that Go enables you to do things that previously were extremely difficult and you'd typically not even consider as options. Such as?
- biztos 10y agoI use a testing framework[0] all the time in Go, and while I appreciate it's possible to write tests without one I think it's just pig-headed to not have something like that in the standard library. If you just use testing.T you will most likely end up with a lousy, developer-hostile test suite. (Also, the default coverage metrics are very very weak. But I love Go just the same.) [0]: https://github.com/stretchr/testify https://github.com/stretchr/testify
- artifaxx 10y agoTestify makes a moderate improvement to writing tests, but I still love it. Multiply the improvements across a hundred tests and the difference is huge.
- jeffizhungry 10y agoI wouldn't even call testify a framework. You can just as easily mix tests that don't use testify with tests that do use testify. It's more of a toolkit with helper functions to help you write test, which you can pick and choose as needed. But I agree, I've done the plain vanilla Go testing in the past, and testify has drastically cleaned up my tests.
- sethammons 10y agoI disagree that you will end up with a `lousy, developer-hostile test suite`. All testify does, to my experience, is change three line if-statement to a one line assert/require that ignores type safety. Aside from that, it is up to the developer to still write good cases, adopt table driven tests when they make sense, and provide enough feedback in test output to debug a broken test.
- wyager 10y ago> what it does couldn't possibly be done in e.g. Python What can you do in Go that you can't do in other languages? I can't think of anything. The only major benefits over, say, C++ or Java (which I don't think are very impressive languages) are a few convenient threading primitives, but you also lose a lot of expressive power.
- weberc2 10y agoEfficient concurrent programming. I'm not aware of any cross-platform C/C++ or Python libraries that give you async I/O + multi-threaded coroutines. Such a library exists for the Java ecosystem (quasar), but IIRC, it's enabled by clever bytecode tricks, so it's not built with vanilla Java. Further, you still have to take care not to use any libraries that are incompatible with this concurrency model (e.g., anything that does sync I/O).
- pjmlp 10y agoC++17 gives you async/await, coroutines and parallel algorithms.
- weberc2 10y agoRight, but this is still a far cry from Go's runtime/scheduler. In particular, the Go runtime completely handles threading and async I/O for me. I'm not sure what C++17 coroutines look like, but I don't even have to explicitly yield (which is the case in other C++ coroutine libraries).
- pjmlp 10y agoJust like any other async/await model. Also you don't need explicit yield on task runtimes like HPX.
- weberc2 10y ago> Just like any other async/await model. I don't see how Go bears any resemblance to an async/await model. Did I misinterpret your statement? > Also you don't need explicit yield on task runtimes like HPX. I don't dispute that it's hypothetically possible to bolt enough things onto C++ to make it behave like Go, but I seriously doubt it's a viable solution. I would sincerely love to know if anyone has done all of this and is using it in production.
- mmargerum 10y agoThe two biggest thorns in my side with go have been rectified in go 1.8 Multiple result sets Sorting slices