Personally, I think this is overkill (the entire concept not the rog solution)

Even with static checking there is no way to ensure that tablex has the needed 
fields. Even if you could check this at compile time - it might be different at 
runtime. 

I don’t think the juice is worth the squeeze. 

Either use an ORM that generates the sql, or create DAOs and rely on test cases 
to ensure the code is correct.

Far simpler and more robust in my opinion. 

> On Oct 6, 2021, at 6:35 AM, roger peppe <rogpe...@gmail.com> wrote:
> 
> 
>> On Wed, 6 Oct 2021 at 09:21, mi...@ubo.ro <mi...@ubo.ro> wrote:
> 
>> Hi Ian ,
>> 
>> I've modified the example towards a more specific use case. The main idea in 
>> the example below  is to make code related to database operations(i.e SELECT 
>> queries) safer and  easier to read. A  kind of json.Unmarshal/Marshal for 
>> databases, with validation (type checking, param numbers etc) to avoid a 
>> class of bugs/errors such invalid param types/numbers passed, invalid 
>> queries, invalid resource type to scan into etc. 
>>  
>> Currently the function returned by Select  throws the validation errors at 
>> runtime (i.e. invalid param type passed etc). It would be great to have that 
>> class of errors checked at compile type.
>>  
>> The only way I could achieve that kind of  type checking was  through code 
>> generation. I already built a tool to generate functions with the proper 
>> param types but it seems that code generation introduces a lot of friction 
>> to the point that I stopped using it.
>> 
>> My hope is that one day a Go feature (i.e. a version of Generics) could help 
>> the function returned by func Select be type checked at compile time.
>> 
>  
> If you change your API slightly to use a single selector argument of struct 
> type, you could do something like this:
> 
> https://go2goplay.golang.org/p/QH1VCQFxrZS
> 
> In summary:
> 
> type Flower struct {
>     Color  string
>     Size   int
>     Weight int
> }
> 
> type ByColor struct {
>     Color string
> }
> 
> var FlowerByColor = Select[Flower, ByColor]("* FROM tablex WHERE Color=$ 
> LIMIT 1")
> 
> type SelectFunc[Resource, Args any] func(args Args) (Resource, error)
> 
> // Select returns a function that executes the given SQL query,
> // expecting results to contain fields matching Resource and
> // using fields in Args to select rows.
> //
> // Both Resource and Args must be struct types; All the fields
> // in Args must have matching fields in Resource.
> func Select[Resource, Args any](q string) SelectFunc[Resource, Args] {
> 
> 
> That is, we can use a combination of reflection and generics. The generics 
> keep the code type-safe. The reflection part does the more specific type 
> checking once only at init time, something I like to think of as "almost 
> statically typed". It's a powerful pattern in my view.
> 
>   cheers,
>     rog.
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/CAJhgacjQGQ%2BEuGVu8%2Bp5FLDFjeE_amrU9G4zGAjderEZAUTAnA%40mail.gmail.com.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/FA2B1054-11DE-4C08-8988-12463FAC9981%40ix.netcom.com.

Reply via email to