【GORM学习笔记】GORM介绍以及增删改查相关操作
优缺点
- 优点:提高开发效率,防止SQL注入、对不熟悉SQL语句的人友好、代码统一
- 缺点:牺牲执行能力、牺牲灵活性、弱化SQL能力
在一些小型项目上使用ORM可以大大提高开发效率,但是在一些对性能要求高得场景下,ORM可能没有那么合适。
环境配置
-
GORM:在命令行中输入如下命令
go get -u github.com/jinzhu/gorm即可安装GORM。 -
MySQL:请参考MySQL安装教程。
连接数据库
-
GROM官方支持的数据库类型有:MySQL、PostgreSQL, SQLite, SQL Server 和 TiDB。
-
以连接MySQL为例,GORM连接MySQL非常简单,其代码如下:
import ("gorm.io/driver/mysql""gorm.io/gorm" )func main() {dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) } -
MySQL驱动程序也提供了一些高级配置供程序员在初始化的过程中使用。
db, err := gorm.Open(mysql.New(mysql.Config{DSN: "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // DSN data source nameDefaultStringSize: 256, // string 类型字段的默认长度DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置 }), &gorm.Config{})
模型默认相关
-
GORM提供了一个预定义的结构体,名为
gorm.Model,其中包含常用字段:ID为默认的主键;CreatedAt记录了该记录被创建的时间;UpdatedAt记录该记录被更新的时间;DeletedAt记录了该记录被删除的时间,因为GORM中的Delete是软删除。// gorm.Model 的定义 type Model struct {ID uint `gorm:"primaryKey"`CreatedAt time.TimeUpdatedAt time.TimeDeletedAt gorm.DeletedAt `gorm:"index"` } -
将其嵌入结构体中: 可以直接在结构体中嵌入
gorm.Model,以便自动包含这些字段。 这对于在不同模型之间保持一致性并利用GORM内置的约定非常有用。当然,我们也可以手动创建。 -
包含的字段:
ID:每个记录的唯一标识符(主键)。CreatedAt:在创建记录时自动设置为当前时间。UpdatedAt:每当记录更新时,自动更新为当前时间。DeletedAt:用于软删除(将记录标记为已删除,而实际上并未从数据库中删除)
-
GORM中常见的结构体tag:
标签名 说明 column 指定 db 列名 type 列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如: not null、size,autoIncrement… 像varbinary(8)这样指定数据库数据类型也是支持的。在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENTserializer 指定将数据序列化或反序列化到数据库中的序列化器, 例如: serializer:json/gob/unixtimesize 定义列数据类型的大小或长度,例如 size: 256primaryKey 将列定义为主键 unique 将列定义为唯一键 default 定义列的默认值 precision 指定列的精度 scale 指定列大小 not null 指定列为 NOT NULL autoIncrement 指定列为自动增长 autoIncrementIncrement 自动步长,控制连续记录之间的间隔 embedded 嵌套字段 embeddedPrefix 嵌入字段的列名前缀 autoCreateTime 创建时追踪当前时间,对于 int字段,它会追踪时间戳秒数,您可以使用nano/milli来追踪纳秒、毫秒时间戳,例如:autoCreateTime:nanoautoUpdateTime 创建/更新时追踪当前时间,对于 int字段,它会追踪时间戳秒数,您可以使用nano/milli来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milliindex 根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看 索引 获取详情 uniqueIndex 与 index相同,但创建的是唯一索引check 创建检查约束,例如 check:age > 13,查看 约束 获取详情<- 设置字段写入的权限, <-:create只创建、<-:update只更新、<-:false无写入权限、<-创建和更新权限-> 设置字段读的权限, ->:false无读权限- 忽略该字段, -表示无读写,-:migration表示无迁移权限,-:all表示无读写迁移权限comment 迁移时为字段添加注释 -
使用方法如下:
type User struct {gorm.ModelUserName string `gorm:"column:user_name;type:varchar(20);not null"`Age string `gorm:"column:age;type:int"`Email string `gorm:"column:email;type:varchar(20);unique"` }
-
创建记录
-
我们可以通过
gorm.Create()方法创建记录,需要注意的是传递的参数是结构体指针,而非结构体本身。此外,gorm.Create()方法也可以创建多条记录。返回值Result有两个属性,分别为创建记录错误Error和创建记录的条数RowAffected。// 创建一条记录 user := User{Name: "xiaoming", Age: 21, Email: "XXX@qq.com"} result := db.Create(&user) // 通过数据的指针来创建// 创建多条记录 users := []*User{{Name: "xiaoming", Age: 21, Email: "XXX@qq.com"},{Name: "ming", Age: 21, Email: "YYY@qq.com"}, } result := db.Create(users) // 传递切片 -
创建记录并为指定字段赋值。
db.Select("Name", "Age", "CreatedAt").Create(&user) -
创建记录并忽略传递给 ‘Omit’ 的字段值
db.Omit("Name", "Age", "CreatedAt").Create(&user) -
使用钩子函数:GORM允许用户通过实现这些接口
BeforeSave,BeforeCreate,AfterSave,AfterCreate来自定义钩子。 这些钩子方法会在创建一条记录时被调用。func (u *User) BeforeCreate(tx *gorm.DB) (err error) {u.UUID = uuid.New()if u.Role == "admin" {return errors.New("invalid role")}return }如果你想跳过
Hooks方法,可以使用SkipHooks会话模式,例子如下DB.Session(&gorm.Session{SkipHooks: true}).Create(&user)DB.Session(&gorm.Session{SkipHooks: true}).Create(&users)DB.Session(&gorm.Session{SkipHooks: true}).CreateInBatches(users, 100)
查询记录
-
GORM提供了
First、Take和Last方法从数据库中检索单个对象。 -
FirstandLast方法会按主键排序找到第一条记录和最后一条记录 (分别)。 只有在目标struct是指针或者通过db.Model()指定 model 时,该方法才有效。 此外,如果相关model没有定义主键,那么将按model的第一个字段进行排序。 例如:var user User var users []User// works because destination struct is passed in db.First(&user) // SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1// works because model is specified using `db.Model()` result := map[string]interface{}{} db.Model(&User{}).First(&result) // SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1// doesn't work result := map[string]interface{}{} db.Table("users").First(&result)// works with Take result := map[string]interface{}{} db.Table("users").Take(&result)// no primary key defined, results will be ordered by first field (i.e., `Code`) type Language struct {Code stringName string } db.First(&Language{}) // SELECT * FROM `languages` ORDER BY `languages`.`code` LIMIT 1 -
如果主键是数字类型,可以使用来检索对象。 当使用字符串时,需要额外的注意来避免SQL注入。
db.First(&user, 10) // SELECT * FROM users WHERE id = 10;db.First(&user, "10") // SELECT * FROM users WHERE id = 10;db.Find(&users, []int{1,2,3}) // SELECT * FROM users WHERE id IN (1,2,3);如果主键是字符串(例如像uuid),查询将被写成如下:
db.First(&user, "id = ?", "1b74413f-f3b8-409f-ac47-e8c062e3472a") // SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";当目标对象有一个主键值时,将使用主键构建查询条件,例如:
var user = User{ID: 10} db.First(&user) // SELECT * FROM users WHERE id = 10;var result User db.Model(User{ID: 10}).First(&result) // SELECT * FROM users WHERE id = 10;如果对象设置了主键,条件查询将不会覆盖主键的值,而是用And连接条件。 例如:
var user = User{ID: 10} db.Where("id = ?", 20).First(&user) // SELECT * FROM users WHERE id = 10 and id = 20 ORDER BY id ASC LIMIT 1这个查询将会给出
record not found错误 所以,在你想要使用例如user这样的变量从数据库中获取新值前,需要将例如id这样的主键设置为nil。 -
检索全部对象
result := db.Find(&users) // SELECT * FROM users; -
我们可以使用
Limit方法限制查询结果的条数result := db.Limit(1).Find(&users) // SELECT * FROM users LIMIT 1; -
使用struct和map作为条件进行查询
// Struct db.Where(&User{Name: "jinzhu", Age: 20}).First(&user) // SELECT * FROM users WHERE name = "jinzhu" AND age = 20 ORDER BY id LIMIT 1;// Map db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users) // SELECT * FROM users WHERE name = "jinzhu" AND age = 20;// Slice of primary keys db.Where([]int64{20, 21, 22}).Find(&users) // SELECT * FROM users WHERE id IN (20, 21, 22); -
个人觉得这一部分和原生的MySQL查询非常地像,只是将一些条件变成了函数,另外一些条件写在
Where方法中作为内联条件,当然,内联条件也可以写在First和Find中。
更新记录
-
Save会更新所有的字段,即使字段是零值。db.First(&user)user.Name = "jinzhu 2" user.Age = 100 db.Save(&user) // UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111; -
Update可以更新单个列,Updates可以更新多列,Updates方法支持struct和map[string]interface{}参数。使用struct更新时,Updates将只更新非零字段。// 更新单列 // User 的 ID 是 `111` db.Model(&user).Update("name", "hello") // UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;// 更新多列 // 根据 `struct` 更新属性,只会更新非零值的字段 db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false}) // UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;// 根据 `map` 更新属性 db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false}) // UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111; -
在更新时可以选择或者忽略某些字段,如果需要选择某些字段,可以使用
Select;如果需要忽略某些字段,则可以使用Omit。// 选择 Map 的字段 // User 的 ID 是 `111`: db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false}) // UPDATE users SET name='hello' WHERE id=111;db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false}) // UPDATE users SET age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;// 选择 Struct 的字段(会选中零值的字段) db.Model(&user).Select("Name", "Age").Updates(User{Name: "new_name", Age: 0}) // UPDATE users SET name='new_name', age=0 WHERE id=111;// 选择所有字段(选择包括零值字段的所有字段) db.Model(&user).Select("*").Updates(User{Name: "jinzhu", Role: "admin", Age: 0})// 选择除 Role 外的所有字段(包括零值字段的所有字段) db.Model(&user).Select("*").Omit("Role").Updates(User{Name: "jinzhu", Role: "admin", Age: 0}) -
GORM 支持的 hook 包括:
BeforeSave,BeforeUpdate,AfterSave,AfterUpdate. 更新记录时将调用这些方法。func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {if u.Role == "admin" {return errors.New("admin user not allowed to update")}return } -
上述提到的方法均会调用钩子函数,如果想不调用钩子函数,则可以使用
UpdateColumn和UpdateCoulmns方法,使用方式类似Update和Updates。 -
阻止全局更新
如果你执行一个没有任何条件的批量更新,GORM 默认不会运行,并且会返回
ErrMissingWhereClause错误你可以用一些条件,使用原生 SQL 或者启用
AllowGlobalUpdate模式,例如:db.Model(&User{}).Update("name", "jinzhu").Error // gorm.ErrMissingWhereClausedb.Model(&User{}).Where("1 = 1").Update("name", "jinzhu") // UPDATE users SET `name` = "jinzhu" WHERE 1=1db.Exec("UPDATE users SET name = ?", "jinzhu") // UPDATE users SET name = "jinzhu"db.Session(&gorm.Session{AllowGlobalUpdate: true}).Model(&User{}).Update("name", "jinzhu") // UPDATE users SET `name` = "jinzhu"
删除记录
-
删除记录时需要指定主键,否则会触发批量删除
// User的ID是1 db.Delete(&user) // DELETE from users where id = 10;// User没有ID db.Delete(&user) // DELETE from users; -
当然,我们可以使用带额外条件的删除避免批量删除
db.Where("name = ?", "xiaoming").Delete(&user) // DELETE from users where name = "xiaoming"; -
使用钩子函数
对于删除操作,GORM 支持
BeforeDelete、AfterDelete等钩子函数,在删除记录时会调用这些方法。func (u *User) BeforeDelete(tx *gorm.DB) (err error) { if u.Role == "admin" { return errors.New("admin user not allowed to delete") } return } -
阻止全局删除
当你试图执行不带任何条件的批量删除时,GORM将不会运行并返回
ErrMissingWhereClause错误如果一定要这么做,你必须添加一些条件,或者使用原生SQL,或者开启
AllowGlobalUpdate模式,如下例:db.Delete(&User{}).Error // gorm.ErrMissingWhereClausedb.Delete(&[]User{{Name: "jinzhu1"}, {Name: "jinzhu2"}}).Error // gorm.ErrMissingWhereClausedb.Where("1 = 1").Delete(&User{}) // DELETE FROM `users` WHERE 1=1db.Exec("DELETE FROM users") // DELETE FROM usersdb.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{}) // DELETE FROM users -
软删除
如果模型中包含了
gorm.DeleteAt字段,则模型会自动获得软删除的能力,反之则没有软删除的能力。在有软删除能力的情况下调用
Delete函数,GORM并不会从数据库中删除该记录,而是将该记录的DeleteAt设置为当前时间,而后的一般查询方法将无法查找到此条记录。 -
查找被软删除的记录:可以使用
gorm.Unscoped()方法实现。db.Unscoped().Where("age = 21").Find(&users) -
永久删除:可以使用
Unscoped来永久删除匹配的记录// User的ID是1 db.Unscoped().Delete(&user) // DELETE FROM order WHERE id=1; -
删除标志
默认情况下,
gorm.Model使用*time.Time作为DeletedAt的字段类型,不过软删除插件gorm.io/plugin/soft_delete同时也提供其他的数据格式支持提示 当使用DeletedAt创建唯一复合索引时,你必须使用其他的数据类型,例如通过
gorm.io/plugin/soft_delete插件将字段类型定义为unix时间戳等等import "gorm.io/plugin/soft_delete"type User struct {ID uintName string `gorm:"uniqueIndex:udx_name"`DeletedAt soft_delete.DeletedAt `gorm:"uniqueIndex:udx_name"` }- Unix 时间戳:使用unix时间戳作为删除标志
import "gorm.io/plugin/soft_delete"type User struct {ID uintName stringDeletedAt soft_delete.DeletedAt }// 查询 SELECT * FROM users WHERE deleted_at = 0;// 软删除 UPDATE users SET deleted_at = /* current unix second */ WHERE ID = 1;- 使用
1/0作为 删除标志
import "gorm.io/plugin/soft_delete"type User struct {ID uintName stringIsDel soft_delete.DeletedAt `gorm:"softDelete:flag"` }// 查询 SELECT * FROM users WHERE is_del = 0;// 软删除 UPDATE users SET is_del = 1 WHERE ID = 1;- 混合模式:混合模式可以使用
0,1或者unix时间戳来标记数据是否被软删除,并同时可以保存被删除时间
type User struct {ID uintName stringDeletedAt time.TimeIsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // use `1` `0`// IsDel soft_delete.DeletedAt `gorm:"softDelete:,DeletedAtField:DeletedAt"` // use `unix second`// IsDel soft_delete.DeletedAt `gorm:"softDelete:nano,DeletedAtField:DeletedAt"` // use `unix nano second` }// 查询 SELECT * FROM users WHERE is_del = 0;// 软删除 UPDATE users SET is_del = 1, deleted_at = /* current unix second */ WHERE ID = 1;
参考文章
- [【官方文档】GORM指南](GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.)
相关文章:
【GORM学习笔记】GORM介绍以及增删改查相关操作
优缺点 优点:提高开发效率,防止SQL注入、对不熟悉SQL语句的人友好、代码统一缺点:牺牲执行能力、牺牲灵活性、弱化SQL能力 在一些小型项目上使用ORM可以大大提高开发效率,但是在一些对性能要求高得场景下,ORM可能没有…...
WebSocket在分布式环境中的局限性及解决方案
WebSocket 在分布式环境中存在一些局限性,特别是当系统需要扩展多个服务实例时,单个 WebSocket 连接的管理和消息推送就变得比较复杂。因此,必须采取一些额外的措施来确保 WebSocket 能在多个服务实例之间正确工作。 WebSocket 在分布式环境…...
SIM盾构建安全底座的可行性分析
一、背景 1.1安全需求现状 在数字化时代,信息安全面临着日益严峻的挑战。各类网络攻击手段层出不穷,如数据泄露、恶意软件攻击、网络诈骗等,给个人、企业和社会带来了巨大的损失。为了保障信息系统的安全性,需要构建一个可靠的安…...
【Java八股文】10-数据结构与算法面试篇
【Java八股文】10-数据结构与算法面试篇 数据结构与算法面试题数据结构红黑树说一下跳表说一下?LRU是什么?如何实现?布隆过滤器怎么设计?时间复杂度? 排序算法排序算法及空间复杂度 数据结构与算法面试题 数据结构 红…...
go 并发 gorouting chan channel select Mutex sync.One
goroutine // head: 前缀 index:是一个int的指针 func print(head string, index *int) {for i : 0; i < 5; i {// 指针对应的int *indexfmt.Println(*index, head, i)// 暂停1stime.Sleep(1 * time.Second)} }/* Go 允许使用 go 语句开启一个新的运…...
亲测Windows部署Ollama+WebUI可视化
一. Ollama下载 登录Ollama官网(Ollama)点击Download进行下载 如果下载很慢可用以下地址下载: https://github.com/ollama/ollama/releases/download/v0.5.7/OllamaSetup.exe 在DeepSeek官网上,你可以直接点击【model】 到达这个界面之后,…...
linux 安装启动zookeeper全过程及遇到的坑
1、下载安装zookeeper 参考文章:https://blog.csdn.net/weixin_48887095/article/details/132397448 2、启动失败 1、启动失败JAVA_HOME is not set and java could not be found in PATH 已安装 JAVA 配置了JAVA_HOME,还是报错解决方法:参考…...
策略模式Spring框架下开发实例
策略类Spring框架下开发实例 先列出策略模式下需要那些类: 策略接口 (Strategy),定义所有策略类必须遵循的行为。 具体策略类(如 ConcreteStrategyA、ConcreteStrategyB),实现不同的算法或行为。 上下文类 (Context),…...
DeepSeek模型量化
技术背景 大语言模型(Large Language Model,LLM),可以通过量化(Quantization)操作来节约内存/显存的使用,并且降低了通讯开销,进而达到加速模型推理的效果。常见的就是把Float16的浮…...
【练习】【回溯:组合:不同集合】力扣 17. 电话号码的字母组合
题目 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 示例 1: 输入:digits “2…...
分布式文件系统HDFS
一、HDFS简介 HDFS( Hadoop Distributed File System ),意为:Hadoop分布式文件系统。是Apache Hadoop核心组件之一,作为大数据生态圈最底层的分布式存储服务而存在。分布式文件系统解决大数据如何存储问题。分布式意味…...
从WebRTC到EasyRTC:嵌入式适配的视频通话SDK实现低延迟、高稳定性音视频通信
WebRTC最初是为浏览器之间的实时通信设计的,其资源需求和复杂性可能对嵌入式设备的性能提出较高要求,因此在嵌入式系统中应用时面临一些挑战: 1)资源消耗较高 CPU和内存占用:WebRTC是一个功能强大的实时通信框架&…...
WordPress自定义排序插件:Simple Custom Post Order完全指南(SEO优化版)
在WordPress建站中,文章、分类目录或页面的默认排序方式往往无法满足个性化需求。WordPress自定义排序插件:Simple Custom Post Order插件,你可以轻松实现拖拽式自定义排序,无需修改代码即可优化内容展示逻辑。本文将详细介绍这款…...
docker安装ros2 并在windows中显示docker内ubuntu系统窗口并且vscode编程
这里包括docker desktop安装ros2 humble hawkshill , 安装xserver(用来在windows中显示ubuntu中窗口), vscode安装插件连接docker并配置python的一系列方法 1.安装xserver 为了能方便的在windows中显示ubuntu内的窗口,比如rqt窗口 参考文章:https://www.cnblogs.com/larva-zhh…...
【QT中的一些高级数据结构,持续更新中...】
QT中有一些很精妙、便捷的设计,在了解这些数据的同时,我们可以学到如何更好的设计代码。本贴持续更新中,欢迎关注和收藏 一 QScopedPointer主要特点:示例代码 二 Q_DISABLE_COPY 一 QScopedPointer QScopedPointer 是 Qt 中的一种…...
简单工厂模式 (Simple Factory Pattern) 在Spring Boot 中的应用
简单工厂模式(Simple Factory Pattern)虽然不属于 GoF 23 种经典设计模式,但在实际开发中非常常用,尤其是在 Spring Boot 项目中。它提供了一种简单的方式来创建对象,将对象的创建逻辑集中到一个工厂类中。 一、简单工…...
《95015网络安全应急响应分析报告(2024)》
2025年2月,95015服务平台发布了最新一期的《95015网络安全应急响应分析报告(2024)》。报告分别从整体形势、受害者特征、攻击者特征等方面,对2024年95015平台接报的739起网络安全应急响应事件展开分析,并给出了7个年度…...
TensorFlow v2.16 Overview
TensorFlow v2.16 Overview 一、模块 Modules二、类 Classes三、函数 Functions TensorFlow v2.16.1 Overview 一、模块 Modules 模块是TensorFlow中组织代码的一种方式,将相关的功能和类封装在一起,方便用户使用和管理。每个模块都提供了特定领域的公共…...
Udp发送和接收数据(python和QT)
服务端代码 (python) import socketdef udp_server(host0.0.0.0, port12345):# 创建一个UDP套接字sock socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 绑定服务器的IP地址和端口号sock.bind((host, port))print(f"UDP服务器已启动,监听端口 {port}...&…...
element-plus 根据条件显示多选框
代码如下: <el-table :data"pager.lists" selection-change"handleSelectionChange" row-key"id" :tree-props"{ checkStrictly: true }" :cell-class-name"cellClass"> <el-table-column type"s…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
