GORM不定参数的用法最佳实践

 更新时间:2023年12月19日 11:57:27   作者:Go学堂  
这篇文章主要为大家介绍了GORM不定参数的用法最佳实践,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

这篇文章介绍本人非常喜欢的一个经验:不定参数(即…运算符)在GORM中的使用。

入门√——初级——中级——高级;本文适应入门及以上。

GORM最佳实践之不定参数的用法

Go中的不定参数

在Golang的语言特性文档中,对不定参数(… 参数)进行了专门的讲解。当在函数定义中声明了一个不定参数…T(比如 func Greeting(prefix string, who ...string))时,在函数内部就相当于有了一个类型为[]T的变量(比如在Greeting函数内,存在一个类型为[]stringwho)。

如果有下面的Greeting函数:

func Greeting(prefix string, who ...string){
 fmt.Println(prefix, len(who), who)
 if len(who) > 0 {
  Greeting(prefix, who[1:]...)
 }
}

那么可以通过Greeting("nobody")Greeting("hello:", "KiKi", "Joe", "Anna")来调用Greeting方法。对于前者用法来说,who的值为nil;对于后者用法来说,who的值为[]string{"KiKi", "Joe", "Anna"}

这里需要注意两点:

1)不能直接传入字符串切片调用Greeting("hello:", []string{"KiKi", "Joe", "Anna"}),否则编译器会报错。

2)也不能这么调用Greeting(prefix, who[1:]),必须要传入who[1:]...

这两点基本上能揭露出不定参数的本质,它更像是声明运算过程而非数据类型

①当在函数声明中使用时,做的是把函数调用时传入的参数组装成为切片(slice)

②当在函数体内部传参使用时,代表的是把切片中的数据拆组成为单个元素。恩,基本上就是这样了。

GROM中不定参数的最佳实践

说实话,在刚开始接触不定参数时,并不觉得它存在的必要性;平日里编写代码很少用到它,感觉它就像是一个玩具,或者像是语言的一个噱头。

直到最近在使用GROM的过程中,面对复杂的业务逻辑,当model层定制的方法越来越多,总觉得力不从心。直到一次review代码时,经过我们组赖老师的指点,才算给我的代码世界又打开了一扇新大门。

先看一段代码:

// Topic 话题
type Topic struct {
 gorm.Model
 Title         string    `gorm:"index"`
 Content       string    `gorm:"type:text"`
 ViewCount     int       `json:"view_count"`
 ReplyCount    int       `json:"reply_count"`
 UserID        int       `gorm:"index" json:"user_id"`
}
// QueryByUserID 根据UserID获取话题
func (t *Topic) QueryByUserID(userID int) (topics []Topic, err error) {
 db := config.DB.Where("user_id = ?", userID).Find(&topics).Error
 return
}

为了根据用户ID(UserID)获取到相应的话题(Topic),我们定义了一个QueryByUserID 的方法,为了表意这里刻意传入了一个参数;好像这个函数已经能帮我们解决model层与controller的分离。但是如果真正使用时会发现,其实这个函数有很大的局限性:它只能获取某个UserID的所有的话题,却无法实现对这个UserID下话题的进一步筛选(比如获取最近七天发布的话题)。

那么应该如何定义这个Query函数,使得我们使用时既优雅又功能强大呢?答案便是不定参数

试想,我们把QueryByUserID函数以如下的方式定义:

// QueryByUserID 根据UserID获取话题
func (t *Topic) QueryByUserID(userID int, args ...interface{}) (topics []Topic, err error) {
 db := config.DB.Where("user_id = ?", userID)
 if len(args) >= 2 {
  db = db.Where(args[0], args[1:]...)
 } else if len(args) >= 1 {
  db = db.Where(args[0])
 }
 err = db.Find(&topics).Error
 return
}

我们这里在QueryByUserID的最后强行添加了一个args不定参数,从而接受调用时传入的附加的参数。同时在函数体内,我们根据args的长度对它进行不同方式的应用,这就非常优雅地扩展了QueryByUserID的功能。根据GORM的特性,大量使用了Go的反射特性,查看源码后知道这种用法完全可行。

在添加了不定参数的情况下,再调用QueryByUserID的时候,想要进一步精细地搜索话题,就方便多了。比如,想要获取UserID为1且最近一周发布的话题,可以这么写了:

topics, err := (&Topic{}).QueryByUserID(1, "created_at > ?", time.Now().Add(-7*24*time.Hour)
// ... 其他对topics 与 err 的处理

非常灵活,好喜欢!

小结

本文对Go中的不定参数、GORM进行了简单的介绍,并就二者的优雅结合实践进行了描述。通过一个搜索某用户发表的话题(Topic)的例子介绍了使用GORM时加入不定参数后所带来的巨大灵活性。

通过这样一种结合,能够对不定参数以及GORM具有更深一步的认识,而认识的够深刻,开发起来就能更加得心应手了😆。

更多关于GORM不定参数用法的资料请关注脚本之家其它相关文章!

相关文章

  • golang通过gorm操作sqlite设置主键自增的步骤

    golang通过gorm操作sqlite设置主键自增的步骤

    这篇文章主要介绍了golang通过gorm操作sqlite设置主键自增的详细步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • 一文带你了解Go语言中锁的实现

    一文带你了解Go语言中锁的实现

    这篇文章主要带大家一起学习一下go锁和读写锁的总结文档, 主要从"参考"部分的文章结合源码学习,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-03-03
  • 详解Go语言中rand(随机数)包的使用

    详解Go语言中rand(随机数)包的使用

    在Golang中,有两个包提供了rand,分别为math/rand和crypto/rand对应两种应用场景。math/rand包实现了伪随机数生成器。也就是生成 整形和浮点型;crypto/rand包实现了用于加解密的更安全的随机数生成器。本文就来和大家详细讲讲math/rand的使用
    2022-08-08
  • go语言中range用法

    go语言中range用法

    这篇文章主要介绍了go语言中range用法,实例分析了Go语言中range的功能及使用技巧,需要的朋友可以参考下
    2015-03-03
  • Golang unsafe包中的类型和函数详解

    Golang unsafe包中的类型和函数详解

    Golang中的unsafe包用于在运行时进行低级别的操作,这些操作通常是不安全的,因为可以打破Golang的类型安全性和内存安全性,使用 unsafe包的程序可能会影响可移植性和兼容性,接下来看下unsafe包中的类型和函数
    2023-08-08
  • golang查看CPU使用率与内存的方法详解

    golang查看CPU使用率与内存的方法详解

    这篇文章主要给大家介绍了golang查看CPU使用率与内存的方法,以及拓展介绍源码里//go:指令,文中有详细的代码示例以及图文介绍,需要的朋友可以参考下
    2023-10-10
  • Go slog 日志打印最佳实践案例

    Go slog 日志打印最佳实践案例

    Go 1.21 引入了log/slog 包,为Go语言带来了原生的结构化日志解决方案,本文将深入探讨如何使用slog实现高效、可靠的日志记录,感兴趣的朋友跟随小编一起看看吧
    2025-10-10
  • Go语言类型内嵌和结构体内嵌的具体使用

    Go语言类型内嵌和结构体内嵌的具体使用

    本文主要介绍了Go语言类型内嵌和结构体内嵌的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Go select 死锁的一个细节

    Go select 死锁的一个细节

    这篇文章主要给大家分享的是Go select 死锁的一个细节,文章先是对主题提出问题,然后展开内容,感兴趣的小伙伴可以借鉴一下,希望对你有所帮助
    2021-10-10
  • Go语言创建、初始化数组的常见方式汇总

    Go语言创建、初始化数组的常见方式汇总

    这篇文章主要介绍了Go语言创建、初始化数组的常见方式,实例汇总了Go语言操作数组的常见技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02

最新评论