go 数据库

本文介绍了Go语言中数据库设计与操作的最佳实践,包括如何创建和关联表,使用GORM库进行CRUD操作,以及数据库设计的重要性。强调了在插入数据时自动递增ID和时间戳的处理,以及在服务层和数据访问层如何处理实体操作。同时讨论了查询策略,如分页、模糊匹配和强匹配,并展示了如何通过主键获取和更新实体。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库设计

数据库设计是底层,关乎代码质量与可阅读性,如果说你要筑起大厦,数据库就是地基。你不想来一个大换血对吧,那就要好好思考数据库的设计。
首先你得给表起一个名字。
就拿cluster和node来说,cluster里面很多node。
为确定唯一cluster,我们为cluster单独建一张表,有很多元素可以描述cluster,其中包括id,id设计为自动递增,cluster_name, status描述当前状态,ctreate_time,update_time方便查询记录,如果说我忘了cluster名字,但我可以通过时间追溯。有些字段可以在后面设计陆续添加。
node存在于cluster,通过nodeId和clusterId确定唯一一个node,有多元素可以描述node,如node_id,node_name, cluster_id绑定cluster的id,status1,status2…标记当前node的状态。有些字段可以在后面设计陆续添加。
如何将cluster的id和node里面的cluster_id关联起来?
你创建一个cluster,前端肯定会送过来一个cluster_name,把他放到数据库里面,然后你在controller里面通过cluster_name获取唯一cluster,拿到你刚创建的cluster然后取出其id,创建node的时候,再把这个cluster的id送过去。
id设计为自动递增 类型为int 长度为11 小数点为0
数字 类型为int 长度为11 小数点为0
字符串 类型为varchar 长度一般为128 小数点为0
时间 类型为timestamp 长度为0 小数点为0
浮点型的数据你就当字符串去保存,用的时候只需要把字符串转为浮点型即可。
数据库表结构的设计:关于varchar的总结
参考文章:敲码前洗一波脑 后台开发
GORM 中文文档

go mod tidy
go get github.com/jinzhu/gorm

https://jasperxu.com/Programming/Golang/GORM/
https://learnku.com/docs/gorm/v2

数据库设计与代码关联起来

数据库你想要查询记录,你忘了名字,但你可以通过时间追溯
新增字段:create_time update_time 类型: timestamp
在这里插入图片描述
你在module写:

type Cluster struct {
	Id              int		`json:"id"`
	Cluster_name    string	`json:"cluster_name"`
	Cluster_status  int		`json:"cluster_status"`
	Create_time     string	`json:"create_time"`
	Update_time     string	`json:"update_time"`
}

这样你返回的json,开头都是小写,本身是结构体的字段会根据tag解析到对应的json里面。

你在dao里面写

func (dto *ClusterDao) CreateCluster (clusterName string) models.Cluster {
	var cluster models.Cluster
    cluster.Cluster_name = clusterName
    cluster.Cluster_status = 0
    cluster.Create_time = utils.GetlocalTime()
    cluster.Update_time = utils.GetlocalTime()
    db := GetDb()
    db.Table("cluster").Create(&cluster)//&很重要,就是这个&把db查询到的数据赋值给了cluster
    return cluster
}

代码run起来
执行的语句:

INSERT INTO `cluster` (`cluster_name`,`cluster_status`,`create_time`,`update_time`) VALUES ('test42',0,'2021-06-25 15:14:09','2021-06-25 15:14:09')
insert into casbin_rule (v1,v3) values  ('/move/cdddddter/cddddrs/create','root');

在这里插入图片描述

insert数据的时候,有些数据你不写

instert的时候,有些字段你不能写,就比如时间,id,id是自动递增的。

insert into cluster (cluster_name,cluster_status) values ('lala',5);

实体操作

查看list

功能:支持分页查看,当前页和limit,模糊匹配or强匹配,模块复用。
分页查看?
没有输入当前页和limit,当前页默认为1,limit默认为n
list模块复用?
就是你一个clusterlist可以通过clusterName或者clusterId去查看。
什么时候用模糊匹配,什么时候用强匹配?
我无法精确的去定位一条数据,比如淘宝的某一家店的某一条裙子,这个时候我就会输入关键词,模糊匹配。强匹配,我非常清楚我要查找的数据,如学生管理系统,输入学号便可以查找唯一一条信息。
dao这里这么写

/*
ClusterListByClusterMsg:查看clusterList
clusterMsg:可能是clusterId,clusterName,模块复用
limitInt:页面显示多少条数据
pageInt:当前页
 */
func (dao *ClusterDao) ClusterListByClusterMsg(clusterMsg string, limitInt, pageInt int) ([]models.Cluster, int) {
	var clusters []models.Cluster
	db := GetDb()
	var total int
	clusterIdInt,err := strconv.Atoi(clusterMsg)//如果能转成数字,说明是clusterId,不行则是clusterName
	if err != nil {
		db.Table("cluster").Where("cluster_name = ?", clusterMsg).Count(&total)
		if limitInt == 0 && pageInt == 0 {//默认设置limit和page
			limitInt = 10
			pageInt = 1
		}else{//边界页的设置
			totali := limitInt * pageInt
			pageInti := total / limitInt
			if (pageInti*limitInt) < totali && totali < ((pageInti+1)*limitInt) {
				limitInt = total % limitInt
			}
			if pageInt > pageInti+1 {
				return nil, total
			}
			fmt.Print("totoai-->",totali,"total-->",total)
		}
		db.Table("cluster").Where("cluster_name = ?", clusterMsg).Limit(limitInt).Offset((pageInt - 1) * limitInt).Find(&clusters)
	}else{
		db.Table("cluster").Where("cluster_id = ?", clusterIdInt).Count(&total)
		if limitInt == 0 && pageInt == 0 {
			limitInt = 10
			pageInt = 1
		}else{
			totali := limitInt * pageInt
			pageInti := total / limitInt
			if (pageInti*limitInt) < totali && totali < ((pageInti+1)*limitInt) {
				limitInt = total % limitInt
			}
			if pageInt > pageInti+1 {
				return nil, total
			}
			fmt.Print("totoai-->",totali,"total-->",total)
		}
		db.Table("cluster").Where("cluster_id = ?", jobIdInt).Limit(limitInt).Offset((pageInt - 1) * limitInt).Find(&clusters)
	}
	return clusters, total
}

create实体

你想传实体给service
我们传值能不用指针就不用指针。

不用指针

dao–>db这里
在db里面设置clusterId自动递增,那么你往db里面插入数据,可以不用赋值给clusterId。

func (dao *ClusterDao) CreateCluster (clusterName string) models.Cluster {
	var cluster models.Cluster
    cluster.Cluster_name = clusterName
    cluster.Cluster_status = 0
    cluster.Create_time = utils.GetlocalTime()
    cluster.Update_time = utils.GetlocalTime()
    db := GetDb()
    db.Table("cluster").Create(&cluster)//&很重要,就是这个&把db查询到的数据赋值给了cluster
    return cluster
}

service这里

cluster := ms.dao.CreateCluster(clusterName)
if cluster != (models.Cluster {}) {//判断结构体是否被赋值
	fmt.Println("ClusterId--->",cluster.Cluster_id)
}

非得用指针

service这里

newCluster := &models.Cluster{//&就注定它是一个指针
	Cluster_id:      cluster_id,
	Cluster_name:    cluster_name,
	Node_num:        node_num,
}
cluster := ms.dao.CreateCluster(newCluster)
if cluster != nil {//判断指针是否成功赋值
	fmt.Println("ClusterId--->",cluster.Cluster_id)
}

dao这里

func (dao *ClusterDao) CreateCluster (cluster *models.Cluster) *models.Cluster{
        db := GetDb()
        db.Table("cluster").Create(cluster)
        return cluster
}

get实体

通过主键获取实体

func (dao *Cluster) GetClusterById(nodeIdInt, podIdInt int) models.Cluster {
	var cluster models.Cluster
    db.Table("cluster").Where("node_id = ? and pod_id = ?", nodeIdInt, podIdInt).First(&cluster)
    return cluster
}

service

func (ms *JobService)GetJobById(jobId string) models.Job {
	jobIdInt, _ := strconv.Atoi(jobId)
	return ms.dao.GetJobById(jobIdInt)
}

controller

job := jobService.GetJobById(jobId)
if job == (models.Job{}) {
	return errors.New(fmt.Sprintf("job_id=%v :数据不存在 ", jobId))
}

判断结构体是否为空

job == (models.Job{})

获取列表

controller

name := c.PostForm("name")
cluster := c.PostForm("cluster")
user := c.PostForm("user")
if self.BindAndValidate(c, &name) {
	if name == "" || cluster == "" {
		log.Error("参数错误")
	}
	data := nameSpaceService.CreateNameSpace(name,cluster,user)
	self.Resp(c, map[string]interface{}{
		"data":  data,
	})
}

service

func (ms *NameSpaceService) NameSpaceList (page, limit string) ([]models.NameSpace, int) {
	pageInt, _ := strconv.Atoi(page)
	limitInt, _ := strconv.Atoi(limit)
	data, total := ms.dao.NameSpaceList(pageInt, limitInt)
	return data, total
}

dao

func (dao *NameSpaceDao) NameSpaceList (pageInt, limitInt int) ([]models.NameSpace, int){
	var nameSpaces []models.NameSpace
	db := GetDb()
	var total int
	if limitInt == 0 && pageInt == 0 {
		limitInt = 10
		pageInt = 1
	}
	db.Table("namespace").Limit(limitInt).Offset((pageInt - 1) * limitInt).Find(&nameSpaces)
	db.Table("namespace").Count(&total)
	return nameSpaces, total
}

update实体

dao这里

func (dao *ClusterDao) UpdateClusterById (cluster models.Cluster) int64{
	cluster.Update_time = utils.GetlocalTime()
	c := db.Table("cluster").Where("node_id = ? and pod_id = ?", cluster.Node_id, cluster.Pod_id).Updates(cluster)
	return c.RowsAffected
}

service这里

cluster.Cluster_status = 1 
affected := ms.dao.UpdateClusterById (cluster)
if affected <= 0 {
	return errors.New("fail to update")
}else{
	fmt.Println("更新成功“)
}

delete实体

dao这里

func (dao *ClusterDao) DeleteClusterById(id string) int64 {
   var cluster models.Cluster
   db := GetDb()
   c := db.Table("cluster").Where("id = ?", id).Delete(&cluster)
   return c.RowsAffected
}

数据库表结构设计与优化
参考文章:数据库性能优化之表结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏小泡泡#

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值