georgysavva / scany

Library for scanning data from a database into Go structs and more
MIT License
1.23k stars 67 forks source link

Scanning into two custom structs that are not under my control #141

Closed somerandomuser666 closed 13 hours ago

somerandomuser666 commented 6 days ago

Hey @georgysavva,

First of all, thank you very much for your efforts and this library!

I have a question about using it and I don't really understand how to achieve my goal. Imagine I have two structs. They could either come from a third party library or be automatically generated by a Golang code generator. Both ways are out of my control. I.e. I'm not able to change their behavior.

// both structures come from a source beyond my control
type NullStr struct {
  isSet bool
  val   *string
}
type User struct {
  FirstName string
  LastName  *NullStr
}

// my hypothetical code is as follows
sqlQuery := "SELECT first_name, last_name FROM users"
var users []*User
err := pgxscan.Select(ctx, db, &users, sqlQuery)

Is there a way to do this with your library? I've already tried it as shown above. It doesn't work.

Cheers!

georgysavva commented 17 hours ago

Hi, thanks for asking your question. For this to work, your type (NullStr) needs to know how to scan data into itself, usually by implementing this standard interface. Scany will detect that and pass the entire object to the underlying database driver to do the scanning. If you use a custom database driver that has a different notion for scannable structs, you can initialize scany with these custom interfaces for it to be able to detect them: https://pkg.go.dev/github.com/georgysavva/scany/v2@v2.1.3/dbscan#WithScannableTypes.

If the types that are outside of your control don't support any .Scan() methods, the only way to make it work is to wrap them in a struct that you control and implement the .Scan() method that conforms with your driver Scanner interface. I hope this help

somerandomuser666 commented 13 hours ago

Thank you for the clarification! I will most likely just end up with my own type and implement two functions to convert between my type and another 3rd party type. I think it's a good idea to keep my Golang code as simple as possible (i.e. it aligns with the overall language philosophy).

Have fun and all the best for you, @georgysavva!