https://segmentfault.com/a/

遇到的问题

golang对于基本类型初始化的处理,是自动给基本类型赋值为默认值。比如:

var i int//在这里如果不对i做任何赋值,那么i的值为零

这个特性在很多地方能够避免访问到未初始化变量的尴尬,但是由此也引出了另外一个问题,就是在进行数据库访问操作时应该如果对待这样的默认值。

现在我们假设一个场景,表A有3个字段{AID int,AField1 string,AField2 string},表B也有3个字段{ID int,BField1 string,REF_AID int},其中表B中的REF_AID是外键对应表A中的AID。对应在GO中的数据结构应该为:

type A struct{
    AID int//主键
    AField1 string
    AField2 string
}

type B struct{
    BID int//主键
    BField1 string
    REF_AID int//外键,对应AID
}

在new对象B的时候,B中的三个值就分别被默认的初始化为{0,“”,0},如果此时不对内容做任何操作,直接执行插入,问题就可能会变得很严重,因为A中很可能并没有任何一条记录的ID值为0,数据库报错,这条插入是一定会失败。但是仅仅在数据库层面上来看,数据库的结构是没问题的,表B中的REF_AID可以为空,在其他的语言中,如果没有对具体数据进行初始化,该属性会为空,对应插入的时候也会为空,但是在golang中,由于语言级别的默认初始化,使得这个插入过程会有大量的0的存在,触犯到原本表的约束规则而导致插入失败。

在orm中也没有看到能够解决这个问题的办法,可能是我用的不够仔细,这个留待以后再说。

自己的一点想法

  1. 把所有的数据库中相关的表都添加一条默认的以0为id的记录,该记录不需要有意义,只是用来防止歧义以及违反约束引起的操作失败,特别是一些ref_表,因为其中数据变动不大,却经常与其他一些表存在外键关系。这样做会给数据库带来一些额外的开销,但是作为一个临时的解决办法似乎还不错,至少能让数据处理流程正确的运行。
  2. 从orm中解决问题。这个只是一个想法,不过这很可能变成一种无理的要求,因为这需要orm去判断你的Field中存放的这个0到底是你自己就想指定的0值,还是你不想要却被语言默认初始化出来的0。
  3. 自己写SQL语句执行,这可能是最傻的一种方法了,不过却能保证事情完全按照自己的想法执行。