duanduo7400 2018-09-05 04:19
浏览 305

使用Go sql重写每种类型的Scan和Value方法时,避免重复代码

Golan SQL plus Gorp expect that all types include a Scan and Value method attached to the type in order to read the Rows to a struct. This is adding a lot of boilerplate code in my project even when the methods can be generalized because I am writing JSON to this columns.

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)
}

Is there a way to avoid defining all those identical Value and Scan Methods for each of my Structs?

The table should look like this:

Table: Type1
-----------------------
ROW   Type2                Type3               Type4
1     {"name": "MyName"}   {"other": "bla"}    {"other": "bla"}

I tried using composition as @danicheeta recommend:

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)
}

But if I execute an insert to the database the result is:

Table: Type1
-----------------------
ROW   Type2                Type3               Type4
1     {}                   {}                  {}

Similarly if I have already inserted "manually" in the database this:

Table: Type1
    -----------------------
    ROW   Type2                Type3               Type4
    1     {"name": "MyName"}   {"other": "bla"}    {"other": "bla"}

And try to do a select * from Type1 I get:

Type1: {
   Type2: {}
   Type3: {}
   Type4: {}
}
  • 写回答

1条回答 默认 最新

  • dongzhang6677 2018-09-05 06:05
    关注

    here's a solution:

    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)
    }
    

    notice that Base embeded in structs should not have a var before it (i mean type Type2 struct { b Base, some primitives... })

    评论

报告相同问题?

悬赏问题

  • ¥15 想问一下树莓派接上显示屏后出现如图所示画面,是什么问题导致的
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号