发布帖子作业 | 青训营笔记

68 阅读3分钟
这是我参与「第五届青训营 」伴学笔记创作活动的第3天。

主要是写第二天的作业当中发布帖子的操作。由于个人水平比较差,可能实现发帖的代码不是很好。

一、server.go

server.go中添加的代码跟视频之前查询帖子的代码大致相同,区别在于这里使用的时Query方法来获取url中?之后的请求参数。如在网页当中输入localhost:8080/community/page?title=发帖&context=我要发贴,则server端能够获取title和context里面的信息

r.GET("/community/page", func(c *gin.Context){
    title := c.Query("title")
    context := c.Query("context")

    data := controller.QueryPageAdd(title, context)
    c.JSON(200, data)
})

这里cotroller.QueryPageAdd方法是跟前面cotroller.QueryPageInfo类似,判断网页返回信息是否有错误。

二、cotroller.QueryPageAdd

这里我图方便,直接把该方法放在cotorller文件夹下的query_page_info.go中。由于不像前文需要返回回复帖子,因此当发帖成功时我只需要告知用户该帖子发布成功即可。

func QueryPageAdd(title string, context string) *PageData {
    err := service.QueryPageAdd(title, context)
    if err != nil {
        return &PageData{
            Code: -1,
            Msg:  err.Error(),
        }
    }
    return &PageData{
        Code: 0,
        Msg:  "success",
        Data: title+"帖子发布成功",
    }
}

三、service.QueryPageAdd

这里我在service中新建了一个query_page_add.go,把QueryPageAdd方法放入该文件下。

package service

import (
    "encoding/json"
    "os"
    "time"
    repository "work/2/gin_web/respository"
)

func QueryPageAdd(title string, context string) error {
    TopicDao := repository.NewTopicDaoInstance()
    n := TopicDao.QueryTopicAll() + 1
    id := int64(n)
    tim := time.Now().Unix()
    topic := repository.Topic{id, title, context, tim}
    st, err := json.Marshal(topic)
    if err != nil {
        return err
    }
    file, err := os.OpenFile("data/topic", os.O_APPEND, 0)
    if err != nil {
        return err
    }
    defer file.Close()
    _, err = file.WriteString("\n")
    if err != nil {
        return err
    }
    _, err = file.Write(st)
    if err != nil {
        return err
    }
    if err := repository.Init("data/"); err != nil {
        os.Exit(-1)
    }
    return nil
}

首先,n是统计topic中有多少话题数,n+1的值作为id的结果,这样就保证本地id生成不重复。由于Topic结构体中id是int64类型,这里要转换数据类型。tim := time.Now().Unix()是获取create_time信息。

TopicDao := repository.NewTopicDaoInstance()
n := TopicDao.QueryTopicAll() + 1
id := int64(n)
tim := time.Now().Unix()

然后将结果序列化为json格式

topic := repository.Topic{id, title, context, tim}
st, err := json.Marshal(topic)
if err != nil {
    return err
}

将json格式的数据写入topic文件。

file, err := os.OpenFile("data/topic", os.O_APPEND, 0)
if err != nil {
    return err
}
defer file.Close()
_, err = file.WriteString("\n")
if err != nil {
    return err
}
_, err = file.Write(st)
if err != nil {
    return err
}

再次加载一下本地文件。如果此处不加载的话,直接搜索刚发布的帖子是搜索不到的。

if err := repository.Init("data/"); err != nil {
    os.Exit(-1)
}

四、TopicDao.QueryTopicAll()

在respository文件夹中的topic.go文件最后加上这个方法,这是统计发布话题总数的方法,方便增加新的不冲突id。

func (*TopicDao) QueryTopicAll() int  {
    return len(topicIndexMap)
}

五、测试

打开浏览器输入网址测试发帖功能。 1.jpg 然后搜索该帖子id,也就是3,可以看到帖子已经能够搜索到。 2.jpg 查看本地topic文件,能够看到刚刚发布的帖子 3.jpg 查看服务端信息 4.jpg

总结

主要说一个比较大的问题

我中间遇到过topic和post文件报错,大概是反序列化那里会返回以下的错误信息,主要是json格式有问题。我到最后也没解决,但是代码还是能跑,后面也没有返回该错误信息。只是打开两个文件还是会提示图中的错误。

invalid character '{' after top-level value

image.png

topic文件如图中所示,第二行会出现红波浪线

image.png

最后,由于个人水平有限,实现作业的方法可能非常糟糕。再加上第三题Map的并发安全问题看不懂,只能写到这里,有没有大佬能帮忙指点一下。

参考

gin框架08--Query 和 post form_gin postform_昕光xg的博客-CSDN博客