I have a struct in which one of the fields type is interface , how can i map the interface into a db field (what should be the column type)so that i can retrive that? In the below code i want to know how to map the Task field inside database so that i can store "a" and "b" in database. If it wasn't an interface i could have mapped with underlying struct . I don't have any constraints in postgres package to be used
package main
import (
"fmt"
)
type Sai struct {
Name string. // can map this in db as string
Task Test. // how should i map this
}
type Test interface {
Print()
}
type dummyStruct1 struct {
Name StringStruct
}
type StringStruct struct {
Name string
}
type dummyStruct2 struct {
Name StringStruct
}
func main() {
fmt.Println("Hello, playground")
s1 := dummyStruct1{Name: StringStruct{"jon"}}
s2 := dummyStruct1{Name: StringStruct{"smith"}}
a := Sai{Name: "task1", Task: s1.Hello()}
b := Sai{Name: "task1", Task: s2.Hello()}
a.Task.Print()
b.Task.Print()
}
func (s StringStruct) Print() {
fmt.Println(s.Name)
}
func (d dummyStruct1) Hello() StringStruct {
return d.Name
}
func (d dummyStruct2) Hello() StringStruct {
return d.Name
}
CodePudding user response:
If you are the one implementing the concrete types for interface Test
:
If you can modify Test
itself do:
import (
"database/sql"
"database/sql/driver"
)
// other stuff
type Test interface{
sql.Scanner
driver.Valuer
Print()
}
else create a new type TestDB
import (
"database/sql"
"database/sql/driver"
)
// other stuff
type TestDB interface{
sql.Scanner
driver.Valuer
Test
}
now whichever new type you create will have to implement the sql.Scanner and driver.Valuer interfaces. These are used automatically by lib/pq
internally when writing value to or scanning data from the database.
As an example
// Assuming Test can implement Valuer and Scanner interfaces
package main
import (
"fmt"
"database/sql"
"database/sql/driver"
)
type Sai struct {
Name string // can map this in db as string
Task Test // how should i map this
}
type Test interface {
sql.Scanner
driver.Valuer
Print()
}
type StringStruct struct {
Name string
}
func main() {
...
}
func (s StringStruct) Print() {
fmt.Println(s.Name)
}
func (s StringStruct) Value() (driver.Value, error) {
return s.Name
}
func (s *StringStruct) Scan(src interface{}) error {
v, ok := src.(string)
if !ok {
return fmt.Errorf("not a string")
}
s.Name = v
}
// more code
...
...
Now you can store anything of type StringStruct
- which is also of type Test
- as a simple varchar
or text
inside postgres. This is also not limited to string
s only though as you can tell - infact this is my current method of storing and retrieving json from pq.
CodePudding user response:
You can use this
type Sai struct {
name string. // can map this in db as string
Task Test. // how should i map this
}
as this by taking a pointer to the address of the struct
type Sai struct {
name string // can map this in db as string
Task *Test // how should i map this
}