#Fiber - pass DB to handlers

27 messages · Page 1 of 1 (latest)

scarlet ridge
#

Hi,

I'm learning how to use Fiber and I'm trying to find how to pass my SQL database object to my handlers. When I look it up I see a lot of very roundabout solutions for how to do it (wrap handlers in a closure, put your handlers in a struct, etc.). Like for example in Rust's axum you can pass it as an additional parameter in the handler function. I also saw you can just make your database a global variable but I was wondering if there's a proper clean way to do it? Thanks

ocean wave
#

the two ways you mentioned are fairly canonical, they’re not really roundabout

#

using methods is the slightly less flexible but more user-friendly strategy in most situations

scarlet ridge
#

What's the most commonly used way to do it

#

Or most recommended or whatever

ocean wave
#

i’ve seen both used in practice, they’re not that different and i won’t claim that one is definitely used more than the other

#

using functions returning a closure may be easier to test (since it requires a fixed number of specific parameters, rather than an entire receiver struct where it’s unclear which fields are used), but can be slightly more annoying to change in different places if you need to add a parameter

#

having access to an entire struct in many handlers may make code less annoying to write initially but leaves you without a strong contract for what the handler requires

scarlet ridge
#

Is there really not a built-in way to pass it? I've seen mentions of Ctx.Local but haven't seen much about it

ocean wave
#

you can use contexts, but that leaves you with a very weak contract for what the handler requires, without even a struct field

#

you may feel like it’s a reasonable trade off for convenience, but testing becomes a lot more fragile (you must set up the context in the same way in every test, without any help from the type system)

scarlet ridge
#

Might be cause I'm new to the language but this fairly essential thing seems quite overcomplicated lol

ocean wave
#

closures may introduce some complexity, but receivers for a method are quite core to the language

#

it’s composing the language’s features outside of the context of the HTTP library, rather than having the HTTP library (and then every other library) provide a one-off solution

pastel scarab
#

i do it with package level ("global") variables, though ymmv

pastel scarab
scarlet ridge
#

Are there different types of globals

pastel scarab
#

well global is a bit ambiguous of a term

#

if it's still namespaced to a given package it's not exactly global

scarlet ridge
pastel scarab
#

a namespace is just a scope that owns / exports things with names

#

but no Go doesn't have a namespace keyword

bronze agate
#

i think using structs is the best way, but rather than passing the sql.db instance, is put the db ops in their own interfaces and that allows for proper testing

#

ive tried using contexts / locals before and it gets messy

#

i tend to have own struct rather than just one huge struct though so can tell what is actually be injected

pastel scarab
#

an interface is great for that application, yes.