import (
"github.com/Moonlight-Zhao/go-project-example/util"
"sync"
"time"
)
type Topic struct {
Id int64 `gorm:"column:id"`
UserId int64 `gorm:"column:user_id"`
Title string `gorm:"column:title"`
Content string `gorm:"column:content"`
CreateTime time.Time `gorm:"column:create_time"`
}
func (Topic) TableName() string {
return "topic"
}
type TopicDao struct {
}
var topicDao *TopicDao
var topicOnce sync.Once
func NewTopicDaoInstance() *TopicDao {
topicOnce.Do(
func() {
topicDao = &TopicDao{}
})
return topicDao
}
func (*TopicDao) QueryTopicById(id int64) (*Topic, error) {
var topic Topic
err := db.Where("id = ?", id).Find(&topic).Error
if err != nil {
util.Logger.Error("find topic by id err:" + err.Error())
return nil, err
}
return &topic, nil
}
当前代码定义了一个名为 Topic 的结构体,它包含了与主题相关的字段,如 Id、UserId、Title、Content 和 CreateTime。每个字段都有相应的标签,用于指定在数据库中对应的列名。此外,还定义了一个名为 TableName 的方法,它返回 Topic 结构体对应的数据库表名。
代码中还定义了一个名为 TopicDao 的结构体,它目前没有任何方法或字段。这个结构体可能是用于封装与 Topic 相关的数据库操作。
接下来,代码使用了一个名为 topicOnce 的 sync.Once 实例和一个名为 topicDao 的 TopicDao 类型指针。sync.Once 用于确保某个操作只执行一次,即使在多个 goroutine 中也是如此。这里的操作是初始化 topicDao 实例。
NewTopicDaoInstance 函数使用 sync.Once 来保证只创建一个 TopicDao 实例。这个函数返回一个 TopicDao 类型的指针。
最后,QueryTopicById 方法接受一个 int64 类型的参数 id,并使用 GORM 库来查询数据库中 id 字段等于传入参数的 Topic 记录。如果查询成功,它将返回一个包含查询结果的 Topic 实例和一个 nil 错误。如果查询失败,它将记录错误信息并返回 nil 和错误对象。
总的来说,这段代码是一个简单的 Go 语言示例,展示了如何使用结构体、方法、sync.Once 和 GORM 库来实现一个单例模式的数据库访问层。
感想
单例模式的作用
可以定义了一个名为 TopicDao 的空结构体,没有任何方法或字段。这个结构体用于封装与 Topic 相关的函数和操作
import (
"errors"
"github.com/Moonlight-Zhao/go-project-example/repository"
"time"
"unicode/utf8"
)
func PublishPost(topicId, userId int64, content string) (int64, error) {
return NewPublishPostFlow(topicId, userId, content).Do()
}
func NewPublishPostFlow(topicId, userId int64, content string) *PublishPostFlow {
return &PublishPostFlow{
userId: userId,
content: content,
topicId: topicId,
}
}
type PublishPostFlow struct {
userId int64
content string
topicId int64
postId int64
}
func (f *PublishPostFlow) Do() (int64, error) {
if err := f.checkParam(); err != nil {
return 0, err
}
if err := f.publish(); err != nil {
return 0, err
}
return f.postId, nil
}
func (f *PublishPostFlow) checkParam() error {
if f.userId <= 0 {
return errors.New("userId id must be larger than 0")
}
if utf8.RuneCountInString(f.content) >= 500 {
return errors.New("content length must be less than 500")
}
return nil
}
func (f *PublishPostFlow) publish() error {
post := &repository.Post{
ParentId: f.topicId,
UserId: f.userId,
Content: f.content,
CreateTime: time.Now(),
}
if err := repository.NewPostDaoInstance().CreatePost(post); err != nil {
return err
}
f.postId = post.Id
return nil
}
当前代码是一个名为 PublishPost 的函数,它用于发布帖子。这个函数接受三个参数:topicId(主题ID),userId(用户ID),和 content(帖子内容)。函数的返回值是一个 int64 类型的 postId(帖子ID)和一个 error 类型的错误对象。
函数的执行流程如下:
- 调用
NewPublishPostFlow函数创建一个PublishPostFlow结构体实例,传入topicId,userId和content参数。 - 调用
PublishPostFlow实例的Do方法,执行发布帖子的流程。 - 在
Do方法中,首先调用checkParam方法检查参数是否合法。如果参数不合法,返回错误。 - 如果参数合法,调用
publish方法发布帖子。在publish方法中,创建一个Post结构体实例,设置帖子的相关属性,然后调用NewPostDaoInstance函数创建一个PostDao实例,并调用其CreatePost方法将帖子保存到数据库。 - 如果帖子保存成功,返回帖子ID和
nil错误。如果保存失败,返回nil和错误对象。
总结来说,PublishPost 函数通过 PublishPostFlow 结构体和 PostDao 实例来实现帖子的发布功能,包括参数检查和数据库操作。
感想
封装了一个 PublishPostFlow 结构体,并用其中的Do()方法,引用结构体方法来实现
repository.NewPostDaoInstance().CreatePost(post)明白了可以调用上一个包的东西