使用Beego和MySQL实现帖子和评论的应用,并进行接口测试(附源码和代码深度剖析)

news2024/12/28 11:14:07

文章目录

  • 小项目介绍
  • 源码分析
    • main.go
    • router.go
    • models/user.go
    • models/Post.go
    • models/comment.go
    • controllers/post.go
    • controllers/comment.go
  • 接口测试
    • 测试增加帖子
    • 测试查看帖子
    • 测试增加评论
    • 测试查看评论

小项目介绍

经过对需求的分析,我增加了一些额外的东西,比如增加了user用户,因为我考虑到帖子或者是评论(跟回帖差不多)都会有作者,主要的功能有增加帖子、查看所有或单个帖子、增加评论、查看某个帖子的所有评论或单个评论。数据我是将它存在数据库中,而不是内存中。

首先终端运行bee api apiname新建一个beego项目,api命令可以让我们很方便地实现API应用。

image.png

在IDE打开生成的项目,并配置app.conf中关于数据库的部分。

数据库我选用MySQLapp.conf文件如下:

appname = post
httpport = 8080
runmode = dev
autorender = false
copyrequestbody = true
EnableDocs = true

username = root
password =
host = 127.0.0.1
port = 3306
database = post

数据库命名为post,因此我先在Navicat软件中创建该数据库,编码规则为utf8mb4,以方便后续操作。

image.png

最后的项目结构如下:

image.png

conf文件夹包含项目配置文件,controllers文件夹负责处理业务逻辑,models文件夹与数据库模型相关,routers文件夹包含项目的所有路由,tests文件夹含有测试文件,而在本篇文章我打算使用postman来进行接口测试。

源码分析

接下来对每个文件进行源码展示与分析。

main.go

package main

import (
    "fmt"
    "github.com/beego/beego/v2/client/orm"
    "github.com/beego/beego/v2/server/web"
    _ "github.com/go-sql-driver/mysql"
    "github.com/prometheus/common/log"
    _ "post/models"
    _ "post/routers"
)

func init() {
    username, _ := web.AppConfig.String("username")
    password, _ := web.AppConfig.String("password")
    host, _ := web.AppConfig.String("host")
    port, _ := web.AppConfig.String("port")
    database, _ := web.AppConfig.String("database")

    datasource := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&loc=Local", username, password, host, port, database)
    err := orm.RegisterDataBase("default", "mysql", datasource)
    if err != nil {
       log.Fatal(err)
    }

    err = orm.RunSyncdb("default", false, true)
    if err != nil {
       log.Fatal(err)
    }

}

func main() {
    orm.RunCommand()
    web.Run()
}
  1. 导入包: 代码开始时导入了一些必要的包:
  • “fmt” 用于格式化的输入输出。
  • “github.com/beego/beego/v2/client/orm” 是 Beego ORM 包。
  • “github.com/beego/beego/v2/server/web” 是 Beego Web 服务器包。
  • “github.com/go-sql-driver/mysql” 是 MySQL 数据库驱动。
  • “github.com/prometheus/common/log” 用于日志记录。
  • “post/models” 和 “post/routers” 用于导入模型和路由配置。 (这些仅用于副作用,因为它们可能在初始化过程中注册模型和路由。)
  1. init() 函数: init() 函数在程序启动时自动调用。在这个函数中,代码使用 Beego 配置读取了 MySQL 数据库的凭据(用户名、密码、主机、端口和数据库名),并构建了连接数据库的数据源字符串。datasource 变量包含连接字符串。

然后,代码使用 orm.RegisterDataBase() 函数将 MySQL 数据库注册到 Beego ORM 中。此函数的参数为:

  • “default”:这是数据库连接的别名,在应用的其他部分中会以 “default” 作为引用。
  • “mysql”:MySQL 数据库的驱动名称。
  • datasource:之前构建的数据源字符串。

接下来,调用 orm.RunSyncdb() 函数,根据 post/models 包中的模型定义来创建数据库表。此函数的参数为:

  • “default”:用于创建表的数据库连接别名。
  • false:此参数指示是否在创建新表之前删除现有表。在这里设置为 false,表示不会删除现有表。
  • true:此参数指示是否在表不存在时创建表。设置为 true,所以会在表不存在时创建它们。
  1. main() 函数: main() 函数是程序的入口点。它调用了两个函数:
  • orm.RunCommand():此函数解析与 ORM 相关的命令行参数,并执行相应的操作。例如,它可以根据 ORM 配置生成模型文件、控制器或数据库迁移脚本。
  • web.Run():此函数启动 Beego Web 服务器,并处理传入的 HTTP 请求。

该应用程序会监听传入的 HTTP 请求,默认端口为 8080,将其路由到适当的控制器动作,这些动作在路由配置中定义。

router.go

package routers

import (
    "github.com/beego/beego/v2/server/web"
    "post/controllers"
)

func init() {
    web.Router("/post", &controllers.PostController{}, "get:PostList;post:PostAdd")
    web.Router("/comment", &controllers.CommentController{}, "get:CommentList;post:CommentAdd")

}

这段代码定义了 Beego 框架中的路由配置。路由配置用于将不同的 URL 路径映射到相应的控制器和处理函数上。

让我们来解释一下这段代码:

  1. 导入包: 代码中导入了两个包:
  • “github.com/beego/beego/v2/server/web”:这是 Beego 框架的 Web 服务器包,用于设置路由和处理 HTTP 请求。
  • “post/controllers”:这是自定义的控制器包,用于处理不同的请求。
  1. init() 函数: init() 函数在该包被导入时自动调用。在此函数中,我们定义了两个路由规则:
  • 第一个路由规则:

    web.Router("/post", &controllers.PostController{}, "get:PostList;post:PostAdd")
    
    • web.Router("/post":这表示将路径 “/post” 映射到后面的控制器和处理函数上。
    • &controllers.PostController{}:这是 PostController 的实例,用于处理与 “/post” 路径相关的请求。
    • "get:PostList;post:PostAdd":这是路由规则字符串,它指定了请求方法和对应的处理函数。在这里,“get:PostList” 表示将 GET 请求映射到 PostControllerPostList 方法上,“post:PostAdd” 表示将 POST 请求映射到 PostControllerPostAdd 方法上。
  • 第二个路由规则:

    web.Router("/comment", &controllers.CommentController{}, "get:CommentList;post:CommentAdd")
    
    • web.Router("/comment":这表示将路径 “/comment” 映射到后面的控制器和处理函数上。
    • &controllers.CommentController{}:这是 CommentController 的实例,用于处理与 “/comment” 路径相关的请求。
    • "get:CommentList;post:CommentAdd":这是路由规则字符串,指定了请求方法和对应的处理函数。“get:CommentList” 表示将 GET 请求映射到 CommentControllerCommentList 方法上,“post:CommentAdd” 表示将 POST 请求映射到 CommentControllerCommentAdd 方法上。

models/user.go

package models

import (
    "github.com/beego/beego/v2/client/orm"
    "time"
)

type User struct {
    Id         int        `orm:"pk;auto"`
    Name       string     `orm:"description(用户名)"`
    Posts      []*Post    `orm:"reverse(many)"`
    Comments   []*Comment `orm:"reverse(many)"`
    CreateTime time.Time  `orm:"auto_now_add;type(datetime);description(创建时间)"`
}

func init() {
    // 需要在init中注册定义的model
    orm.RegisterModel(new(User), new(Post), new(Comment))
}

这段代码定义了三个数据模型:User、Post、和Comment,并使用 Beego ORM 包进行了注册。

让我们逐步解释这段代码:

  1. 导入包: 代码中导入了两个包:
  • “github.com/beego/beego/v2/client/orm”:这是 Beego ORM 包,用于进行数据库操作和对象关系映射。
  • “time”:这是 Go 标准库中的时间包,用于处理时间相关的操作。
  1. User 结构体: 定义了名为 User 的结构体,表示数据库中的用户表。
  • Id int orm:"pk;auto":Id 字段是主键,“pk” 表示主键,“auto” 表示自增。
  • Name string orm:"description(用户名)":Name 字段是用户名字段,“description(用户名)” 是对字段的描述。
  • Posts []*Post orm:"reverse(many)":Posts 是用户与帖子之间的一对多反向关系,表示一个用户可以有多个帖子。
  • Comments []*Comment orm:"reverse(many)":Comments 是用户与评论之间的一对多反向关系,表示一个用户可以有多个评论。
  • CreateTime time.Time orm:"auto_now_add;type(datetime);description(创建时间)":CreateTime 字段是创建时间字段,“auto_now_add” 表示在创建新记录时自动设置为当前时间,“type(datetime)” 表示字段类型为 datetime,“description(创建时间)” 是对字段的描述。
  1. init() 函数: init() 函数在包被导入时自动调用。在这里,代码调用 orm.RegisterModel() 函数来注册定义的模型,以便在应用程序运行时与数据库表进行映射。
  • orm.RegisterModel(new(User), new(Post), new(Comment)):注册 User、Post、和 Comment 三个模型,这样 Beego ORM 就知道它们的结构和与数据库表之间的映射关系。

models/Post.go

package models

import "time"

type Post struct {
    Id         int        `orm:"pk;auto"`
    Title      string     `orm:"description(帖子标题)"`
    Content    string     `orm:"size(4000);description(帖子内容)"`
    ReadNum    int        `orm:"description(阅读量);default(0)"`
    Author     *User      `orm:"rel(fk);description(作者)"`
    Comments   []*Comment `orm:"reverse(many);description(评论)"`
    CreateTime time.Time  `orm:"auto_now_add;type(datetime);description(创建时间)"`
}

func PostData(posts []Post) (data []interface{}) {

    for _, post := range posts {
       data = append(data, map[string]interface{}{
          "id":          post.Id,
          "title":       post.Title,
          "author":      post.Author.Name,
          "content":     post.Content,
          "read_num":    post.ReadNum,
          "create_time": post.CreateTime.Format("2006-1-2 15:04"),
       })
    }
    return
}

这段代码定义了一个名为 Post 的数据模型,并提供了一个函数 PostData,用于将 Post 结构体的数据转换为特定格式的数据。

让我们来逐步解释这段代码:

  1. Post 结构体: Post 是一个数据模型,表示数据库中的帖子表。
  • Id int orm:"pk;auto"Id 字段是主键,“pk” 表示主键,“auto” 表示自增长。
  • Title string orm:"description(帖子标题)"Title 字段是帖子标题字段,“description(帖子标题)” 是对字段的描述。
  • Content string orm:"size(4000);description(帖子内容)"Content 字段是帖子内容字段,“size(4000)” 表示字段最大长度为 4000,“description(帖子内容)” 是对字段的描述。
  • ReadNum int orm:"description(阅读量);default(0)"ReadNum 字段是阅读量字段,“description(阅读量)” 是对字段的描述,“default(0)” 表示默认值为 0。
  • Author *User orm:"rel(fk);description(作者)"Author 字段是一个指向 User 结构体的外键关联字段,表示这篇帖子的作者。
  • Comments []*Comment orm:"reverse(many);description(评论)"Comments 字段是一个指向 Comment 结构体的一对多反向关联字段,表示这篇帖子可以有多条评论。
  • CreateTime time.Time orm:"auto_now_add;type(datetime);description(创建时间)"CreateTime 字段是创建时间字段,“auto_now_add” 表示在创建新记录时自动设置为当前时间,“type(datetime)” 表示字段类型为 datetime,“description(创建时间)” 是对字段的描述。
  1. PostData 函数: PostData 函数接收一个 []Post 切片,该切片包含多个 Post 结构体。函数的目的是将这些结构体的数据转换为一个特定格式的切片 []interface{}

在函数中,通过遍历 posts 切片,将每个 Post 结构体的字段值存储在一个 map[string]interface{} 中,然后将该 map 添加到 data 切片中。

具体转换的字段如下:

  • “id”: 帖子的 Id 字段。
  • “title”: 帖子的 Title 字段。
  • “author”: 帖子的作者的姓名,通过访问 post.Author.Name 获取。
  • “content”: 帖子的 Content 字段。
  • “read_num”: 帖子的 ReadNum 字段。
  • “create_time”: 帖子的 CreateTime 字段,格式化为形式类似 “2006-1-2 15:04” 的字符串。

最后,函数返回转换后的 data 切片。

models/comment.go

package models

import "time"

type Comment struct {
    Id         int       `orm:"pk;auto"`
    Content    string    `orm:"size(4000);description(评论内容)"`
    Post       *Post     `orm:"rel(fk);description(帖子外键)"`
    Author     *User     `orm:"rel(fk);description(评论人)"`
    CreateTime time.Time `orm:"auto_now_add;type(datetime);description(创建时间)"`
}

func CommentData(comments []Comment) (data []interface{}) {

    for _, comment := range comments {
       data = append(data, map[string]interface{}{
          "id":          comment.Id,
          "author":      comment.Author.Name,
          "content":     comment.Content,
          "create_time": comment.CreateTime.Format("2006-1-2 15:04"),
       })
    }
    return
}

这段代码定义了一个名为 Comment 的数据模型,并提供了一个函数 CommentData,用于将 Comment 结构体的数据转换为特定格式的数据。

让我们逐步解释这段代码:

  1. Comment 结构体: Comment 是一个数据模型,表示数据库中的评论表。
  • Id int orm:"pk;auto"Id 字段是主键,“pk” 表示主键,“auto” 表示自增长。
  • Content string orm:"size(4000);description(评论内容)"Content 字段是评论内容字段,“size(4000)” 表示字段最大长度为 4000,“description(评论内容)” 是对字段的描述。
  • Post *Post orm:"rel(fk);description(帖子外键)"Post 字段是一个指向 Post 结构体的外键关联字段,表示该评论所属的帖子。
  • Author *User orm:"rel(fk);description(评论人)"Author 字段是一个指向 User 结构体的外键关联字段,表示该评论的作者。
  • CreateTime time.Time orm:"auto_now_add;type(datetime);description(创建时间)"CreateTime 字段是创建时间字段,“auto_now_add” 表示在创建新记录时自动设置为当前时间,“type(datetime)” 表示字段类型为 datetime,“description(创建时间)” 是对字段的描述。
  1. CommentData 函数: CommentData 函数接收一个 []Comment 切片,该切片包含多个 Comment 结构体。函数的目的是将这些结构体的数据转换为一个特定格式的切片 []interface{}

在函数中,通过遍历 comments 切片,将每个 Comment 结构体的字段值存储在一个 map[string]interface{} 中,然后将该 map 添加到 data 切片中。

具体转换的字段如下:

  • “id”: 评论的 Id 字段。
  • “author”: 评论的作者的姓名,通过访问 comment.Author.Name 获取。
  • “content”: 评论的 Content 字段。
  • “create_time”: 评论的 CreateTime 字段,格式化形式类似为 “2006-1-2 15:04” 的字符串。

最后,函数返回转换后的 data 切片。

controllers/post.go

package controllers

import (
    "github.com/beego/beego/v2/client/orm"
    "github.com/beego/beego/v2/server/web"
    "post/models"
)

type PostController struct {
    web.Controller
}

func (c *PostController) PostList() {
    o := orm.NewOrm()

    postId, _ := c.GetInt("post_id", 0)
    if postId == 0 {
       var posts []models.Post
       if _, err := o.QueryTable(new(models.Post)).RelatedSel().All(&posts); err == nil {
          c.Data["json"] = map[string]interface{}{"code": 200, "count": len(posts), "data": models.PostData(posts)}
          c.ServeJSON()
       } else {
          c.Data["json"] = map[string]interface{}{"code": 400, "msg": "获取帖子列表失败"}
          c.ServeJSON()
       }
    } else {
       var post models.Post

       qs := o.QueryTable(new(models.Post)).Filter("id", postId)

       if err := qs.RelatedSel().One(&post); err == nil {
          // 阅读数+1
          qs.Update(orm.Params{"read_num": post.ReadNum + 1})

          c.Data["json"] = map[string]interface{}{"code": 200, "data": models.PostData([]models.Post{post})}
          c.ServeJSON()
       } else {
          c.Data["json"] = map[string]interface{}{"code": 400, "msg": "获取帖子失败"}
          c.ServeJSON()
       }
    }
}

func (c *PostController) PostAdd() {
    title := c.GetString("title")
    content := c.GetString("content")
    author := c.GetString("author_id")
    if title == "" || content == "" || author == "" {
       c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
       c.ServeJSON()
       return
    }

    o := orm.NewOrm()
    user := models.User{}
    if err := o.QueryTable(new(models.User)).Filter("id", author).One(&user); err != nil {
       c.Data["json"] = map[string]interface{}{"code": 400, "msg": "用户不存在"}
       c.ServeJSON()
       return
    }

    post := models.Post{
       Title:   title,
       Content: content,
       Author:  &user,
    }

    if _, err := o.Insert(&post); err == nil {
       c.Data["json"] = map[string]interface{}{"code": 200, "msg": "添加帖子成功"}
    } else {
       c.Data["json"] = map[string]interface{}{"code": 400, "msg": "添加帖子失败"}
    }

    c.ServeJSON()

}

这段代码定义了一个名为 PostController 的控制器,并实现了两个处理函数:PostList()PostAdd(),用于处理与帖子相关的请求。

让我们逐步解释这段代码:

  1. 导入包: 代码中导入了一些包:
  • “github.com/beego/beego/v2/client/orm”:这是 Beego ORM 包,用于进行数据库操作和对象关系映射。
  • “github.com/beego/beego/v2/server/web”:这是 Beego Web 服务器包,用于处理请求和响应。
  • “post/models”:这是自定义的 models 包,用于操作数据模型。
  1. PostController 结构体: PostController 是一个控制器结构体,继承了 web.Controller
  2. PostList() 函数: PostList() 是一个处理函数,用于获取帖子列表或单个帖子详情。
  • 首先,通过 orm.NewOrm() 创建一个新的 ORM 对象 o,用于进行数据库操作。
  • 检查是否有 post_id 参数,如果没有,则返回帖子列表。在数据库中查询所有的帖子,并使用 models.PostData() 函数将帖子列表转换成特定格式的数据。
  • 如果有 post_id 参数,表示要获取单个帖子的详情。在数据库中查询该 post_id 对应的帖子,并将其阅读数加 1,然后将帖子详情转换成特定格式的数据。
  • 最后,将处理结果以 JSON 格式返回。
  1. PostAdd() 函数: PostAdd() 是一个处理函数,用于添加新的帖子。
  • 获取请求参数 titlecontentauthor_id,如果这些参数有为空的情况,则返回参数错误。
  • 创建一个新的 ORM 对象 o,用于进行数据库操作。
  • 根据 author_id 查询对应的用户,如果用户不存在,则返回用户不存在的错误。
  • 创建一个新的 Post 结构体,填充帖子的标题、内容和作者。
  • 将帖子插入数据库,如果插入成功,则返回添加帖子成功的消息,否则返回添加帖子失败的消息。
  • 最后,将处理结果以 JSON 格式返回。

controllers/comment.go

package controllers

import (
    "github.com/beego/beego/v2/client/orm"
    "github.com/beego/beego/v2/server/web"
    "post/models"
)

type CommentController struct {
    web.Controller
}

func (c *CommentController) CommentList() {
    o := orm.NewOrm()

    postId, _ := c.GetInt("post_id", 0)
    commentId, _ := c.GetInt("comment_id", 0)
    if postId == 0 {
       c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
       c.ServeJSON()
       return
    }
    if commentId == 0 {
       var comments []models.Comment
       if _, err := o.QueryTable(new(models.Comment)).RelatedSel().Filter("post_id", postId).All(&comments); err == nil {
          c.Data["json"] = map[string]interface{}{"code": 200, "count": len(comments), "data": models.CommentData(comments)}
          c.ServeJSON()
       } else {
          c.Data["json"] = map[string]interface{}{"code": 400, "msg": "获取评论列表失败"}
          c.ServeJSON()
       }
    } else {
       var comment models.Comment

       if err := o.QueryTable(new(models.Comment)).Filter("id", commentId).RelatedSel().One(&comment); err == nil {

          c.Data["json"] = map[string]interface{}{"code": 200, "data": models.CommentData([]models.Comment{comment})}
          c.ServeJSON()
       } else {
          c.Data["json"] = map[string]interface{}{"code": 400, "msg": "获取评论失败"}
          c.ServeJSON()
       }
    }
}

func (c *CommentController) CommentAdd() {
    postId := c.GetString("post_id")
    content := c.GetString("content")
    author := c.GetString("author_id")
    if postId == "" || content == "" || author == "" {
       c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
       c.ServeJSON()
       return
    }

    o := orm.NewOrm()
    user := models.User{}
    post := models.Post{}
    if err := o.QueryTable(new(models.User)).Filter("id", author).One(&user); err != nil {
       c.Data["json"] = map[string]interface{}{"code": 400, "msg": "用户不存在"}
       c.ServeJSON()
       return
    }
    if err := o.QueryTable(new(models.Post)).Filter("id", postId).One(&post); err != nil {
       c.Data["json"] = map[string]interface{}{"code": 400, "msg": "帖子不存在"}
       c.ServeJSON()
       return
    }

    comment := models.Comment{
       Content: content,
       Post:    &post,
       Author:  &user,
    }

    if _, err := o.Insert(&comment); err == nil {
       c.Data["json"] = map[string]interface{}{"code": 200, "msg": "添加评论成功"}
    } else {
       c.Data["json"] = map[string]interface{}{"code": 400, "msg": "添加评论失败"}
    }

    c.ServeJSON()
}

这段代码定义了一个名为 CommentController 的控制器,并实现了两个处理函数:CommentList()CommentAdd(),用于处理与评论相关的请求。

让我们逐步解释这段代码:

  1. 导入包: 代码中导入了一些包:
  • “github.com/beego/beego/v2/client/orm”:这是 Beego ORM 包,用于进行数据库操作和对象关系映射。
  • “github.com/beego/beego/v2/server/web”:这是 Beego Web 服务器包,用于处理请求和响应。
  • “post/models”:这是自定义的 models 包,用于操作数据模型。
  1. CommentController 结构体: CommentController 是一个控制器结构体,继承了 web.Controller
  2. CommentList() 函数: CommentList() 是一个处理函数,用于获取评论列表或单个评论详情。
  • 首先,通过 orm.NewOrm() 创建一个新的 ORM 对象 o,用于进行数据库操作。
  • 检查是否有 post_id 参数和 comment_id 参数,如果 post_id 参数为空,则返回参数错误。
  • 如果 comment_id 参数为空,则返回帖子的评论列表。在数据库中查询 post_id 对应的帖子的所有评论,并使用 models.CommentData() 函数将评论列表转换成特定格式的数据。
  • 如果 comment_id 参数不为空,则表示要获取单个评论的详情。在数据库中查询该 comment_id 对应的评论,并将其转换成特定格式的数据。
  • 最后,将处理结果以 JSON 格式返回。
  1. CommentAdd() 函数: CommentAdd() 是一个处理函数,用于添加新的评论。
  • 获取请求参数 post_idcontentauthor_id,如果这些参数有为空的情况,则返回参数错误。
  • 创建一个新的 ORM 对象 o,用于进行数据库操作。
  • 根据 author_id 查询对应的用户,如果用户不存在,则返回用户不存在的错误。
  • 根据 post_id 查询对应的帖子,如果帖子不存在,则返回帖子不存在的错误。
  • 创建一个新的 Comment 结构体,填充评论的内容、帖子和作者。
  • 将评论插入数据库,如果插入成功,则返回添加评论成功的消息,否则返回添加评论失败的消息。
  • 最后,将处理结果以 JSON 格式返回。

接口测试

运行该beego项目,命令为bee run,然后使用postman软件进行接口测试。

image.png

首先我在数据库插入了两条用户数据,方便后续的接口测试:

image.png

测试增加帖子

在表单输入正确的参数:

image.png

在表单输入错误的参数(没有提交content):

image.png

增加帖子接口测试成功。

测试查看帖子

不加参数,查询所有帖子:

image.png

加入post_id参数,查询单个帖子:

image.png

查看帖子接口测试成功。

测试增加评论

image.png

如果用户不存在:

image.png

如果帖子不存在:

image.png

如果缺少参数:

image.png

增加评论接口测试成功。

测试查看评论

查看某个帖子的所有评论:

image.png

查看某个帖子的某条评论:

image.png

不传入post_id

image.png

传入不存在的post_id显示没有评论(也可以修改代码,返回帖子不存在的消息):

image.png

查看评论接口测试成功。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/812401.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux学习之脚本优先级控制

fork炸弹 在编写Shell脚本时不要写出不可控的死循环,比如func() { func | func& } ; func,简写版为.(){ .|.& };.。接下来见证一下这两条语句的威力。因为在root用户下许多资源没有限制,所以useradd userfork新建一个用户userfork&a…

fwrite函数

1、函数声明 size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream ); 2、参数说明 buffer 指向要写入的数据的指针。 size 项大小(以字节为单位)。 count 要写入的项的最大数量。 stream 指向 FILE 结构的指针。 3、…

OpenCloudOS 与PolarDB全面适配

近日,OpenCloudOS 开源社区签署阿里巴巴开源 CLA (Contribution License Agreement, 贡献许可协议), 正式与阿里云 PolarDB 开源数据库社区牵手,并展开 OpenCloudOS (V8)与阿里云开源云原生数据库 PolarDB 分布式版、开源云原生数…

AD21原理图的高级应用(四)线束的设计及应用

(四)线束的设计及应用 Altium Designer 21 可以使用 Signal Harnesses(信号线束)的方法来建立元件之间的连接,也可用于不同原理图间的信号对接。信号线束是一种抽象连接,操作方式类似于总线,但信号线束可对包括总线、导线和其他信号线束在内的不同信号进…

el-button增加下载功能

vue3和element-plus <el-uploadv-model:file-list="fileList"action="/api/upload"multiple:limit="1":headers="headers" ><el-button type="primary">选择文件</el-button><template #file

【前缀和】560.和为 K 的子数组

Halo&#xff0c;这里是Ppeua。平时主要更新C&#xff0c;数据结构算法&#xff0c;Linux与ROS…感兴趣就关注我bua&#xff01; 和为K的子数组 题目:示例:题解&#xff1a;解法一:解法二: 题目: 示例: 题解&#xff1a; 解法一: 暴力解法:我们很容易想到通过两个for循环去遍…

【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

操作系统理论:Linux进程与进程状态(进程调度的大O(1)算法数据结构模型)

文章目录 一.进程的基本概念进程间的基本关系:父子关系 二.进程状态(1)进程的运行状态RLinux进程调度的大O(1)算法数据结构模型(运行队列哈希桶):进程的运行时间片 (2)进程的睡眠状态(S和D)(3)进程的僵尸状态和死亡状态 一.进程的基本概念 冯诺依曼体系的计算机在运行时,内存中…

基于C语言 --- 自己写一个三子棋小游戏

C语言程序设计笔记---019 初阶三子棋小游戏(开源)1、arr_main.c程序大纲2、arr_game1.h3、arr_game1.c3.1、 自定义初识化函数 InitBoard( ) 和 自定义显示函数 DisPlayBoard( )3.2、 自定义玩家下棋函数 PlayerMove( )3.4、 自定义电脑下棋函数 ComputerMove( )3.5、 输赢判断…

成为一名黑客(网络安全),需要掌握哪些黑客技能?

前言 黑客技能是一项非常复杂和专业的技能&#xff0c;需要广泛的计算机知识和网络安全知识。你可以参考下面一些学习步骤&#xff0c;系统自学网络安全。 在学习之前&#xff0c;要给自己定一个目标或者思考一下要达到一个什么样的水平&#xff0c;是学完找工作&#xff08;…

使用DataX实现mysql与hive数据互相导入导出

一、概论 1.1 什么是DataX DataX 是阿里巴巴开源的一个异构数据源离线同步工具&#xff0c;致力于实现包括关系型数据库(MySQL、Oracle 等)、HDFS、Hive、ODPS、HBase、FTP 等各种异构数据源之间稳定高效的数据同步功能。 1.2 DataX 的设计 为了解决异构数据源同步问题&#xf…

【外卖系统】分类管理业务

公共字段自动填充 需求分析 对于之前的开发中&#xff0c;有创建时间、创建人、修改时间、修改人等字段&#xff0c;在其他功能中也会有出现&#xff0c;属于公共字段&#xff0c;对于这些公共字段最好是在某个地方统一处理以简化开发&#xff0c;使用Mybatis Plus提供的公共…

简单记录牛客top101算法题(初级题C语言实现)判断回文字符串 反转字符串 合并两个有序的数组

1. 判断是否为回文字符串 给定一个长度为 n 的字符串&#xff0c;请编写一个函数判断该字符串是否回文。如果是回文请返回true&#xff0c;否则返回false。   字符串回文指该字符串正序与其逆序逐字符一致。 //示例 输入&#xff1a;"ranko" 返回值&#xff1a;fa…

DevOps系列文章之 自动化测试大全(单测和集成测试)

自动化测试业界主流工具 核心目标&#xff1a; 主要是功能测试和覆盖率测试 业界常用主流工具 GoogleTest GoogleTest是一个跨平台的(Liunx、Mac OS X、Windows 、Cygwin 、Windows CE and Symbian ) C单元测试框架&#xff0c;由google公司发布&#xff0c;为在不同平台上为编…

案例:缺陷个数与返工工作量强相关

某公司积累了21个项目缺陷个数与返工工作量的数据&#xff0c;如下表所示&#xff1a; 项目序号缺陷修复工时缺陷数1943314452299040536347446471385496071061370246774066812232189276652810830213781162678126111511381110514209032015144023516516078417710010301875601239…

3.Makefile变量的用法(附示例)

一、本节概要 本专栏所有内容围绕Makefile官方文档进行刨析,给出详细具体示例做辅助理解手撕Makefile官方手册 二、Makefile中的变量 1、没有使用变量的makefile 以下是不使用变量的makefile完整示例: edit: main.o kbd.o command.o display.o insert.o search.o files…

django channels实战(websocket底层原理和案例)

1、websocket相关 1.1、轮询 1.2、长轮询 1.3、websocket 1.3.1、websocket原理 1.3.2、django框架 asgi.py在django项目同名app目录下 1.3.3、聊天室 django代码总结 小结 1.3.4、群聊&#xff08;一&#xff09; 前端代码 后端代码 1.3.5、群聊&#xff08;二&#xff09…

网络编程 IO多路复用 [epoll版] (TCP网络聊天室)

//head.h 头文件 //TcpGrpSer.c 服务器端 //TcpGrpUsr.c 客户端 通过IO多路复用实现服务器在单进程单线程下可以与多个客户端交互 API epoll函数 #include<sys/epoll.h> int epoll_create(int size); 功能&#xff1a;创建一个epoll句柄//创建红黑树根…

TypeScript算法题实战——剑指 Offer篇(5)

目录 一、平衡二叉树1.1、题目描述1.2、题解 二、数组中数字出现的次数2.1、题目描述2.2、题解 三、数组中数字出现的次数 II3.1、题目描述3.2、题解 四、和为s的两个数字4.1、题目描述4.2、题解 五、和为s的连续正数序列5.1、题目描述5.2、题解 六、翻转单词顺序6.1、题目描述…

《cuda c编程权威指南》01- 用gpu输出hello world

学习一门新语言的最好方式就是用它来编写程序。 目录 1. 使用cpu输出hello world 2. 使用gpu输出hello world 3. CUDA编程结构 1. 使用cpu输出hello world hello.cu #include <stdio.h>void helloFromCPU() {printf("hello world from cpu!\n"); }int m…