Jason Moiron, a Go developer, writes about Go, Python performance, databases, and programming language opinions.
HN commenters cite his posts on why CPython is slow and on Go's database/sql, and one likes his minimal blog design.
I'm going to chime in, since I've been using Go as my primary language for over a year, and I'm currently working on a major (production) Go project that others might see as well-suited for Rails (in fact, the early prototype was written in Rails[0])
> The thing no framework I have seen so far addresses is persistence. SQL persistence in Golang is a bit of a nightmare. It's raw SQL, and the database libraries are fussy.
> The thing that makes Rails so easy to write in, especially for newcomers, is ActiveRecord. As far as I can tell, nothing like it exists (in a stable form) for Golang.
I wouldn't recommend newcomers to Go use SQL right off the bat. Document-based storage (like CouchDB or MongoDB), or even key/value (Redis, etc.) is much more aligned with Go's concept of structs, and all three of those databases have strong library support in Go. If you're just looking to dabble in Go and just happen to need a database (and it doesn't matter which), I'd recommend playing around with those first. Even Neo4j works very well with Go, though as of January 2013 (when I last used it), the only Go library for Neo4j was third-party, and not very well-documented.
That said, once you know the Go language, using SQL (either with or without an ORM) is straightforward, if not as convenient as ActiveRecord. jmoiron has a good blog post[1] comparing the good, bad, and ugly of Go ORMs, so I won't try to top that here - rather, I'll share my experience.
(As pointed out elsewhere, ORMs…
There are a couple of good resources you can use here, the first is just about the best reference for using Go with a RDBMS:
http://go-database-sql.org/
The second speaks of database connections:
http://jmoiron.net/blog/gos-database-sql/
The general approach:
1. Use a single DB connection, it will pool automatically
2. Use this pattern for all single row queries:
err = db.QueryRow(`...`, ...).Scan(&...)
if err == sql.ErrNoRows {
// Handle no rows
} else if err != nil {
// Handle actual error
}
// All fine
3. Use this pattern for all multi-row queries where you want to return a slice of structs containing the row values. Note that it is fine to call rows.Close() as soon as possible in addition to deferring it, defer takes care of handling it whenever something goes wrong and the explicit call returns the connection as soon as possible:
rows, err := db.Query(`...`, ...)
if err != nil {
// Handle connection or statement error
}
defer rows.Close()
things := []rowStruct{}
for rows.Next() {
thing := rowStruct{}
err = rows.Scan(
&thing.id,
&thing.value,
)
if err != nil {
// Handle row parsing error
}
things = append(things, thing)
}
err = rows.Err()
if err != nil {
// Handle any errors within rows
}
rows.Close()
4. Use transactions as serial things, if you need to call another query whilst in a loop where you can't rows.Close(),…
I've independently come up with the same decisions on many of these points and, weirdly, a very similar blog design:
http://jmoiron.net
I decided even to dispatch with the header bar, putting navigation at the bottom of the main page; presumably, people will only care to see more of my writing if they've read the article. Not as good for people revisiting the page, but they can likely remember http://jmoiron.net/blog or bookmark it in order to get to the search.
My fonts are slightly smaller and slightly less contrast, and after looking at Gemmell's blog I wonder if I should change that decision. I wanted to have emphasized elements of the text easily distinguishable from the body while not distracting.
Also, I agree with Gemmell's "The basic tenets of hypertext should be left alone". One of these basic tenets, to me, are the semantic meanings of Blue, Purple, and Red text for normal, :visited, and :active hyperlinks. If you want to chose a link color, do not invert or violate these classical meanings.
> I often describe Go as the strongly-typed, more performant version of Python.
I've heard Go described this way several times, but I've found it to be a significantly lower-level language than Python.
For example, it's much more verbose. In this recent blog post [0], the author converts some C++ code to Go - and it gets longer. 57 lines of C++ become 65 lines of Go. The same code in Python is about 20 lines.
In particular, the author's Go code requires five lines to do the equivalent of Python's `with open(path) as f` and four lines for the equivalent of `word_array = list(word_counts.items())`:
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
// [...]
wordArray := make([]WordCount, 0, len(wordCounts))
for word, count := range wordCounts {
wordArray = append(wordArray, WordCount{word: word, count: count})
}
[0] http://jmoiron.net/blog/cpp-deserves-its-bad-reputation/
For Go, they have a statistic from a few years back that suggests about 98% of a cross section of real-world Go projects are formatted according to gofmt. (https://jmoiron.net/blog/fmty-dmpty) I can believe Rustfmt and other tools not having quite the same reach, but I would guess that the proportion is still pretty high.
These tools are very standard and very widely used.
> Don't you want to see neatly formatted code while you're writing it?
Every time I pause, I press ctrl-S or an equivalent. So I really am seeing neatly formatted code while I'm writing it. I would guess that 90% of the time, if my code is syntactically valid, it's also neatly formatted. And even if it's not valid code, it's probably very close to being neatly formatted.
Wow, actually had an article starred on this in the trusty Reader. http://jmoiron.net/blog/about-sqlalchemy-and-djangos-orm/
Money quote for me: "SQLAlchemy is a toolkit for python programmers who want or need to use a database to write programs that do so. Django's ORM is a tool for python programmers to quickly model business-level data relationships and use a database for persistent storage. This is really an important distinction; the Django ORM interface is focused on the application's data model, whereas SQLAlchemy's interface is focused on the underlying data store."