7 ms·
This looks like a great resource! A bit of a rant (not directed at the person who wrote this, because the link at hand is great): Writing APIs in Go is not the
by mitchellh 13y ago
This looks like a great resource! A bit of a rant (not directed at the person who wrote this, because the link at hand is great):
Writing APIs in Go is not the hard part. There are a ton of options for routing basic URLs to handlers. There are a few areas that are a nightmare, total total nightmare:
* SQL - The raw database/sql package in Go is very low-level. It is a terrible experience to use in a project that makes anything more than a handful of simple queries. I'm not asking for an ORM, but it would really benefit the community if there was a SQLAlchemy style (the non-ORM part of it) library for Go. It should be MUCH easier to make basic queries to SQL and get out results.
* Templating - The built in "html/template" package is just not good enough for a web app when compared to something like Jinja (Python). "html/template" gets points for being simple, and actually its not a complaint against "html/template": I think there just needs to be a more feature-packed templating package like Jinja for Go. "html/template" doesn't support things like inheritance, didn't even support comparison operators until Go 1.2, etc.
These two problems have made it so I've pretty much given up web apps in Go for now. Services in Go are _amazing_. But if you're trying to get a full blown web app (again, not the point of the linked article above), then you're gonna have a bad time.
- chimeracoder 13y ago> "html/template" doesn't support things like inheritance I don't want to get into a debate about what "inheritance" means, but html/template does support template composition and nested templates, which seem to address the same use case. > These two problems have made it so I've pretty much given up web apps in Go for now. Services in Go are _amazing_. But if you're trying to get a full blown web app (again, not the point of the linked article above), then you're gonna have a bad time. I'm sorry to hear that, especially since writing a "full-blown web app" is really not difficult in Go at all, once you know what you're doing. I've actually been working on Jetpack[0], a sample web application in Go to demonstrate how straightforward this is, once one understands how it actually works. (Disclaimer: it's still a work in progress, so it's not complete/ready yet). [0] https://github.com/ChimeraCoder/go-angular-jetpack https://github.com/ChimeraCoder/go-angular-jetpack
- BarkMore 13y agoThe html/template package seems to address the use case, but it comes up short in several ways. One example is defining a site template with sections that are optionally specified in a page specific template.
- memset 13y agoMany of your comments on this thread state that writing webapps in Go (SQL, etc) is not so difficult "once you know what you're doing." Could you elaborate on this? What should one know before attempting to use Go for such things?
- unoti 13y agoHere's one possible example. At the top of this thread, there's a statement about how Go templates don't support inheritance-- embedding one template within another as Django and Jinja do[1]. I personally consider this a requirement, because the old school way of having headers and footers in separate templates is radically inferior. Go doesn't offer a clear simple way to do this in their builtin template library. But it turns out, it really is possible to do it, as described in this thread on Stack Exchange[2]. I bookmarked that so that I can boil it down into some simple-to-reuse code if I ever bite the bullet and start using Go for the presentation layer on a major website. What they're doing there is a cool technique, but it's not simple to use out of the box. 1. https://sites.google.com/site/usfcomputerscience/django-templates https://sites.google.com/site/usfcomputerscience/django-temp... 2. http://stackoverflow.com/questions/11467731/is-it-possible-to-have-nested-templates-in-go-using-the-standard-library-googl http://stackoverflow.com/questions/11467731/is-it-possible-t...
- zemo 13y agothe problem with html/template is that it's made for Go programmers. A good template language is one that's made for front end devs and designers. html/template tends to be painful in practice because it's too difficult for a non-gopher to use.
- chimeracoder 13y ago
- aktau 13y agoI'm usually pretty anti-ORM and actually like low-level SQL interfaces (I guess because I did a short stint as an Oracle developer once, once you see what can be done with some custom SQL...). But for a recent sideproject of mine, I really didn't want to create a laborious interface to the database. I wanted something quick and dirty. I got something quick, and it doesn't feel dirty at all. It's called gorp: http://github.com/coopernurse/gorp http://github.com/coopernurse/gorp. By the way, my sideproject is about getting financial data from sources like Yahoo Finance, Bloomberg, et cetera. You can find it here: https://github.com/aktau/gofinance https://github.com/aktau/gofinance
- jamra 13y agoI agree with the templating problem. Additionally, it is difficult to find proper documentation on how to do templating and not just basic examples.
- lann 13y ago> SQL I'm working on an arel-esque fluent SQL generator now: https://github.com/lann/squirrel https://github.com/lann/squirrel I'll release it once I'm a little more confident in the interface. Currently you can do things like this: rows, err := Select("col"). From("tab"). Where("x = ?", 1). RunWith(db).Query()
- rckclmbr 13y agoHonest question... how is this different from, say: rows, err := db.execute("SELECT col FROM tab WHERE x = ?", 1);
- lann 13y agoPrimarily because you can reuse partial queries and add conditional where clauses more easily. There are other features I haven't shown here as well, like building an IN expression with placeholders from a slice.
- mercurial 13y agoIt's harder to shoot yourself in the foot by mistyping SELECT, for instance, and it's clearly more composable.
- wc- 13y ago> I'll release it once I'm a little more confident in the interface. Release it now! I've said the same thing in the past about some code I was working on. Add a little readme, explicitly say it is a work in progress, and get it out there. At the very least the rush of publicizing something will push your drive to work on this codebase, and you might even gain some contributors. I'd rather use a repo that is obviously a work in progress but has active contributions from the creator over some more 'complete' but stagnant repo any day.
- lann 13y agoDon't worry, I'm not shooting for anything like perfection. I released another library that this builds on just last week: https://github.com/lann/builder https://github.com/lann/builder
- hierro 13y agoWe're about to release our Go web framework which, I think, implements all the features you're mentioning and a few more. We're aiming for a release in Q1, but getting everything cleaned up and writing good documentation is taking a bit longer than expected. Right now, our internal framework (codenamed Gondola, but subject to change), includes: * A full ORM which generates tables from structs and allows relations between models, as well as a simple querying system based on Go functions which joins the tables automatically for you e.g. memeId := base36.Decode(param) var meme *Meme var template *Template err := ctx.Orm().One(orm.Eq("Meme|Id", memeId), &meme, &template) Meme declares a FK to Template, so the ORM automatically joins the tables and populates both pointers. Note that the ORM does not require the backends to be relational, so even when ATM we only have database/sql based backends you could write a backend for mongodb or rethinkdb. * Inheritance based template system, with a declarative assets pipeline supporting compilation (e.g. it compiles coffescript to JS and less to CSS on demand - also pluggable). This is the base template from one of our apps: {{/* jquery|if=~ie-gte-9: 2.0.3 jquery|if=ie: 1.10.2 bootstrap|fontawesome=4.0.3: 3.0.0 styles|bundle: css/style.css, lightbox/css/lightbox.css scripts|top,bundle: js/modernizr.js, js/detectizr.js scripts|bundle: js/responsiveslides.js, lightbox/js/lightbox-2.6.min.js, js/site.js analytics|nodebug: {{ $Config.Analytics }} */}} <!DOCTYPE html> ... {{ template "main" }}... This server query 1.10 and 2.0 from Google's CDN, bootstrap and fontawesome from bootstrapcdn.com and bundles all our styles and scripts a CSS and a JS file. Then other templates can extend this one and override its blocks e.g. {{/* extends: base.html */}} {{ define "main" }}... (note that base.html could also define its own "main" block which would act as a default if you loaded base.html and it would be replaced by main.html's "main" block if you loaded "main"). * Easy to use signed and encrypted cookies. * Regular expression based URL routing. * Functions for easily parsing input parameters. * A development server which automatically rebuilds the source as it changes and reports compilation errors in the browser itself. While developing, runtime errors are also reported in the browser with complete backtraces and printing the values passed to each function. While running in production, those reports are sent by email to the project administrator(s). * App-wide and low-level caching system with pluggable backends, currently supporting Redis and Memcache as well as a dummy backend for development. * Form generator and validator from Go structs, with renderers for both Bootstrap and Foundation (renderers are also pluggable, so you could also write your own. We also support generating forms from multiple objects so you e.g. write an object which generates a captcha and include it in any form with a single line in code (in fact, we provide just that, but a simple numeric captcha a a full-blown recaptcha object). It also does automatic CSRF protection. * A complete i18n system, which extracts strings from Go code and templates, generates .pot files which can be translated using any editor (or a specialized .po editor if you feel like it) and them compiles .po files back to Go code again. This makes packages with their translations "go-get-able". * Periodic and background tasks which can either be scheduled or just started from any web request. * A configuration package which takes a struct and fills it by parsing an optional configuration file as well as command line flags. * Support for administrative commands, which can be executed from the command line or started remotely. * Support for pluggable apps. e.g. we do have a "users" app which provides user registration, authentication and social integration. This can be included in any other app with a couple of lines of code (one line for the import, another line to tell our main app to include it). Included apps can do a lot of stuff, like inserting code in every template rendered by the parent app, including external assets like images, styles or scripts and even rendering their own templates contained inside your parent's app base template. * Last but not least, a minimal overhead (in the range of 100ns per request) profiling framework which lets you know how much time a request spent in the cache, the orm, the template, e.g... as well as seeing how much each operation took (e.g. you can check how much time a SELECT took and also perform an EXPLAIN on it). Users can also define their own events and profile them by instrumenting their code (it usually requires just a line of code per resource, to indicate its name). You can also profile a live server by using a command line app included in the framework. We also have helper and utility functions for the more mundane stuff and basically everything you could expect from a web framework. We took inspiration from Django, Tornado and Rails and tried to take the best of them while building this framework (I used to contribute to Tornado back in the day). We've been developing this internally for almost 2 years and it's now around 40KLOC of Go and a couple of K of coffescript, less and html.
- johne20 13y agoYou mentioned "Services in Go are _amazing_", but how do you avoid the first issue you mentioned? I have found so far getting data in and out to be somewhat cumbersome. Also how do you handle data validations and logging?
- latch 13y agoFWIW, I started to work on an erb-inspired templating package: https://github.com/karlseguin/gerb https://github.com/karlseguin/gerb I didn't get to finish it before leaving on a trip, but I'll be back on it Feb 1st and can hopefully wrap it up in the first week. I did finish a liquid-inspired template: https://github.com/karlseguin/liquid https://github.com/karlseguin/liquid but I wasn't particularly happy with it (neither the implementation nor liquid itself).
- elithrar 13y ago> * SQL - The raw database/sql package in Go is very low-level. It is a terrible experience to use in a project that makes anything more than a handful of simple queries. I'm not asking for an ORM, but it would really benefit the community if there was a SQLAlchemy style (the non-ORM part of it) library for Go. It should be MUCH easier to make basic queries to SQL and get out results. I can highly recommend https://github.com/jmoiron/sqlx https://github.com/jmoiron/sqlx which allows you to easily unpack results into structs/maps, or pass in a struct/map and insert it (using struct tags + named queries). If you're writing a CRUD application this covers a lot of the basics. There's also https://github.com/eaigner/jet https://github.com/eaigner/jet which is a 'micro ORM' (and very light on the ORM part). > "html/template" doesn't support things like inheritance, didn't even support comparison operators until Go 1.2, etc. I grew to like html/template over time, but the lack of comparison operators pre Go 1.2 was a huge sore point and I had I been working on this little project a year ago I'd have been extremely frustrated. The lack of inheritance was a bit of a pain for me too—I ended up splitting my templates into many (!) smaller pieces so I could at least re-use the portions I needed to. Hopefully something "Jinja-esque" comes in time. There's an (unmaintained) Mustache port and a Mustache-alike in Mandira (https://github.com/jmoiron/mandira https://github.com/jmoiron/mandira) but I've not seen anything like Jinja yet. If there's one thing html/template has going for it is that I can trust it (as much as one can) to be 'safe'. I wouldn't say web apps in Go should be avoided at all costs, but I would say that you should consider the scope/scale and do a bit of research first. Sometimes Django/Rails or Flask/Sinatra might make it easier on you.