Commit e5a34ae1 authored by Zhu yizheng's avatar Zhu yizheng
Browse files

除了跨域

parent ceddb47f
package db
import (
"github.com/sirupsen/logrus"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
// DB 全局数据库实例
var DB *gorm.DB
// InitDB 初始化 PostgreSQL 数据库
func InitDB() {
// PostgreSQL 连接字符串
// 替换为你的实际配置:host、port、user、password、dbname
dsn := "host=localhost port=5432 user=go_zyz password=zyz757605 dbname=mygo sslmode=disable"
var err error
DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
logrus.WithError(err).Fatal("数据库连接失败")
}
// 自动迁移,创建/更新 Comment 表
if err := DB.AutoMigrate(&Comment{}); err != nil {
logrus.WithError(err).Fatal("数据库迁移失败")
}
logrus.Info("PostgreSQL 数据库初始化成功")
}
package db
import (
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
// Comment 数据库模型
type Comment struct {
ID int `json:"id" gorm:"primaryKey;autoIncrement"`
Name string `json:"name" gorm:"not null"`
Comment string `json:"content" gorm:"not null"`
}
// CreateComment 创建评论
func CreateComment(name, content string) (*Comment, error) {
comment := &Comment{
Name: name,
Comment: content,
}
if err := DB.Create(comment).Error; err != nil {
logrus.WithError(err).Error("创建评论失败")
return nil, err
}
logrus.WithFields(logrus.Fields{
"comment_id": comment.ID,
"name": comment.Name,
}).Info("评论创建成功")
return comment, nil
}
// GetComments 获取评论(支持分页)
func GetComments(page, size int) ([]Comment, int64, error) {
var comments []Comment
var total int64
// 查询总数
if err := DB.Model(&Comment{}).Count(&total).Error; err != nil {
logrus.WithError(err).Error("获取评论总数失败")
return nil, 0, err
}
// 分页查询
if size == -1 {
// 返回所有评论
if err := DB.Find(&comments).Error; err != nil {
logrus.WithError(err).Error("获取所有评论失败")
return nil, 0, err
}
} else {
// 分页
offset := (page - 1) * size
if err := DB.Limit(size).Offset(offset).Find(&comments).Error; err != nil {
logrus.WithError(err).Error("获取分页评论失败")
return nil, 0, err
}
}
logrus.WithFields(logrus.Fields{
"page": page,
"size": size,
"total": total,
}).Info("评论查询成功")
return comments, total, nil
}
// DeleteComment 删除评论
func DeleteComment(id int) error {
result := DB.Where("id = ?", id).Delete(&Comment{})
if err := result.Error; err != nil {
logrus.WithError(err).Error("删除评论失败")
return err
}
if result.RowsAffected == 0 {
logrus.WithField("comment_id", id).Warn("评论不存在")
return gorm.ErrRecordNotFound
}
logrus.WithField("comment_id", id).Info("评论删除成功")
return nil
}
module github.com/zyz/comment module github.com/zyz/comment-api
go 1.24.3 go 1.21
require ( require (
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect gorm.io/driver/postgres v1.6.0
gorm.io/gorm v1.30.0
)
require (
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.6.0 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
) )
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
...@@ -3,6 +3,8 @@ package main ...@@ -3,6 +3,8 @@ package main
import ( import (
"net/http" "net/http"
"github.com/zyz/comment-api/db"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
...@@ -11,6 +13,9 @@ func main() { ...@@ -11,6 +13,9 @@ func main() {
logrus.SetFormatter(&logrus.JSONFormatter{}) logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.Info("启动服务器...") logrus.Info("启动服务器...")
// 初始化数据库
db.InitDB()
// 注册路由 // 注册路由
http.HandleFunc("/comment/get", getCommentsHandler) http.HandleFunc("/comment/get", getCommentsHandler)
http.HandleFunc("/comment/add", addCommentHandler) http.HandleFunc("/comment/add", addCommentHandler)
......
...@@ -4,37 +4,26 @@ import ( ...@@ -4,37 +4,26 @@ import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"strconv" "strconv"
"sync"
"github.com/zyz/comment-api/db"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gorm.io/gorm"
) )
// Comment 表示单个评论 // Response 统一响应格式
type Comment struct {
ID int `json:"id"`
Name string `json:"name"`
Comment string `json:"content"`
}
// Response 表示统一的 API 响应格式
type Response struct { type Response struct {
Code int `json:"code"` Code int `json:"code"`
Msg string `json:"msg"` Msg string `json:"msg"`
Data interface{} `json:"data"` Data interface{} `json:"data"`
} }
// GetCommentsResponse 表示获取评论 API 的响应 // GetCommentsResponse 获取评论响应
type GetCommentsResponse struct { type GetCommentsResponse struct {
Total int `json:"total"` Total int64 `json:"total"`
Comments []Comment `json:"comments"` Comments []db.Comment `json:"comments"`
} }
// 模拟数据库
var mutex = &sync.RWMutex{}
var comments []Comment
var incrementID int
// getCommentsHandler 处理获取评论的请求
func getCommentsHandler(w http.ResponseWriter, r *http.Request) { func getCommentsHandler(w http.ResponseWriter, r *http.Request) {
log := logrus.WithFields(logrus.Fields{ log := logrus.WithFields(logrus.Fields{
"method": r.Method, "method": r.Method,
...@@ -53,35 +42,21 @@ func getCommentsHandler(w http.ResponseWriter, r *http.Request) { ...@@ -53,35 +42,21 @@ func getCommentsHandler(w http.ResponseWriter, r *http.Request) {
"size": size, "size": size,
}) })
// 使用读锁读取评论 // 查询数据库
mutex.RLock() comments, total, err := db.GetComments(page, size)
defer mutex.RUnlock() if err != nil {
respondError(w, http.StatusInternalServerError, "查询评论失败", nil, log.WithError(err))
// 计算分页 return
total := len(comments)
var result []Comment
if size == -1 {
result = comments
} else {
start := (page - 1) * size
end := start + size
if start < total {
if end > total {
end = total
}
result = comments[start:end]
}
} }
// 准备响应 // 准备响应
data := GetCommentsResponse{ data := GetCommentsResponse{
Total: total, Total: total,
Comments: result, Comments: comments,
} }
respondSuccess(w, data, log) respondSuccess(w, data, log)
} }
// addCommentHandler 处理添加评论的请求
func addCommentHandler(w http.ResponseWriter, r *http.Request) { func addCommentHandler(w http.ResponseWriter, r *http.Request) {
log := logrus.WithFields(logrus.Fields{ log := logrus.WithFields(logrus.Fields{
"method": r.Method, "method": r.Method,
...@@ -109,27 +84,16 @@ func addCommentHandler(w http.ResponseWriter, r *http.Request) { ...@@ -109,27 +84,16 @@ func addCommentHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
// 使用写锁添加评论 // 创建评论
mutex.Lock() comment, err := db.CreateComment(req.Name, req.Content)
defer mutex.Unlock() if err != nil {
respondError(w, http.StatusInternalServerError, "创建评论失败", nil, log.WithError(err))
incrementID++ return
newComment := Comment{
ID: incrementID,
Name: req.Name,
Comment: req.Content,
} }
comments = append(comments, newComment)
log.WithFields(logrus.Fields{ respondSuccess(w, comment, log)
"comment_id": newComment.ID,
"name": newComment.Name,
}).Info("评论已添加")
respondSuccess(w, newComment, log)
} }
// deleteCommentHandler 处理删除评论的请求
func deleteCommentHandler(w http.ResponseWriter, r *http.Request) { func deleteCommentHandler(w http.ResponseWriter, r *http.Request) {
log := logrus.WithFields(logrus.Fields{ log := logrus.WithFields(logrus.Fields{
"method": r.Method, "method": r.Method,
...@@ -149,28 +113,16 @@ func deleteCommentHandler(w http.ResponseWriter, r *http.Request) { ...@@ -149,28 +113,16 @@ func deleteCommentHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
// 使用写锁删除评论 // 删除评论
mutex.Lock() if err := db.DeleteComment(id); err != nil {
defer mutex.Unlock() if err == gorm.ErrRecordNotFound {
respondError(w, http.StatusNotFound, "评论不存在", nil, log)
found := false } else {
for i, comment := range comments { respondError(w, http.StatusInternalServerError, "删除评论失败", nil, log.WithError(err))
if comment.ID == id {
comments = append(comments[:i], comments[i+1:]...)
found = true
break
} }
}
if !found {
respondError(w, http.StatusNotFound, "评论不存在", nil, log)
return return
} }
log.WithFields(logrus.Fields{
"comment_id": id,
}).Info("评论已删除")
respondSuccess(w, nil, log) respondSuccess(w, nil, log)
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment