昨天花了大半天去一排查一个 bug, 从数据请求入口一直到数据比较的来源,把整个项目的程序运行过程从头到尾走了一遍。后来发现问题的根源竟然来源于最基本的数据写入操作。项目中使用的数数据库为 mongodb,对于每一组数据都会构建一个数据结构 (struct) 并且一般会给数据结构中的每一个字段 (field) 指定一个 bson tag, 当然如果不指定的话 monog 会以结构中字段名称的全小写格式去读写数据,这没什么问题,特别是对于只有一个程序在使用这个数据的时候。但是像目前自己接触到的 bug 涉及到两个甚至三个,每个项目中都要从 mongo 中读取这些数据,两个项目中指定的 bson tag 不一样,或者说一个项目中的代码指定了 bson tag,另一个却没指定那问题就来了。我就是遇到了后面一种。
像这种最基本的 Bug 出现的原因更多的在于开发人员不够细心,而不够细心的原因就多了,可能是由于一下子代码写得多了,偶你出现一两个小的失误;也可能是因为个人平常时真的没有意识到要去注意等等… 但是犯了最基础的错误往往会导致严重的问题,所以对基础的严格要求也是作为一名(合格的)开发人员最基本的前提。顿时也想到了为什么公司企业在招人时最注重应聘者的技能和修养之一在于:良好的技术基础和认真细心的做事态度
最后,随便把自己测试确认的代码也贴上来:
mongo.go
package mongoDemo
import (
"fmt"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
type JPerson struct {
Name string
Phone string
Id int
// Name string `json:"Name"`
// Phone string `json:"Phone"`
// Id int `json:"Id"`
}
type BPerson struct {
Name string `bson:"Name"`
Phone string `bson:"Phone"`
Id int `bson:"Id"`
}
func StructTagDemo() (err error) {
println("<<<structTagDemo---------------------------")
session, err := mgo.Dial("127.0.0.1:27017")
if err != nil {
return
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB("testdb").C("demo")
//warn: if not specific a bson tag, all file name will convert to lower case
// err = c.Insert(&JPerson{"json", "+222222222fjefei22", 1})
// err = c.Insert(&BPerson{"bson", "+222222222fjefei22", 1})
// if err != nil {
// return
// }
// result := []*BPerson{}
result := []*BPerson{}
// singleResult := BPerson{}
// err = c.Find(bson.M{"Name": "bson"}).One(&singleResult)
// err = c.FindId(bson.M{"Name": "bson"}).One(&result)
// err = c.Find(bson.M{}).All(&result)
err = c.Find(bson.M{"Name": "bson"}).All(&result)
if err != nil {
return
}
// fmt.Printf("singleResult: %+v\n",singleResult)
for k, v := range result {
fmt.Printf("%+v: %+v\n", k, v)
}
println("-----------------------------structTagDemo>>>")
return
}
mongo_test.go
package mongoDemo
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestStructTagDemo(t *testing.T) {
Convey("elegant result", t, func() {
// var tmp interface{}
err := StructTagDemo()
So(err, ShouldEqual, nil)
// b := A{N: good"}
// r := `{"name":"good"}`
// ret := MarshalDemo(b)
// // fmt.Printf("rest: %+v\n", ret)
// // t.Log(ret)
// So(r, ShouldNotEqual, ret)
// So(r, ShouldEqual, ret)
})
}