16 ms·
sqlc definitely uses reflection But don't let that stop you, it looks like a nice solution and reflection isn't really all that bad anyway :)
by arwineap 5y ago
sqlc definitely uses reflection
But don't let that stop you, it looks like a nice solution and reflection isn't really all that bad anyway :)
- benhoyt 5y agoAre you sure? Well, it uses "reflection" in a general sense of introspecting your SQL code, but not in the Go sense of using using type information at runtime via the "reflect" package. sqlc compiles your SQL at build time to statically typed, non-reflect-using functions, as shown here: https://docs.sqlc.dev/en/stable/howto/select.html https://docs.sqlc.dev/en/stable/howto/select.html
- earthboundkid 5y agoTechnically, reflection is used by Go’s database Scanner interface, but it’s not what most people think of when they complain about reflection.
- benhoyt 5y agoGood point. I had assumed Rows.Scan() would have just used type switches for efficiency -- it looks like it does for common cases (https://github.com/golang/go/blob/d62866ef793872779c9011161e51b9c805fcb73d/src/database/sql/convert.go#L220 https://github.com/golang/go/blob/d62866ef793872779c9011161e...) but then falls back to reflect. I wonder why it doesn't just do all of that with type switches? Maybe there are just too many cases and it ends up slower than reflect for the rest of the cases. Scanner.Scan() is actually just called via a type assertion, though I guess implementations of Scan() might use reflection.
- arwineap 5y agoIt needs reflect in order to translate struct field names into column names at the very least
- benhoyt 5y agosqlc doesn't quite work that way (though "sqlx" and other packages do). sqlc generates code at build time that avoids reflect by using database/sql's Rows.Scan() with pointers to fields (see the link above): var i Author if err := rows.Scan(&i.ID, &i.Bio, &i.BirthYear); ... This generated code is exactly what you'd write by hand if you were using database/sql directly. As earthboundkid points out, database/sql itself may use reflection under the hood to convert the individual fields (though the common cases are done without reflect, using ordinary type switches: https://github.com/golang/go/blob/d62866ef793872779c9011161e51b9c805fcb73d/src/database/sql/convert.go#L220 https://github.com/golang/go/blob/d62866ef793872779c9011161e...).