Gorm 数据库表迁移与表模型定义
文章目录
- 一、Docker快速创建MySQL实例
- 1.1 创建
- 1.3 创建数据库
- 二、AutoMigrate介绍与使用
- 2.1 AutoMigrate介绍
- 2.2 AutoMigrate 基本使用
- 三、模型定义
- 3.1 模型定义
- 3.2 快速增删改查
- 3.3 约定
- 3.4 gorm.Model
- 四、表模型主键、表名、列名的约定
- 4.1 主键(Primary Key)
- 4.1.1 使用 `ID` 作为主键
- 4.1.2 复合主键
- 4.2 表名(Table Name)
- 4.2.1 TableName
- 4.2.2 临时指定表名
- 4.2.3 命名策略
- 4.3 列名(Column Name)
- 4.4 时间戳跟踪
- 4.4.1 CreatedAt
- 4.4.2 UpdatedAt
- 4.4.3 DeletedAt
- 五、模型定义高级选项与标签
- 5.1 字段级权限控制
- 5.2 创建/更新时间追踪(纳秒、毫秒、秒、Time)
- 5.3 嵌入结构体
- 5.4 结构体标签(tags)
- 5.5 举个例子
一、Docker快速创建MySQL实例
1.1 创建
因为这里我们是测试学习使用,单独安装MySQL 比较费时费力,所以这里使用Docker方便快速掌握Gorm 相关知识。
如果你没有docker环境,可以参考:【一文搞定】Linux、Mac、Windows安装Docker与配置教程!
下载镜像:
docker pull mysql
运行MySQL容器:
docker run -p 3306:3306 --name mysql -v $PWD/conf/my.cnf:/etc/mysql/my.cnf -v $PWD/logs:/logs -v $PWD/data:/mysql_data -e MYSQL_ROOT_PASSWORD=123456 -d mysql
下面是对命令中参数的解释:
-
-p 3306:3306
:将容器的 3306 端口映射到主机的 3306 端口 -
-v $PWD/conf/my.cnf:/etc/mysql/my.cnf
:将主机当前目录下的conf/my.cnf
挂载到容器的/etc/mysql/my.cnf
-
-v $PWD/logs:/logs
:将主机当前目录下的logs
目录挂载到容器的/logs
-
-v $PWD/data:/mysql_data
:将主机当前目录下的data
目录挂载到容器的 /mysql_data -
-e MYSQL_ROOT_PASSWORD=123456
:初始化root
用户的密码
查看运行中的容器:
docker ps
1.3 创建数据库
首先,使用Datagrip 链接数据,接着在使用GORM前手动创建数据库db1
,执行如下SQL:
CREATE DATABASE db1;
二、AutoMigrate介绍与使用
2.1 AutoMigrate介绍
AutoMigrate
是 Gorm 提供的一个功能强大的数据库迁移工具,它可以自动创建或更新数据库表结构,使数据库的结构与 Golang 模型一致。使用 AutoMigrate
可以方便地进行数据库表的初始化和更新,而无需手动执行 SQL 语句。
2.2 AutoMigrate 基本使用
在 Gorm 中,你可以通过调用 db.AutoMigrate
方法来进行数据库表的自动迁移。以下是一个基本的使用示例:
package mainimport ("gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger""log""os""time"
)type Product struct {gorm.ModelCode stringPrice uint
}func main() {// 日志配置newLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)logger.Config{SlowThreshold: time.Second, // 慢 SQL 阈值LogLevel: logger.Info, // 日志级别为infoIgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound(记录未找到)错误Colorful: true, // 彩色打印},)dsn := "root:123456@tcp(127.0.0.1:3306)/db1?charset=utf8mb4&parseTime=True&loc=Local"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {panic(err) // 如果数据库不存在会报错}db.AutoMigrate(&Product{}) // 可以加多个log.Println("Auto Migration Completed")
}
三、模型定义
3.1 模型定义
模型是标准的 struct,由 Go 的基本数据类型、实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成
例如:
type User struct {ID uintName stringEmail *stringAge uint8Birthday *time.TimeMemberNumber sql.NullStringActivatedAt sql.NullTimeCreatedAt time.TimeUpdatedAt time.Time
}
3.2 快速增删改查
package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger""log""os""time"
)// UserInfo 用户信息
type UserInfo struct {ID uintName stringGender stringHobby string
}func main() {// 日志配置newLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)logger.Config{SlowThreshold: time.Second, // 慢 SQL 阈值LogLevel: logger.Info, // 日志级别为infoIgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound(记录未找到)错误Colorful: true, // 彩色打印},)dsn := "root:123456@tcp(127.0.0.1:3306)/db1?charset=utf8mb4&parseTime=True&loc=Local"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {panic(err) // 如果数据库不存在会报错}// 自动迁移db.AutoMigrate(&UserInfo{})u1 := UserInfo{1, "贾维斯", "男", "篮球"}u2 := UserInfo{2, "荆轲", "女", "足球"}// 创建记录db.Create(&u1)db.Create(&u2)// 查询var u = new(UserInfo)db.First(u)fmt.Printf("%#v\n", u)var uu UserInfodb.Find(&uu, "hobby=?", "足球")fmt.Printf("%#v\n", uu)// 更新db.Model(&u).Update("hobby", "双色球")// 删除db.Delete(&u)
}
3.3 约定
GORM 倾向于约定优于配置 默认情况下,GORM 使用 ID
作为主键,使用结构体名的 蛇形复数
作为表名,字段名的 蛇形
作为列名,并使用 CreatedAt
、UpdatedAt
字段追踪创建、更新时间
如果您遵循 GORM 的约定,您就可以少写的配置、代码。 如果约定不符合您的实际要求,GORM 允许你配置它们
3.4 gorm.Model
GORM 定义一个 gorm.Model
结构体,其包括字段 ID
、CreatedAt
、UpdatedAt
、DeletedAt
// gorm.Model 的定义
type Model struct {ID uint `gorm:"primaryKey"`CreatedAt time.TimeUpdatedAt time.TimeDeletedAt gorm.DeletedAt `gorm:"index"`
}
您可以将它嵌入到您的结构体中,以包含这几个字段,详情请参考 嵌入结构体
四、表模型主键、表名、列名的约定
4.1 主键(Primary Key)
4.1.1 使用 ID
作为主键
默认情况下,GORM 会使用 ID
作为表的主键。
type User struct {ID string // 默认情况下,名为 `ID` 的字段会作为表的主键Name string
}
你可以通过标签 primaryKey
将其它字段设为主键
// 将 `UUID` 设为主键
type Animal struct {ID int64UUID string `gorm:"primaryKey"`Name stringAge int64
}
4.1.2 复合主键
通过将多个字段设为主键,以创建复合主键,例如:
type Product struct {ID string `gorm:"primaryKey"`LanguageCode string `gorm:"primaryKey"`Code stringName string
}
**注意:**默认情况下,整型 PrioritizedPrimaryField
启用了 AutoIncrement
,要禁用它,您需要为整型字段关闭 autoIncrement
:
type Product struct {CategoryID uint64 `gorm:"primaryKey;autoIncrement:false"`TypeID uint64 `gorm:"primaryKey;autoIncrement:false"`
}
4.2 表名(Table Name)
GORM 使用结构体名的 蛇形命名
作为表名。对于结构体 User
,根据约定,其表名为 users
4.2.1 TableName
您可以实现 Tabler
接口来更改默认表名,例如:
type Tabler interface {TableName() string
}// TableName 会将 User 的表名重写为 `profiles`
func (User) TableName() string {return "profiles"
}
注意:
TableName
不支持动态变化,它会被缓存下来以便后续使用。想要使用动态表名,你可以使用Scopes
,例如:
func UserTable(user User) func (tx *gorm.DB) *gorm.DB {return func (tx *gorm.DB) *gorm.DB {if user.Admin {return tx.Table("admin_users")}return tx.Table("users")}
}db.Scopes(UserTable(user)).Create(&user)
4.2.2 临时指定表名
您可以使用 Table
方法临时指定表名,例如:
// 根据 User 的字段创建 `deleted_users` 表
db.Table("deleted_users").AutoMigrate(&User{})// 从另一张表查询数据
var deletedUsers []User
db.Table("deleted_users").Find(&deletedUsers)
// SELECT * FROM deleted_users;db.Table("deleted_users").Where("name = ?", "jinzhu").Delete(&User{})
// DELETE FROM deleted_users WHERE name = 'jinzhu';
查看 from 子查询 了解如何在 FROM 子句中使用子查询
4.2.3 命名策略
GORM 允许用户通过覆盖默认的命名策略
更改默认的命名约定,命名策略被用于构建: TableName
、ColumnName
、JoinTableName
、RelationshipFKName
、CheckerName
、IndexName
。查看 GORM 配置 获取详情
4.3 列名(Column Name)
根据约定,数据表的列名使用的是 struct 字段名的 蛇形命名
type User struct {ID uint // 列名是 `id`Name string // 列名是 `name`Birthday time.Time // 列名是 `birthday`CreatedAt time.Time // 列名是 `created_at`
}
您可以使用 column
标签或 命名策略
来覆盖列名
type Animal struct {AnimalID int64 `gorm:"column:beast_id"` // 将列名设为 `beast_id`Birthday time.Time `gorm:"column:day_of_the_beast"` // 将列名设为 `day_of_the_beast`Age int64 `gorm:"column:age_of_the_beast"` // 将列名设为 `age_of_the_beast`
}
4.4 时间戳跟踪
4.4.1 CreatedAt
对于有 CreatedAt
字段的模型,创建记录时,如果该字段值为零值,则将该字段的值设为当前时间
db.Create(&user) // 将 `CreatedAt` 设为当前时间user2 := User{Name: "jinzhu", CreatedAt: time.Now()}
db.Create(&user2) // user2 的 `CreatedAt` 不会被修改// 想要修改该值,您可以使用 `Update`
db.Model(&user).Update("CreatedAt", time.Now())
你可以通过将 autoCreateTime
标签置为 false
来禁用时间戳追踪,例如:
type User struct {CreatedAt time.Time `gorm:"autoCreateTime:false"`
}
4.4.2 UpdatedAt
对于有 UpdatedAt
字段的模型,更新记录时,将该字段的值设为当前时间。创建记录时,如果该字段值为零值,则将该字段的值设为当前时间
db.Save(&user) // 将 `UpdatedAt` 设为当前时间db.Model(&user).Update("name", "jinzhu") // 会将 `UpdatedAt` 设为当前时间db.Model(&user).UpdateColumn("name", "jinzhu") // `UpdatedAt` 不会被修改user2 := User{Name: "jinzhu", UpdatedAt: time.Now()}
db.Create(&user2) // 创建记录时,user2 的 `UpdatedAt` 不会被修改user3 := User{Name: "jinzhu", UpdatedAt: time.Now()}
db.Save(&user3) // 更新时,user3 的 `UpdatedAt` 会修改为当前时间
你可以通过将 autoUpdateTime
标签置为 false
来禁用时间戳追踪,例如:
type User struct {UpdatedAt time.Time `gorm:"autoUpdateTime:false"`
}
4.4.3 DeletedAt
// 只要使用了gorm.Model结构体继承,DeletedAt DeletedAt `gorm:"index"` 字段
// 执行删除是其实是update语句,并没有真正的删除
五、模型定义高级选项与标签
5.1 字段级权限控制
可导出的字段在使用 GORM 进行 CRUD 时拥有全部的权限,此外,GORM 允许您用标签控制字段级别的权限。这样您就可以让一个字段的权限是只读、只写、只创建、只更新或者被忽略
注意: 使用 GORM Migrator 创建表时,不会创建被忽略的字段
type User struct {Name string `gorm:"<-:create"` // allow read and createName string `gorm:"<-:update"` // allow read and updateName string `gorm:"<-"` // allow read and write (create and update)Name string `gorm:"<-:false"` // allow read, disable write permissionName string `gorm:"->"` // readonly (disable write permission unless it configured)Name string `gorm:"->;<-:create"` // allow read and createName string `gorm:"->:false;<-:create"` // createonly (disabled read from db)Name string `gorm:"-"` // ignore this field when write and read with structName string `gorm:"-:all"` // ignore this field when write, read and migrate with structName string `gorm:"-:migration"` // ignore this field when migrate with struct
}
5.2 创建/更新时间追踪(纳秒、毫秒、秒、Time)
GORM 约定使用 CreatedAt
、UpdatedAt
追踪创建/更新时间。如果您定义了这种字段,GORM 在创建、更新时会自动填充 当前时间
要使用不同名称的字段,您可以配置 autoCreateTime
、autoUpdateTime
标签
如果您想要保存 UNIX(毫/纳)秒时间戳,而不是 time,您只需简单地将 time.Time
修改为 int
即可
type User struct {CreatedAt time.Time // 在创建时,如果该字段值为零值,则使用当前时间填充UpdatedAt int // 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充Updated int64 `gorm:"autoUpdateTime:nano"` // 使用时间戳填纳秒数充更新时间Updated int64 `gorm:"autoUpdateTime:milli"` // 使用时间戳毫秒数填充更新时间Created int64 `gorm:"autoCreateTime"` // 使用时间戳秒数填充创建时间
}
5.3 嵌入结构体
对于匿名字段,GORM 会将其字段包含在父结构体中,例如:
type User struct {gorm.ModelName string
}
// 等效于
type User struct {ID uint `gorm:"primaryKey"`CreatedAt time.TimeUpdatedAt time.TimeDeletedAt gorm.DeletedAt `gorm:"index"`Name string
}
对于正常的结构体字段,你也可以通过标签 embedded
将其嵌入,例如:
type Author struct {Name stringEmail string
}type Blog struct {ID intAuthor Author `gorm:"embedded"`Upvotes int32
}
// 等效于
type Blog struct {ID int64Name stringEmail stringUpvotes int32
}
并且,您可以使用标签 embeddedPrefix
来为 db 中的字段名添加前缀,例如:
type Blog struct {ID intAuthor Author `gorm:"embedded;embeddedPrefix:author_"`Upvotes int32
}
// 等效于
type Blog struct {ID int64AuthorName stringAuthorEmail stringUpvotes int32
}
5.4 结构体标签(tags)
声明 model 时,tag 是可选的,GORM 支持以下 tag: tag 名大小写不敏感,但建议使用 camelCase
风格,Gorm支持以下标记:
标签名 | 说明 |
---|---|
column | 指定 db 列名 |
type | 列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如:not null 、size , autoIncrement … 像 varbinary(8) 这样指定数据库数据类型也是支持的。在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENT |
serializer | 指定如何将数据序列化和反序列化到数据库中的序列化程序,如: serializer:json/gob/unixtime |
size | 指定列数据大小/长度, 如: size:256 |
primaryKey | 指定列作为主键 |
unique | 指定列作为unique |
default | 指定列的默认值 |
precision | 指定列的精度 |
scale | 指定列的比例 |
not null | 指定列不为空 |
autoIncrement | 指定列自增 |
autoIncrementIncrement | 自动递增步长,控制连续列值之间的间隔 |
embedded | 嵌入字段 |
embeddedPrefix | 嵌入嵌入字段的字段列名前缀 |
autoCreateTime | 跟踪当前时间创建时,对于’int’字段,它将跟踪unix秒,使用值’nano/'milli 跟踪unix nano/milli秒,如: autoCreateTime:nano |
autoUpdateTime | 在创建/更新时跟踪当前时间,对于’int’字段,它将跟踪unix秒,使用值’nano/'milli 跟踪unix nano/milli秒, 如: autoUpdateTime:milli |
index | 使用选项创建索引,对多个字段使用相同的名称创建复合索引, 详情参照 Indexes |
uniqueIndex | 与’index’相同,但创建唯一索引 |
check | 创建检查约束, 如: check:age > 13 , 参照 Constraints |
<- | 设置字段的写入权限, <-:create 仅创建字段, <-:update 仅更新字段, <-:false 没有写权限, <- 创建和更新权限 |
-> | 设置字段读权限, ->:false 没有读权限 |
- | 忽略该字段, - 没有读写权限, -:migration 没有迁移权限, -:all 没有 read/write/migrate 权限 |
comment | 迁移时为字段添加注释 |
5.5 举个例子
package mainimport ("gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger""log""os""time"
)// Teacher 定义一个模型
type Teacher struct {UserId uint `gorm:"primaryKey"` // 设置主键Name string `gorm:"column:teacher_name;type:varchar(60)"` // 设置字段名和类型Gender uint `gorm:"index"` // 设置索引
}func main() {// 日志配置newLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)logger.Config{SlowThreshold: time.Second, // 慢 SQL 阈值LogLevel: logger.Info, // 日志级别为infoIgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound(记录未找到)错误Colorful: true, // 彩色打印},)dsn := "root:123456@tcp(127.0.0.1:3306)/db1?charset=utf8mb4&parseTime=True&loc=Local"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {panic(err) // 如果数据库不存在会报错}db.AutoMigrate(&Teacher{})// 如果表之前存在会修改,但是只会修改之前存在的字段,有问题// 改了字段属性,再执行AutoMigrate,字段属性会变,设置default测试看
}
相关文章:
Gorm 数据库表迁移与表模型定义
文章目录 一、Docker快速创建MySQL实例1.1 创建1.3 创建数据库 二、AutoMigrate介绍与使用2.1 AutoMigrate介绍2.2 AutoMigrate 基本使用 三、模型定义3.1 模型定义3.2 快速增删改查3.3 约定3.4 gorm.Model 四、表模型主键、表名、列名的约定4.1 主键(Primary Key&a…...
系列三、Spring Security中自定义用户名/密码
一、Spring Security中自定义用户名/密码 1.1、自定义用户名/密码 1.1.1、配置文件中配置 spring.security.user.nameroot spring.security.user.password123456 1.1.2、定义基于内存的用户 /*** Author : 一叶浮萍归大海* Date: 2024/1/11 21:50* Description:*/ Configu…...

如何顺滑使用华为云编译构建平台?
这两年平台构建服务需求越来越大,却一直苦于找不到一些指南, 这里特意写了一篇, 对在学习代码阶段和新手程序员朋友也蛮友好, 配置真的也不难, 也特别适合想尝试从0到1做个APP的朋友了。 以华为云的CodeArts Build为例…...

查看Linux磁盘空间
(1)、该命令会列出当前系统所有挂载的文件系统以及它们的使用情况,包括总容量、已用空间、可用空间、使用百分比等信息 df -h如果查看某一个文件夹的,可以 df -h folderName (2)、计算指定目录下所有文件和子目录所占用的磁盘空间大小,并以人类可读的格…...

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷⑩
2023年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷10 目录 需要竞赛软件包环境以及备赛资源可私信博主!!! 2023年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷10 模块…...

vim基本操作命令
一、vi简介 vi是“Visual interface”的简称,它在Linux上的地位就仿佛Edit程序在DOS上一样。它可以执行输出、删除、查找、替换、块操作等众多文本操作,而且用户可以根据自己的需要对其进行定制。Vi不是一个排版程序,它不象Word或WPS那样可以…...
mybatis-plus实现真正的批量插入
1、安装依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-extension</artifactId><version>3.5.3.2</version></dependency>版本与mybatis-plus一致 2、编写sql注入器 package com.example.answe…...

pytorch12:GPU加速模型训练
目录 1、CPU与GPU2、数据迁移至GPU2.1 to函数使用方法 3、torch.cuda常用方法4、多GPU并行运算4.1 torch.nn.DataParallel4.2 torch.distributed加速并行训练 5、gpu总结 1、CPU与GPU CPU(Central Processing Unit, 中央处理器):主要包括控制…...
P1603 斯诺登的密码题解
题目 (1)找出句子中所有用英文表示的数字(≤20),列举在下: 正规:one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty 非正规…...

YOLOv8 + openVINO 多线程数据读写顺序处理
多线程数据读写顺序处理 一个典型的生产者-消费者模型,在这个模型中,多个工作线程并行处理从共享队列中获取的数据,并将处理结果以保持原始顺序的方式放入另一个队列。 多线程处理模型,具体细节如下: 1.数据:数据里必…...

端到端自动驾驶
自动驾驶主要流程:感知->预测->规划 预测是预测周围目标(车、行人、动物等)的轨迹,规划是规划自车的运动轨迹。 UniAD[CVPR 2023]: 使用transformer架构,统一自动驾驶流程,完成所有检测,…...

Developer Tools for Game Creator 1
插件包含: 持久世界时间管理系统 单击以生成对象或预设 游戏内调试控制台 游戏内事件控制台 控制台管理控制 命令模板脚本 游戏内屏幕截图 低分辨率和高分辨率图像 缩略图生成 移动支持 使用Game Creator Action或拖放来激活和控制组件,无需编码。 通过此资产,您可以获得: …...

软件测试|好用的pycharm插件推荐(三)——Rainbow Brackets
简介 我们平时写代码的时候,括号是让我们非常头疼的地方,特别是代码逻辑很多,层层嵌套的情况。 一眼很难看出,代码是从哪个括号开始,到哪个反括号结束的。这个时候要是有一款工具能够让我们一眼就看出代码从哪个括号开…...

MyBatisPlus学习二:常用注解、条件构造器、自定义sql
常用注解 基本约定 MybatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息。可以理解为在继承BaseMapper 要指定对应的泛型 public interface UserMapper extends BaseMapper<User> 实体类中,类名驼峰转下划线作为表名、名为id的…...

深入理解C#中的引用类型、引用赋值以及 `ref` 关键字
深入理解C#中的引用类型、引用赋值以及 ref 关键字 在C#编程中,理解引用类型、引用赋值以及 ref 关键字的使用对于编写高效、可靠的代码至关重要。本文将深入探讨这些概念,帮助您更好地理解C#的工作原理。 引用类型简介 在C#中,所有的类型都…...

【算法提升】LeetCode每五日一总结【01/01--01/05】
文章目录 LeetCode每五日一总结【01/01--01/05】2023/12/31今日数据结构:二叉树的前/中/后 序遍历<非递归> 2024/01/01今日数据结构:二叉树的 前/中/后 序遍历 三合一代码<非递归>今日数据结构:二叉树的 前/中/后 序遍历 三合一代…...
linux下驱动学习—平台总线 (3)
platform 设备驱动 在设备驱动模型中, 引入总线的概念可以对驱动代码和设备信息进行分离。但是驱动中总线的概念是软件层面的一种抽象,与我们SOC中物理总线的概念并不严格相等: 物理总线:芯片与各个功能外设之间传送信息的公共通…...

【leetcode】字符串中的第一个唯一字符
题目描述 给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 。 用例 示例 1: 输入: s “leetcode” 输出: 0 示例 2: 输入: s “loveleetcode” 输出: 2 示例 3: 输入: s “aabb”…...
Serverless与Kubernetes(K8s)的区别、优缺点及应用场景
Serverless与Kubernetes(K8s)的区别 架构模型 Serverless是一种基于事件驱动的计算模型,它允许开发者编写应用程序时无需关心底层的基础设施。在Serverless架构中,云服务提供商会负责管理服务器、操作系统、运行时环境等基础设施&…...

参数小,性能强!开源多模态模型—TinyGPT-V
安徽工程大学、南洋理工大学和理海大学的研究人员开源了多模态大模型——TinyGPT-V。 TinyGPT-V以微软开源的Phi-2作为基础大语言模型,同时使用了视觉模型EVA实现多模态能力。尽管TinyGPT-V只有28亿参数,但其性能可以媲美上百亿参数的模型。 此外&…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...

实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...