2017-11-16 17:23
浏览 123


I have a nested struct which I am using to decode JSON request.

type Service struct {
    ID       string `json:"id,omitempty" db:"id"`
    Name     string `json:"name" db:"name"`
    Contract struct {
        ServiceTime int    `json:"service_time"`
        Region      string `json:"region"`
    } `json:"contract" db:"contract"`

I am using blob type to store Contract in MySQL. To make it work , I would be needing to create a different struct with Contract as string to insert in DB. Can this be done in better way by using single struct only or is there any other elegant way ?

图片转代码服务由CSDN问答提供 功能建议


 ID字符串`json:“ id,omitempty” db:“ id”`
名称字符串`json:“ name” db:“ name”`
 ServiceTime  int`json:“ service_time”`
区域字符串`json:“ region”`
}`json:“ contract” db:“ contract”`
 \  n 

我正在使用Blob类型将Contract存储在MySQL中。 为了使其工作,我将需要使用Contract作为字符串创建另一个结构以插入DB中。 可以仅通过使用单个结构以更好的方式完成此操作,还是有其他优雅的方法?

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • douciping4283 2017-11-16 18:25

    This depends on what you use to talk to the database, but if you're using database/sql and a driver that provides support for this you can have your Contract type implement the Valuer interface.

    type Service struct {
        ID       string    `json:"id,omitempty" db:"id"`
        Name     string    `json:"name" db:"name"`
        Contract Contract `json:"contract" db:"contract"`
    type Contract struct {
        ServiceTime int    `json:"service_time"`
        Region      string `json:"region"`
    func (c *Contract) Value() (driver.Value, error) {
        if c != nil {
            b, err := json.Marshal(c)
            if err != nil {
                return nil, err
            return string(b), nil
        return nil, nil

    And then when you're executing the query just pass in the Service.Contract field and the driver should call the Value method.

    sql := // INSERT INTO ...
    svc := // &Service{ ...
    db.Exec(sql, svc.ID, svc.Name, svc.Contract)

    And to be able to retrieve the blob back from db and unmarshal it back into Contract you can have it implement the Scanner interface, again, if a type implements this the driver is expected to call it.

    func (c *Contract) Scan(src interface{}) error {
        var data []byte
        if b, ok := src.([]byte); ok {
            data = b
        } else if s, ok := src.(string); ok {
            data = []byte(s)
        return json.Unmarshal(data, c)
    // ...
    sql := // SELECT * FROM ...
    svc := // &Service{ ...
    db.QueryRow(sql, 123).Scan(&svc.ID, &svc.Name, &svc.Contract)
    打赏 评论

相关推荐 更多相似问题