“This is the 11th day of my participation in the First Challenge 2022. For details: First Challenge 2022.”

B station video explanation address

www.bilibili.com/video/BV1h4…

Making the source code

Github.com/CocaineCong…

2. User module

2.1 Database Configuration

  • user/conf/conf.ini

File configuration, mysql configuration, service configuration…

[service]
AppMode = debug
HttpPort = :3000

[mysql]
Db = mysql
DbHost = 127.0.0.1
DbPort = 3306
DbUser = root
DbPassWord = root
DbName = todo_list
Copy the code
  • user/model/

Load the configuration

func Init(a) {
	file, err := ini.Load("./conf/config.ini")
	iferr ! =nil {
		fmt.Println(Configuration file reading error, please check file path:, err)
	}
	LoadMysqlData(file)
	path := strings.Join([]string{DbUser, ":", DbPassWord, "@tcp(", DbHost, ":", DbPort, "/", DbName, "? charset=utf8&parseTime=true"}, "")
	model.Database(path)
}
Copy the code
  • user/model/user.go

Defining the database model

type User struct {
	gorm.Model
	UserName       string `gorm:"unique"`
	PasswordDigest string
}
Copy the code
  • user/model/migration.go

Database model migration

func migration(a) {
	Automatic migration mode
	DB.Set("gorm:table_options"."charset=utf8mb4").
		AutoMigrate(&User{})
}
Copy the code

2.2 ProTO file preparation

  • user/services/protos/userModels.proto

Define the proto model of user, note that this must be capitalized!! Otherwise, the back gateway cannot be bound!

syntax="proto3";
package services;
option go_package =". /; protos";

message UserModel{
    // @inject_tag: json:"id"
    uint32 ID=1;
    // @inject_tag: json:"user_name"
    string UserName=2;
    // @inject_tag: json:"avatar"
    string Avatar=3;
    // @inject_tag: json:"email"
    string Email=4;
    // @inject_tag: json:"nickname"
    string NickName=5;
    // @inject_tag: json:"status"
    string Status=6;
    // @inject_tag: json:"limit"
    uint32 Limit=7;
    // @inject_tag: json:"created_at"
    int64 CreatedAt=8;
    // @inject_tag: json:"updated_at"
    int64 UpdatedAt=9;
    // @inject_tag: json:"deleted_at"
    int64 DeletedAt=10;
}
Copy the code

Execute in the proto directory

protoc --proto_path=. --micro_out=. --go_out=. userModel.proto
Copy the code
  • user/services/protos/userService.proto

The UserRequest and UserResponse parameters are defined here

syntax="proto3";
package services;
import "userModels.proto";
option go_package =". /; protos";

message UserRequest{
  // @inject_tag: json:"user_name" form:"user_name" uri:"user_name"
  string UserName=1;
  // @inject_tag: json:"password" form:"password" uri:"password"
  string Password=2;
  // @inject_tag: json:"password_confirm" form:"password_confirm" uri:"password_confirm"
  string PasswordConfirm=3;
}

message UserDetailResponse{
  UserModel UserDetail=1;
  uint32 Code=2;
}


service UserService{
  rpc UserLogin(UserRequest) returns(UserDetailResponse);
  rpc UserRegister(UserRequest) returns(UserDetailResponse);
}
Copy the code

Execute in the proto directory

protoc --proto_path=. --micro_out=. --go_out=. userService.proto
Copy the code

Just generate these four files and move toservicesFile.

2.3 Implement the service logic of the user module

Define the structure of the user service

//UserService UserService
type UserService struct{}Copy the code

2.3.1 User Registration method

The parameters passed here are the context information, as well as the UserRequest and UserDetailResponse of the Services layer

// UserRegister user registration
func (*UserService) UserRegister(ctx context.Context, req *services.UserRequest, res *services.UserDetailResponse) error {
	ifreq.Password ! = req.PasswordConfirm { err := errors.New("Two different passwords entered.")
		return err
	}
	count := 0
	if err := model.DB.Model(&model.User{}).Where("user_name=?", req.UserName).Count(&count).Error; err ! =nil {
		return err
	}
	if count > 0 {
		err := errors.New("Username already exists")
		return err
	}
	user := model.User{
		UserName: req.UserName,
	}
	// Encrypt the password
	iferr := user.SetPassword(req.Password); err ! =nil {
		return err
	}
	// Create a user
	iferr := model.DB.Create(&user).Error; err ! =nil {
		return err
	}
	res.UserDetail = BuildUser(user)
	return nil
}
Copy the code

2.3.2 Logging In to the Service

Same logic, UserLogin method implemented here, same context, request parameters, response parameters

//UserLogin implements user service interface UserLogin
func (*UserService) UserLogin(ctx context.Context, req *services.UserRequest, res *services.UserDetailResponse) error {
	var user model.User
	res.Code = 200
	if err := model.DB.Where("user_name = ?", req.UserName).First(&user).Error; err ! =nil {
		// If no query is found, an error is returned
		if gorm.IsRecordNotFoundError(err) {
			res.Code = 10003
			return nil
		}
		res.Code = 30001
		return nil
	}
	if user.CheckPassword(req.Password) == false {
		res.Code = 10004
		return nil
	}
	res.UserDetail =  BuildUser(user)
	return nil
}
Copy the code

2.4 Access etCD Service Discovery

  • Registered etcd
	etcdReg := etcd.NewRegistry(
		registry.Addrs("127.0.0.1:2379"),Copy the code
  • Get the microservice instance
	// 1. Get the microservice instance
	microService := micro.NewService(
		micro.Name("rpcUserService"), // Set the name of the microservice to be accessed
		micro.Address("127.0.0.1:8082"),
		micro.Registry(etcdReg),
	)
Copy the code
  • Initialize the
	microService.Init()
Copy the code
  • The service registry

Register user services with etCD

	_ = services.RegisterUserServiceHandler(microService.Server(), new(core.UserService))
Copy the code
  • Start microservices
	_ = microService.Run()
Copy the code

Check the etcdhttp://localhost:8080/etcdkeeper/Whether the module has registration information

At this point, the client’s micro service has been completed, we access the gateway, call the service.