Go三件套介绍 3 | 青训营笔记

83 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 18 天

实战案例介绍

笔记项目拆解为如下服务:

服务demoapi,主要实现服务介绍,采用的传输协议是HTTP,主要技术栈为Gorm/Kitex/Hertz。

服务demouser,主要实现用户数据管理,采用的传输协议是Protobuf,主要技术栈为Gorm/Kitex。

服务demonote,主要实现笔记数据管理,采用的传输协议是Thrift,主要技术栈为Gorm/Kitex

项目功能

demoapi:主要实现用户登陆,用户注册,用户创建笔记,用户更新笔记,用户删除笔记,用户查询笔记

demouser:实现创建用户,查询用户和校验用户

demonote:创建笔记,更新笔记,删除笔记和查询笔记

功能关系

调用方使用http协议连接demoapi,demoapi访问demouser,通过操作用户数据proto;访问ETCD通过服务发现;访问demonote通过操作笔记数据thrift;而demouser和demonote都需要在ETCD上进行服务注册,都将MySQL作为数据库。

代码说明

message User {
    int64 user_id = 1;
    string user_name = 2;
    string avatar = 3;
}
message CreateUserRequest {
    string user_name = 1;
    string password = 2;
}

message CreateUserResponse {
	BaseResp base_resp = 1;
}
message MGetUserRequest {
	repeated int64 user_ids = 1;

}
message MGetUserResponse {
    repeated User users = 1;
    BaseResp base_resp = 2;
}

message CheckUserRequest{
string user_name = 1;
string password = 2;
}
message CheckUserResponse{
    int64 user_id = 1;
    BaseResp base_resp = 2;
}
service UserService {
        rpc createUser (createUserRequest) returns (createUserResponse){}
        rpc MGetUser (MGetUserRequest) returns (MGetUserResponse){}
        rpc CheckUser (CheckUserRequest) returns (CheckUserResponse){}
}
struct DeleteNoteResponse {
1:BaseResp base_resp
}
struct UpdateNoteRequest {
    1:i64 note_id
    2:i64 user_id
    3 : optional string title
    4: optional string content
}
struct UpdateNoteResponse {
	1:BaseResp base_resp
}

struct MGetNoteRequest {
    1:list<i64> note_ids	
}

struct MGetNoteResponse {
    1:list<Note> notes
    2: BaseResp base_resp
}

struct QueryNoteRequest {
    1:i64 user_id
    2 : optional string search_key
    3:i64 offset
    4:i64 limit
}

struct QueryNoteResponse, {
    1:list<Note>notes
    2 :i64 total
    3 :BaseResp base_resp
}

service NoteService {
    CreateNoteResponse CreateNote(1:CreateNoteRequest req)
    MGetNoteResponse MGetNote( 1:MGetNoteRequest req)
    DeleteNoteResponse DeleteNote( 1:DeleteNoteRequest req)
    QueryNoteResponse QueryNote( 1 : QueryNoteRequest req)
    UpdateNoteResponse UpdateNote(1: UpdateNoteRequest req)
}

Hertz关键代码详解

// CreateNote create note info
func CreateNote(ctx context.Context, c *app.RequestContext) {
    var noteVar NoteParam
    if err :c.Bind( &noteVar);err!=nil{
        SendResponse(c, errno.ConvertErr(err), nil)
        return
     }
    if len(noteVar.Title) == 0 len(noteVar.Content) == 0 {
        SendResponse(c, errno.ParamErr, nil)
        return
    }
    claims := jwt.ExtractClaims ( ctx,c)
    userID := int64(claims[constants.IdentityKey]. (float64))
    err := rpc.CreateNote(context.Background( ), &notedemo.CreateNoteRequest{
        UserId: userID,
        Content: noteVar.Content,Title: noteVar.Title,
    })
    if err != nil {
        SendResponse(c, errno.ConvertErr(err), nil)
        return
    }
    SendResponse(c, errno.Success, nil)
}

KitexClient关键代码

func initNoteRpc( ) {
r, err := etcd.NewEtcdResolver( []stringiconstants.EtcdAddress})
if err != nil {
panic(err)
}
c, err := noteservice.NewClient(
constants.NoteServiceName,
client.withMiddleware(middleware.CommonMiddleware),
client.withInstanceMw( middleware.clientMiddleware),
client.withMuxConnection(1),//mux
client.withRPCTimeout(3*time.Second),//rpc timeout
client.withConnectTimeout(50*time.Millisecond),//conn timeout
client.withFailureRetry( retry.NewFailurePolicy( )),//retry
client.withSuite(trace.NewDefaultclientSuite()),//tracer
client.withResolver(r),//resolver
)
if err != nil {
panic(err)
}
noteclient = c
// Createlote create note info
func CreateNote(ctx context.Context,req *notedemo.CreateNoteRequest) error {
resp, err := noteclient. CreateNote( ctx, req)
if err != nil {
return err
}
if resp.BaseResp.Statuscode != 0 {
return errno.NewErrNo(resp.BaseResp.StatusCode, resp.BaseResp.StatusNessage)
}
return nil

KitexServer关键代码

type CreateNoteService struct {
	ctx context.Context
}
// NewCreateNoteService new CreateNoteService
func NewCreateNoteService(ctx context.Context) *CreateNoteService {
	return &CreateNoteService{ctx: ctx}
}
// CreateNote create note info
func (s *CreateNoteService)CreataNoto( req *notedemo.CreateNoteRequest) error{ 
	noteModel := &db.Note{
		UserID:req.UserId,
		Title:req.Title,
		Content: req.Content,
}
	return db. CreateNote(s.ctx,[]*db.Note{noteModel})
}

Gorm关键代码

type Note struct {
	gorm.Model
	UserID int64 `json:"user_id"
	Title string `"son:"title"`
	Content string `json: "content"`
}

func (n *Note) TableName() string {
	return constants.NoteTableName
}
/ / CreateNote create note info

func CreateNote(ctx context.Context,notes[]*Note) error {
	if err := DB.withContext(ctx).Create(notes).Error; err != nil {
		return err
}
return nil
}
// MGetNotes multiple get list of note info
func MGetNotes(ctx context.Context,noteIDs []int64)( []*Note,error) {
	var res []*Note
	if len(noteIDs) == 0 {
		return res, nil
	}
	if err := DB.withContext(ctx).where("id in ?",noteIDs).Find(&res).Error; err != nil {
		return res, err
	}	
	return res, nil
}
 // UpdateNote update note info
func UpdateNote(ctx context.Context,noteID,userID int64,title,content *string) error {
params := map[string]interface{}{}
if title != nil {
params [""title"] =*title
}
if content != nil {
params [""content"]=*content
}
return DB.withContext(ctx).Model(&Note{}).where("id = ? and user_id = ?",noteID,userID).
Updates(params).Error
}
// DeleteNote delete note info
func DeleteNote(ctx context.Context,noteID,userID int64) error {
return DB.withContext(ctx).where("id = ? and user_id = ? ", noteID,userID).Delete(&Note{}).Error
}