使用go sql时,在每种类型中重写扫描和值方法时避免重复代码

使用go sql时,在每种类型中重写扫描和值方法时避免重复代码,go,gorp,Go,Gorp,SQL plus Gorp希望所有类型都包含附加到该类型的扫描和值方法,以便将行读取到结构。这在我的项目中添加了很多样板代码,即使这些方法可以通用化,因为我正在为这些列编写JSON type Type1 struct { Type2 Type2 Type3 Type3 Type4 Type4 } type Type2 struct { some primitives... } type Type3 struct { some primitives... } type Type4 stru

SQL plus Gorp希望所有类型都包含附加到该类型的扫描和值方法,以便将行读取到结构。这在我的项目中添加了很多样板代码,即使这些方法可以通用化,因为我正在为这些列编写JSON

type Type1 struct {
 Type2 Type2
 Type3 Type3
 Type4 Type4
}

type Type2 struct { some primitives... }
type Type3 struct { some primitives... }
type Type4 struct { some primitives... }


func (q Type2) Value() (driver.Value, error) {
    return json.Marshal(q)
}

func (q *Type2) Scan(src interface{}) error {
    source, _ := src.([]byte)
    if string(source) == "null" {
        return nil
    }
    return json.Unmarshal(source, q)
}

func (q Type3) Value() (driver.Value, error) {
    return json.Marshal(q)
}

func (q *Type3) Scan(src interface{}) error {
    source, _ := src.([]byte)
    if string(source) == "null" {
        return nil
    }
    return json.Unmarshal(source, q)
}

func (q Type4) Value() (driver.Value, error) {
    return json.Marshal(q)
}

func (q *Type4) Scan(src interface{}) error {
    source, _ := src.([]byte)
    if string(source) == "null" {
        return nil
    }
    return json.Unmarshal(source, q)
}
有没有办法避免为我的每个结构定义所有相同的值和扫描方法

该表应如下所示:

Table: Type1
-----------------------
ROW   Type2                Type3               Type4
1     {"name": "MyName"}   {"other": "bla"}    {"other": "bla"}
我尝试使用@Danichetta推荐的构图:

type Base struct {} 
type Type2 struct { Base, some primitives... }

func (q Base) Value() (driver.Value, error) {
    return json.Marshal(q)
}

func (q *Base) Scan(src interface{}) error {
    source, _ := src.([]byte)
    if string(source) == "null" {
        return nil
    }
    return json.Unmarshal(source, q)
}
但如果我对数据库执行insert,结果是:

Table: Type1
-----------------------
ROW   Type2                Type3               Type4
1     {}                   {}                  {}
同样,如果我已经在数据库中插入了“手动”,则:

Table: Type1
    -----------------------
    ROW   Type2                Type3               Type4
    1     {"name": "MyName"}   {"other": "bla"}    {"other": "bla"}
然后试着做一个
select*fromtype1
I get:

Type1: {
   Type2: {}
   Type3: {}
   Type4: {}
}
这里有一个解决方案:

type Base struct {}

type Type2 struct { Base, some primitives... }
type Type3 struct { Base, some primitives... }
type Type4 struct { Base, some primitives... }

func (q Base) Value() (driver.Value, error) {
    return json.Marshal(q)
}

func (q *Base) Scan(src interface{}) error {
    source, _ := src.([]byte)
    if string(source) == "null" {
        return nil
    }
    return json.Unmarshal(source, q)
}

请注意,嵌入结构中的Base前面不应该有一个var(我的意思是
类型2 struct{b Base,一些原语…}

Hi@danichetta,我已经测试过了,但它不起作用。我猜Go中的SQL库使用反射来读取这个扫描和值函数的类型,因此它返回了一个错误的Json,其中封送和解封在基类中执行,而不是在Type2、Type3、Type4中执行。不,它只是调用Scan in,您能提供有关错误的更多信息吗?在开始扫描时,请惊慌失措,看看它是否被称为reply@danichetta的hanks,主要问题不在golang SQL中,而是因为在添加新的基本结构时,它破坏了我的JSON转换。我用一些例子详细阐述了这个问题。这不起作用,因为嵌入结构
Base
无法访问嵌入结构
Type2
Type3
Type4
的其他字段。因为结构嵌入是组合而不是继承,
Type2
(以及其他)有一个
Base
,但不是
Base
。调用
Type2.Value()。它返回一个空的json字符串
{}
,这仅仅是因为
Base
值没有任何字段。尝试将一个虚拟导出字段添加到
Base
结构中,看看它是否被序列化。@SamChoukri是的,就是这样。那么回到最初的问题,有没有办法避免所有的代码重复?也许正是由于我对函数式语言或POO语言的固执,我觉得我应该摆脱所有那些重复的方法……:)您的类型是否只有未导出的字段?只有导出的字段将序列化为json.Nop,所有字段都是导出字段。如果我复制代码如图所示,它就会工作。如果我尝试使用@danichetta提到的基本结构进行组合,我会得到空数据。