1.路徑:\src\api\v1\service\todo-service.go
2.service服務端增刪改查介面:
package v1
import (
"context"
"database/sql"
"fmt"
"github.com/golang/protobuf/ptypes"
v1 "goWebGin/api/proto/v1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"time"
)
const (
apiVersion = "v1"
)
type ToDoServiceServer struct {
db *sql.DB
}
func NewToDoServiceServer(db *sql.DB) *ToDoServiceServer {
return &ToDoServiceServer{db: db}
}
//校驗版本號
func (s *ToDoServiceServer) checkAPI(api string) error {
if len(api) > 0 && apiVersion != api {
return status.Error(codes.Unimplemented, fmt.Sprintf("不支援當前API版本號%s", api))
}
return nil
}
//連線資料庫
func (s *ToDoServiceServer) connect(ctx context.Context) (*sql.Conn, error) {
c, err := s.db.Conn(ctx)
if err != nil {
return nil, status.Error(codes.Unknown, "資料庫連線失敗:"+err.Error())
}
return c, nil
}
//新增單條記錄
func (s *ToDoServiceServer) Create(ctx context.Context, req *v1.CreateRequest) (*v1.CreateResponse, error) {
if err := s.checkAPI(req.Api); err != nil {
return nil, err
}
c, err := s.connect(ctx)
if err != nil {
return nil, err
}
defer func() {
_ = c.Close()
}()
reminder, err := ptypes.Timestamp(req.ToDo.Reminder)
if err != nil {
return nil, status.Error(codes.InvalidArgument, "引數錯誤:"+err.Error())
}
res, err := c.ExecContext(ctx, "INSERT INTO ToDO(`title`,`description`,`reminder`) VALUES (?,?,?)", req.ToDo.Title, req.ToDo.Description, reminder)
if err != nil {
return nil, status.Error(codes.Unknown, "新增 ToDo失敗:"+err.Error())
}
id, err := res.LastInsertId()
if err != nil {
return nil, status.Error(codes.Unknown, "獲取最新ID失敗"+err.Error())
}
return &v1.CreateResponse{Api: apiVersion, Id: id}, nil
}
//讀取單條記錄
func (s *ToDoServiceServer) Read(ctx context.Context, req *v1.ReadRequest) (*v1.ReadResponse, error) {
if err := s.checkAPI(req.Api); err != nil {
return nil, err
}
c, err := s.connect(ctx)
if err != nil {
return nil, err
}
defer func() {
_ = c.Close()
}()
row, err := c.QueryContext(ctx, "SELECT * FROM ToDo WHERE `id`=?", req.Id)
if err != nil {
return nil, status.Error(codes.Unknown, "查詢失敗"+err.Error())
}
defer func() {
_ = row.Close()
}()
if !row.Next() {
if err := row.Err(); err != nil {
return nil, status.Error(codes.Unknown, "獲取資料失敗"+err.Error())
}
return nil, status.Error(codes.NotFound, fmt.Sprintf("ID='%d'找不到", req.Id))
}
var td v1.ToDo
var reminder time.Time
if err := row.Scan(&td.Id, &td.Title, &td.Description, &reminder); err != nil {
return nil, status.Error(codes.Unknown, "查詢資料失敗"+err.Error())
}
if row.Next() {
return nil, status.Error(codes.Unknown, fmt.Sprintf("查詢到多條記錄ID=%d", req.Id))
}
td.Reminder, err = ptypes.TimestampProto(reminder)
if err != nil {
return nil, status.Error(codes.Unknown, "reminder無效:"+err.Error())
}
return &v1.ReadResponse{Api: apiVersion, ToDo: &td}, nil
}
//更新記錄
func (s *ToDoServiceServer) Update(ctx context.Context, req *v1.UpdateRequest) (*v1.UpdateResponse, error) {
if err := s.checkAPI(req.Api); err != nil {
return nil, err
}
c, err := s.connect(ctx)
if err != nil {
return nil, err
}
defer func() {
_ = c.Close()
}()
reminder, err := ptypes.Timestamp(req.ToDo.Reminder)
res, err := c.ExecContext(ctx, "UPDATE toDo SET `title`=?,`description`=?,`reminder`=? WHERE `id`=?",
req.ToDo.Title, req.ToDo.Description,reminder, req.ToDo.Id)
if err != nil {
return nil, status.Error(codes.Unknown, "更新失敗")
}
row, err := res.RowsAffected()
if err != nil {
return nil, status.Error(codes.Unknown, "更新失敗")
}
if row == 0 {
return nil, status.Error(codes.NotFound, fmt.Sprintf("ID=%d找不到", req.ToDo.Id))
}
return &v1.UpdateResponse{
Api: apiVersion,
Updated: row,
}, nil
}
//刪除記錄
func (s *ToDoServiceServer) Delete(ctx context.Context, req *v1.DeleteRequest) (*v1.DeleteResponse, error) {
if err := s.checkAPI(req.Api); err != nil {
return nil, err
}
c, err := s.connect(ctx)
if err != nil {
return nil, err
}
defer func() {
_ = c.Close()
}()
res, err := c.ExecContext(ctx, "DELETE FROM TOdO WHERE `id`=?", req.Id)
if err != nil {
return nil, status.Error(codes.Unknown, "刪除失敗:"+err.Error())
}
row, err := res.RowsAffected()
if err != nil {
return nil, status.Error(codes.Unknown, "刪除失敗:"+err.Error())
}
if row == 0 {
return nil, status.Error(codes.NotFound, fmt.Sprintf("ID=%d找不到", req.Id))
}
return &v1.DeleteResponse{
Api: apiVersion,
Deleted: row,
}, nil
}
//獲取多行記錄
func (s *ToDoServiceServer) ReadAll(ctx context.Context, req *v1.ReadAllRequest) (*v1.ReadAllResponse, error) {
if err := s.checkAPI(req.Api); err != nil {
return nil, err
}
c, err := s.connect(ctx)
if err != nil {
return nil, err
}
defer func() {
_ = c.Close()
}()
rows, err := c.QueryContext(ctx, "SELECT * FROM toDo")
if err != nil {
return nil, status.Error(codes.Unknown, "查詢失敗:"+err.Error())
}
defer func() {
_ = rows.Close()
}()
var reminder time.Time
list := []*v1.ToDo{}
for rows.Next() {
td := new(v1.ToDo)
if err := rows.Scan(&td.Title, &td.Description, &reminder); err != nil {
return nil, status.Error(codes.Unknown, "查詢失敗:"+err.Error())
}
td.Reminder, err = ptypes.TimestampProto(reminder)
if err != nil {
return nil, status.Error(codes.Unknown, "reminder無效:"+err.Error())
}
list = append(list, td)
if err := rows.Err(); err != nil {
return nil, status.Error(codes.Unknown, "獲取資料失敗:"+err.Error())
}
}
return &v1.ReadAllResponse{
Api: apiVersion,
ToDos: list,
}, nil
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結