一、snakecalm 是如何实现?
有很多场景,我们需要自己实现类似 orm 映射的规则,自己实现一个简答的映射规则该怎么实现?
如下代码可以适配大部分场景。
转换规则:ID -> id, User -> user, UserID -> user_id, MyUID -> my_uid, OAuth -> o_auth
orm.go
// GonicCasedName ID -> id, User -> user, UserID -> user_id, MyUID -> my_uid, OAuth -> o_auth
func GonicCasedName(columnName string) string {
newstr := make([]rune, 0, len(columnName)+3)
for index, r := range columnName {
if isASCIIUpper(r) && index > 0 {
if !isASCIIUpper(newstr[len(newstr)-1]) {
newstr = append(newstr, '_')
}
}
if !isASCIIUpper(r) && index > 1 {
l := len(newstr)
if isASCIIUpper(newstr[l-1]) && isASCIIUpper(newstr[l-2]) {
newstr = append(newstr, newstr[l-1])
newstr[l-1] = '_'
}
}
newstr = append(newstr, r)
}
return strings.ToLower(string(newstr))
}
func isASCIIUpper(r rune) bool {
return 'A' <= r && r <= 'Z'
}
//func toASCIIUpper(r rune) rune {
// if 'a' <= r && r <= 'z' {
// r -= ('a' - 'A')
// }
// return r
//}
orm_test.go
func TestGonicCasedName(t *testing.T) {
assert := assert.New(t)
assert.Equal("id", GonicCasedName("ID"))
assert.Equal("user", GonicCasedName("User"))
assert.Equal("user_id", GonicCasedName("UserID"))
assert.Equal("my_uid", GonicCasedName("MyUID"))
assert.Equal("o_auth", GonicCasedName("OAuth"))
}
二、借助成熟框架实现
gorm:
gorm.TheNamingStrategy.Column("OAuth")
=> o_authgorm.TheNamingStrategy.Column("TestURL2")
=> test_url_2
xorm:
func TestORM() {
engine, _ := xorm.NewEngine("mysql", "root:123@/test?charset=utf8")
engine.SetMapper(core.SameMapper{})
engine.SetColumnMapper(core.SnakeMapper{})
}