Home > other >  map an interface inside struct filed into a postgres db column datatype
map an interface inside struct filed into a postgres db column datatype

Time:10-06

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 strings 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
    }
  • Related