рдорд╛рдЗрдХреНрд░реЛрд╕реЙрд░реНрдлрд╝ рдмреНрд▓реЙрдЧ рд▓рд┐рдЦрдирд╛ - рднрд╛рдЧ 3 "рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛"

рд▓реЗрдЦреЛрдВ рдХреА рд╣рдорд╛рд░реА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рджреВрд╕рд░реЗ рднрд╛рдЧ рдореЗрдВ "рдорд╛рдЗрдХреНрд░реЛрд╕реЙрдлрд╝реНрдЯ рдкрд░ рдПрдХ рдмреНрд▓реЙрдЧ рд▓рд┐рдЦрдирд╛" рд╣рдордиреЗ рдПрдкреАрдЖрдИ рдЧреЗрдЯрд╡реЗ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ ред

рдпрд╣рд╛рдБ рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдорд╛рдЗрдХреНрд░реЛрд╕реЗрд╡рд╛ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред

рд╣рдорд╛рд░рд╛ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:

  • TraceId (рдПрдкреАрдЖрдИ- gw рджреНрд╡рд╛рд░рд╛ рдЬрд╛рд░реА рд╡рд╣реА, рдЬреЛ рднрд╛рдЧ 2 тАЬрдПрдкреАрдЖрдИ рдЧреЗрдЯрд╡реЗтАЭ рджреЗрдЦреЗрдВ ) рдХрд╛ рд╕рдВрдХреЗрдд рдХрд░рддреЗ рд╣реБрдП рд╕реЗрд╡рд╛ рдХреЙрд▓ рдФрд░ рдЗрдВрдЯрд░рдореАрдбрд┐рдПрдЯ рд╕реНрдЯреЗрдЯреНрд╕ рд▓реЙрдЧ рдХрд░реЗрдВред
  • рд▓реЙрдЧрд┐рди (рд╕рд╛рдЗрдирдЗрди) рдФрд░ рдкрдВрдЬреАрдХрд░рдг (рд╕рд╛рдЗрдирдЕрдк) рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВ
  • рдХреНрд░реВрдб рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВ (рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рдмрдирд╛рдПрдВ, рдкрдврд╝реЗрдВ, рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ, рд╣рдЯрд╛рдПрдВ)ред рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ MongoDB рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдкреНрд░реЛрдЯреЛ рдлрд╛рдЗрд▓ (./services/user/protobuf/user.proto) рдореЗрдВ рдЕрдкрдиреА рд╕реЗрд╡рд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред
рдкреНрд░рдпреБрдХреНрдд рд╕рд┐рдВрдЯреИрдХреНрд╕ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВ - рдкреНрд░реЛрдЯреЛ 3ред рд╣рдо рдкреНрд░реЛрдЯреЛрдмреБрдлрд╝ рдкреИрдХреЗрдЬ рдХреЗ рдирд╛рдо рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕ рдкреИрдХреЗрдЬ рдореЗрдВ рд╕рд░реНрд╡рд░ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рднрд╛рдЧреЛрдВ рдХреЗ рдСрдЯреЛ-рдЬреЗрдирд░реЗрдЯ рдХрд┐рдП рдЧрдП рдХреЛрдб рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рд╣рдо рдПрдиреЛрдЯреЗрд╢рди рд▓рд╛рдЗрдмреНрд░реЗрд░реА google / api / annotations.proto рдХреЛ рдЗрдореНрдкреЛрд░реНрдЯ рдХрд░рддреЗ рд╣реИрдВ, REST API рдЬрдирд░реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдЧрд╛ред

syntax = "proto3"; package protobuf; import "google/api/annotations.proto"; 

рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗрд╡рд╛ рдХрд╛ рд╡рд┐рд╡рд░рдг, рд╕реАрдзреЗ рдЗрдВрдЯрд░рдлреЗрд╕ (рд╡рд┐рдзрд┐рдпрд╛рдБ) рдЬреЛ рдЙрд╕рдХреЗ рдкрд╛рд╕ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, SignUp рдЗрдВрдЯрд░рдлрд╝реЗрд╕ (рдкрдВрдЬреАрдХрд░рдг): рдпрд╣ рдПрдХ SignUpRequest рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо, рдкрд╛рд╕рд╡рд░реНрдб, FirstName рдФрд░ LastName рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ рд╣реЛрддреА рд╣реИрдВ рдФрд░ рдПрдХ SignUpResponse рд╕рдВрджреЗрд╢ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╕реНрд▓рдЧ (UserID), рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо, рднреВрдорд┐рдХрд╛ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╡рд┐рд╡рд░рдг рдореЗрдВ, рд╡рд┐рдХрд▓реНрдк рдЕрдиреБрднрд╛рдЧ рдореЗрдВ, рдкреЛрд╕реНрдЯ рдирд┐рд░реНрджреЗрд╢ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВ: "/ api / v1 / рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ / рд╕рд╛рдЗрдирдЕрдкред рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдХреЛрдб рдЬрдирд░реЗрдЯрд░ рдПрдХ REST рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдПрдЧрд╛ рдЬреЛ http: {{api_ww_host}} / api / v1 / рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрд░ POST рдЕрдиреБрд░реЛрдз рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛ред / рд╕рд╛рдЗрдирдЕрдкред

 //-------------------------------------------------- //   User //-------------------------------------------------- service UserService { //  rpc SignUp (SignUpRequest) returns (SignUpResponse) { option (google.api.http) = { post: "/api/v1/user/signup" }; } тАж } //-------------------------------------------------- // SignUp //-------------------------------------------------- message SignUpRequest { string Username = 1; string Password = 2; string FirstName = 3; string LastName = 4; } message SignUpResponse { string Slug = 1; string Username = 2; string Role = 3; } 

рдФрд░ рдпрд╣ рдЕрдиреБрд░реЛрдз рдирд┐рдХрд╛рдп рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрд░рдЪрдирд╛ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░реЗрдЧрд╛:

 { Username: 'username_value', Password: 'password_value', FirstName: 'firstname_value', LastName: 'lastname_value', } 

рдФрд░ рддрджрдиреБрд╕рд╛рд░, рдпрджрд┐ рд╕рдлрд▓ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╕рдВрд░рдЪрдирд╛ рджреЗрдЧрд╛:

 { Slug: 'user_id_value', Username: 'username_value', Role: 'role_value', } 

рдпрд╛ рдХреЛрдИ рддреНрд░реБрдЯрд┐ред рд╣рдо рдЖрдкрдХреЛ рдлрдВрдХреНрд╢рдирд▓ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдмрддрд╛рдПрдВрдЧреЗред

рдЕрдиреНрдп рдЗрдВрдЯрд░рдлреЗрд╕ (рд╕рд╛рдЗрди рдЗрди, рдХреНрд░рд┐рдПрдЯ, рдЕрдкрдбреЗрдЯ, рдбрд┐рд▓реАрдЯ, рдЧреЗрдЯ, рдлрд╛рдЗрдВрдб) рдЙрд╕реА рддрд░рд╣ рд╕реЗ рдШреЛрд╖рд┐рдд рдХрд┐рдП рдЧрдП рд╣реИрдВред

рдЕрдм рдЬрдмрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд░реЗрдбреАрдореЗрдб рдкреНрд░реЛрдЯреЙрдлрд╛рдЗрд▓ рд╣реИред рд╣рдо рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреА рд░реВрдЯ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдореЗрдВ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ sh ./bin/protogen.sh рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореБрдЦреНрдп рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░реЗрдЧрд╛ред
рдЗрд╕рдХреЗ рдмрд╛рдж, ./services/user рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкрд░ рдЬрд╛рдПрдВ рдФрд░ functions.go рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдШреЛрд╖рд┐рдд рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд▓рд┐рдЦреЗрдВред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред рд╕реЗрд╡рд╛ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдкрд░, рд╣рдо TraceId, UserId, UserRole рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдЕрдиреБрд░реЛрдз рд╕рдВрджрд░реНрдн рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд▓реЙрдЧ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рдЖрдк рдЕрдиреБрд░реЛрдз рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

 //-------------------------------------------------- // Midelware //-------------------------------------------------- func AccessLogInterceptor(ctx context.Context,req interface{},info *grpc.UnaryServerInfo,handler grpc.UnaryHandler,) (interface{}, error) { start:=time.Now() md,_:=metadata.FromIncomingContext(ctx) // Calls the handler reply, err := handler(ctx, req) var traceId,userId,userRole string if len(md["trace-id"])>0{ traceId=md["trace-id"][0] } if len(md["user-id"])>0{ userId=md["user-id"][0] } if len(md["user-role"])>0{ userRole=md["user-role"][0] } msg:=fmt.Sprintf("Call:%v, traceId: %v, userId: %v, userRole: %v, time: %v", info.FullMethod,traceId,userId,userRole,time.Since(start)) app.AccesLog(msg) return reply, err } 

рд╕рд╛рдЗрдирдЕрдк рд╡рд┐рдзрд┐ рдореЗрдВ, рд╣рдо рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕рдВрд░рдЪрдирд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред

 //,   STATUS_FAIL out:=&SignUpResponse{} 

рдЕрдЧрд▓рд╛, рдЕрдиреБрд░реЛрдз рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВред

 //     // Username err:=checkUserName(in.Username) if err!=nil{ log.Printf("[ERR] %s.SignUp, %v", app.SERVICE_NAME,err) return out,err } // Username   err=o.checkUserNameExist(in.Username) if err!=nil{ log.Printf("[ERR] %s.SignUp, %v", app.SERVICE_NAME,err) return out,err } // Password err=checkPassword(in.Password) if err!=nil{ log.Printf("[ERR] %s.SignUp, %v", app.SERVICE_NAME,err) return out,err } 

рдФрд░ рдЕрдЧрд░ рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ, рддреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рдВрд░рдЪрдирд╛ рднрд░реЗрдВ, рдбреЗрдЯрд╛рдмреЗрд╕ рдкрд░ рд▓рд┐рдЦреЗрдВ рдФрд░ рдЙрддреНрддрд░ рд╡рд╛рдкрд╕ рдХрд░реЗрдВред

 user:=&User{ Username:in.Username, FirstName:in.FirstName, LastName:in.LastName, Password:getMD5(in.Password), } var slug string collection:= o.DbClient.Database("blog").Collection("users") insertResult, err := collection.InsertOne(context.TODO(), user) if err != nil { return out,err } if oid, ok := insertResult.InsertedID.(primitive.ObjectID); ok { slug=fmt.Sprintf("%s",oid.Hex()) }else { err:=app.ErrInsert return out,err } out.Slug=slug out.Username=in.Username out.Role=app.ROLE_USER return out,nil 

рдЕрд▓рдЧ-рдЕрд▓рдЧ, рд╣рдо рддреНрд░реБрдЯрд┐ рд╡рд╛рдкрд╕реА рдкрд░ рдзреНрдпрд╛рди рджреЗрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

 err:=app.ErrInsert 

рдЕрдВрддрддрдГ рдпрд╣ рддреНрд░реБрдЯрд┐ рд╣рдорд╛рд░реЗ рдПрдкреАрдЖрдИ-рдбрдмреНрд▓реНрдпреВрдЬреА (рдЗрд╕рдХреЗ рдЖрд░рдИрдПрд╕рдЯреА рднрд╛рдЧ рдореЗрдВ) рдкрд░ рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдПрдЧреА рдФрд░ рдЗрд╕реЗ рдорд╛рдирдХ рдПрдЪрдЯреАрдЯреАрдкреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред рдЕрддрд┐рд░рд┐рдХреНрдд рдХреЛрдб рдХреЗ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдХреЛ рд▓рд┐рдЦрдиреЗ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдорд╛рдирдХ рдЧреЛ рддреНрд░реБрдЯрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди google.golang.org/grpc/status рдкреИрдХреЗрдЬ рд╕реЗ status.errorред

рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ microservice рдХреЗ рд╕рднреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдФрд░ рд╡реЗ HTTP рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛрдб рдореЗрдВ рдХреИрд╕реЗ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣реИрдВред / рд╕реЗрд╡рд╛рдПрдБ / рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ / рдРрдк / рддреНрд░реБрдЯрд┐рдпрд╛рдБред

 package app import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) //    var ( //  ErrEmailIncorrect = status.Error(codes.InvalidArgument, " E-mail") ErrPasswordIsEmpty = status.Error(codes.InvalidArgument, "Password  ") ErrUserNameIsEmpty = status.Error(codes.InvalidArgument, "E-mail  ") ErrUserNameIsExist = status.Error(codes.AlreadyExists, "  ") ErrNotFound = status.Error(codes.NotFound, "  ") ErrIncorrectLoginOrPassword = status.Error(codes.Unauthenticated,"   ") // CRUD ErrInsert = status.Error(codes.Internal, "  ") ErrUpdate = status.Error(codes.Internal, "  ") ) //================================================== // All gRPC err codes //================================================== // codes.OK - http.StatusOK // codes.Canceled - http.StatusRequestTimeout // codes.Unknown - http.StatusInternalServerError // codes.InvalidArgument - http.StatusBadRequest // codes.DeadlineExceeded - http.StatusGatewayTimeout // codes.NotFound - http.StatusNotFound // codes.AlreadyExists - http.StatusConflict // codes.PermissionDenied - http.StatusForbidden // codes.Unauthenticated - http.StatusUnauthorized // codes.ResourceExhausted - http.StatusTooManyRequests // codes.FailedPrecondition - http.StatusBadRequest // codes.Aborted - http.StatusConflict // codes.OutOfRange - http.StatusBadRequest // codes.Unimplemented - http.StatusNotImplemented // codes.Internal - http.StatusInternalServerError // codes.Unavailable - http.StatusServiceUnavailable // codes.DataLoss - http.StatusInternalServerError 

рдФрд░ рдЖрдЦрд┐рд░реА рдЪреАрдЬ рдЬреЛ рдореИрдВ рдпреВрдЬрд░ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрддрд╛рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рд╡рд╣ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдЬреБрдбрд╝рддрд╛ рд╣реИред рдпреЗ рдСрдкрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред/services/user/main.go

рд╕реЗрд╡рд╛ рдХрд╛ рд╢реБрднрд╛рд░рдВрдн:

 lis,err:= net.Listen("tcp", fmt.Sprintf(":%s", Port)) if err != nil { log.Fatalf("failed to listen: %v", err) } grpcServer:= grpc.NewServer( grpc.UnaryInterceptor(protobuf.AccessLogInterceptor), ) s:=&protobuf.Server{} тАж // attach the user service to the server protobuf.RegisterUserServiceServer(grpcServer, s) 

рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдХрдиреЗрдХреНрд╢рди (main.go):

 //   s.DbConnect() defer s.DbDisconnect() 

DbConnect рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди (./services/user/functions.go):

 //-------------------------------------------------- // /   //-------------------------------------------------- func (o *Server) DbConnect() error { var client *mongo.Client // Create client strURI:=fmt.Sprintf("mongodb://%s:%s@%s:%s",os.Getenv("MONGO_USER"),os.Getenv("MONGO_PASS"),os.Getenv("MONGO_HOST"),os.Getenv("MONGO_PORT")) client, err:= mongo.NewClient(options.Client().ApplyURI(strURI)) if err != nil { return err } // Create connect err = client.Connect(context.TODO()) if err != nil { return err } o.DbClient=client return nil } 

Source: https://habr.com/ru/post/hi482002/


All Articles