Crie o hábito de escrever juntos! Este é o terceiro dia da minha participação no "Nuggets Daily New Plan · April Update Challenge", clique para ver os detalhes do evento .
prefácio
Este mês, continuarei atualizando artigos relacionados ao idioma Go, especialmente GoFrame. Os alunos interessados podem me seguir e ir juntos.
Ao mesmo tempo, vou resumir e resumir: "Prática de Desenvolvimento China-Taiwan", "Prática de Implantação Privada", "Compreensão Aprofundada de Goroutine e Prática de Uso", "Como Refletir o Valor da Linguagem GO no Processo de Desenvolvimento ".
Determinado a precipitar algum conteúdo de alta qualidade.
Hoje, este artigo GoFrame ORM
compartilha os pontos de conhecimento relevantes que considero valiosos, possíveis armadilhas e melhores práticas no processo de usá-lo.
Tipos de valor e tipos de ponteiro
Quando aprendi a ir, eu estava emaranhado com tipos de valor e tipos de ponteiro. Mais tarde, no processo de usá-lo, descobri que não há necessidade de emaranhar.
A vantagem do tipo de ponteiro é que ele economiza espaço de memória. Várias variáveis apontam para o mesmo endereço de memória, e cada uma é próspera. Uma modificação pode ser modificada em todos os lugares.
O tipo de valor pode ser entendido simplesmente como: para evitar esse problema de modificar um local e modificar em todos os lugares, em alguns cenários, não podemos simplesmente considerar o desempenho, e não podemos apenas considerá-lo 复用
.
Também somos incentivados a usar tipos de ponteiro no GoFrame, por exemplo:
Scan
Converta os resultados da consulta em struct
objetos usando
Scan
Suporta a conversão do resultado da consulta em um struct
objeto, o resultado da consulta deve ser um registro específico, e o pointer
parâmetro deve ser struct
o endereço do ponteiro ( *struct
ou **struct
) do objeto, por exemplo:
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
user := User{}
g.Model("user").Where("id", 1).Scan(&user)
复制代码
ou
var user = User{}
g.Model("user").Where("id", 1).Scan(&user)
复制代码
As duas primeiras maneiras são pré-inicializar o objeto (alocar memória com antecedência)
O método recomendado é o seguinte, este método só realizará a inicialização e alocação de memória quando os dados forem consultados:
var user *User
g.Model("user").Where("id", 1).Scan(&user)
复制代码
Preste atenção à diferença de uso, especialmente a diferença no tipo de parâmetro passado (o tipo de parâmetro passado nas duas primeiras maneiras é *User
, o tipo de parâmetro passado aqui é na verdade **User
).
inserir dados
Inserir Ignorar
这个函数需要重点和大家说一下,因为我之前有Laravel的使用经验,Laravel中的InsertIgnore
是配合唯一索引使用,意思是如果存在唯一主键或者唯一索引就忽略掉,不重复插入。
在GoFrame中是相反的:
GoFrame中默认的insert
函数,就会根据唯一索引(或主键)执行,如果有存在的数据返回失败,不重复插入。
而GoFrame中的InsertIgnore是忽略错误继续插入,而不是存在就不插入。
大家在使用中要注意。
灵活执行SQL
我们要拼接自定义的sql参数怎么办法呢?
gdb.Raw()
示例如下:
OnDuplicate(g.Map{
"nickname": gdb.Raw("CONCAT('name_', VALUES(`nickname`))"),
})
复制代码
gdb.Raw()
中的参数将作为sql执行的语句,不会自动转换成字符串类型,也不会作为预处理参数。
示例如下:
// INSERT INTO `user`(`id`,`passport`,`password`,`nickname`,`create_time`) VALUES(id+2,'80','123456','wzy',now())
g.Model("user").Data(g.Map{
"id": gdb.Raw("id+2"),
"passport": "80",
"password": "123456",
"nickname": "wzy",
"create_time": gdb.Raw("now()"),
}).Insert()
复制代码
链式安全
我们首先要有这个概念:什么是链式安全?
其实很简单:链式安全就是操作model模型时不会改变当前model对象,模型属性修改/条件叠加需要使用赋值来操作。
而链式非安全
或者非链式安全
就是:操作model模型时会改变当前model对象的属性。
在GoFrame开发过程中,强烈建议使用gf gen dao
生成的model和dao文件!!!
通过gf gen dao
生成的model和dao文件默认是链式安全的。
举例如下:
func NewGomeStockDao() *GomeStockDao {
return &GomeStockDao{
M: g.DB("default").Model("gome_stock").Safe(), //注意看这里
DB: g.DB("default"),
Table: "gome_stock",
Columns: gomeStockColumns{
Id: "id",
MchWhseCode: "mch_whse_code",
MchWhseName: "mch_whse_name",
IsNationWide: "is_nation_wide",
Status: "status",
LastUpateTime: "last_upate_time",
},
}
}
复制代码
链式安全时我们如何叠加条件改变呢?
答案就是:通过赋值。
链式安全时通过 m = m.xxx 方式赋值实现链式调用
举例如下:
m := user.Where("status IN(?)", g.Slice{1,2,3})
if vip {
// 查询条件通过赋值叠加
m = m.And("money>=?", 1000000)
} else {
// 查询条件通过赋值叠加
m = m.And("money<?", 1000000)
}
// vip: SELECT * FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT * FROM user WHERE status IN(1,2,3) AND money < 1000000
r, err := m.All()
// vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money < 1000000
n, err := m.Count()
复制代码
总结
碰到好的东西就忍不住分享,我现在可以说是Go语言的忠实拥趸。
对GO感兴趣的朋友可以查看我之前写的文章,了解一下Go的魅力:
欢迎大家关注我的Go语言学习专栏
,我会持续更新在Go学习和使用过程中的干货分享。
最后
Obrigado por ler, e bem-vindos a todos: like, favorito,moeda(focar em)! ! !