├── 4-layers ├── internal │ ├── domain │ │ ├── errors.go │ │ └── profile.go │ ├── controller │ │ ├── http │ │ │ ├── handlers.go │ │ │ ├── get_profile.go │ │ │ ├── create_profile.go │ │ │ └── router.go │ │ └── kafka_consume │ │ │ └── consumer.go │ ├── adapter │ │ ├── redis │ │ │ └── redis.go │ │ ├── kafka_produce │ │ │ └── produce.go │ │ └── postgres │ │ │ └── postgres.go │ └── usecase │ │ ├── get_profile.go │ │ ├── usecase.go │ │ └── create_profile.go ├── pkg │ ├── transaction │ │ └── wrap.go │ ├── render │ │ └── json.go │ ├── httpserver │ │ └── httpserver.go │ ├── logger │ │ └── logger.go │ ├── otel │ │ └── otel.go │ └── metrics │ │ └── http_server.go ├── go.mod ├── go.sum ├── config │ └── config.go └── cmd │ └── app │ └── main.go ├── 5-layers-dto ├── internal │ ├── domain │ │ ├── errors.go │ │ └── profile.go │ ├── dto │ │ ├── get_profile.go │ │ └── create_profile.go │ ├── controller │ │ ├── http │ │ │ ├── handlers.go │ │ │ ├── get_profile.go │ │ │ ├── create_profile.go │ │ │ └── router.go │ │ └── kafka_consume │ │ │ └── consumer.go │ ├── adapter │ │ ├── redis │ │ │ └── redis.go │ │ ├── kafka_produce │ │ │ └── produce.go │ │ └── postgres │ │ │ └── postgres.go │ └── usecase │ │ ├── get_profile.go │ │ ├── usecase.go │ │ └── create_profile.go ├── pkg │ ├── transaction │ │ └── wrap.go │ ├── render │ │ └── json.go │ ├── httpserver │ │ └── httpserver.go │ ├── logger │ │ └── logger.go │ ├── otel │ │ └── otel.go │ └── metrics │ │ └── http_server.go ├── go.mod ├── go.sum ├── config │ └── config.go └── cmd │ └── app │ └── main.go ├── 6-layers-ddd ├── internal │ ├── domain │ │ ├── errors.go │ │ └── profile.go │ ├── dto │ │ ├── get_profile.go │ │ └── create_profile.go │ ├── controller │ │ ├── http │ │ │ ├── handlers.go │ │ │ ├── get_profile.go │ │ │ ├── create_profile.go │ │ │ └── router.go │ │ └── kafka_consume │ │ │ └── consumer.go │ ├── adapter │ │ ├── redis │ │ │ └── redis.go │ │ ├── kafka_produce │ │ │ └── produce.go │ │ └── postgres │ │ │ └── postgres.go │ └── usecase │ │ ├── get_profile.go │ │ ├── usecase.go │ │ └── create_profile.go ├── pkg │ ├── transaction │ │ └── wrap.go │ ├── render │ │ └── json.go │ ├── httpserver │ │ └── httpserver.go │ ├── logger │ │ └── logger.go │ ├── otel │ │ └── otel.go │ └── metrics │ │ └── http_server.go ├── go.mod ├── config │ └── config.go ├── cmd │ └── app │ │ └── main.go └── go.sum ├── 7-layers-cqrs ├── internal │ ├── domain │ │ ├── errors.go │ │ └── profile.go │ ├── dto │ │ ├── get_profile.go │ │ └── create_profile.go │ ├── controller │ │ ├── http │ │ │ ├── handlers.go │ │ │ ├── get_profile.go │ │ │ ├── create_profile.go │ │ │ └── router.go │ │ └── kafka_consume │ │ │ └── consumer.go │ ├── adapter │ │ ├── redis │ │ │ └── redis.go │ │ ├── kafka_produce │ │ │ └── produce.go │ │ └── postgres │ │ │ └── postgres.go │ └── usecase │ │ ├── get_profile.go │ │ ├── create_profile.go │ │ └── usecase.go ├── pkg │ ├── transaction │ │ └── wrap.go │ ├── render │ │ └── json.go │ ├── httpserver │ │ └── httpserver.go │ ├── logger │ │ └── logger.go │ ├── otel │ │ └── otel.go │ └── metrics │ │ └── http_server.go ├── go.mod ├── config │ └── config.go ├── cmd │ └── app │ │ └── main.go └── go.sum ├── 8-vertical-slices ├── internal │ ├── domain │ │ ├── errors.go │ │ └── profile.go │ ├── profile │ │ ├── get_profile │ │ │ ├── dto.go │ │ │ ├── http_v1.go │ │ │ └── usecase.go │ │ └── create_profile │ │ │ ├── dto.go │ │ │ ├── http_v1.go │ │ │ ├── usecase.go │ │ │ └── consumer.go │ ├── adapter │ │ ├── redis │ │ │ └── redis.go │ │ ├── kafka_produce │ │ │ └── produce.go │ │ └── postgres │ │ │ └── postgres.go │ └── controller │ │ └── http │ │ └── router.go ├── pkg │ ├── transaction │ │ └── wrap.go │ ├── render │ │ └── json.go │ ├── httpserver │ │ └── httpserver.go │ ├── logger │ │ └── logger.go │ ├── otel │ │ └── otel.go │ └── metrics │ │ └── http_server.go ├── config │ └── config.go ├── go.mod ├── cmd │ └── app │ │ └── main.go └── go.sum ├── 1-handler-first ├── pkg │ ├── transaction │ │ └── wrap.go │ ├── render │ │ └── json.go │ ├── httpserver │ │ └── httpserver.go │ ├── logger │ │ └── logger.go │ ├── otel │ │ └── otel.go │ └── metrics │ │ └── http_server.go ├── internal │ ├── model │ │ └── profile.go │ ├── redis │ │ └── redis.go │ ├── kafka_produce │ │ └── produce.go │ ├── server │ │ ├── get_profile.go │ │ ├── handlers.go │ │ ├── router.go │ │ └── create_profile.go │ └── postgres │ │ └── postgres.go ├── go.mod ├── config │ └── config.go ├── cmd │ └── app │ │ └── main.go └── go.sum ├── 2-service-first ├── pkg │ ├── transaction │ │ └── wrap.go │ ├── render │ │ └── json.go │ ├── httpserver │ │ └── httpserver.go │ ├── logger │ │ └── logger.go │ ├── otel │ │ └── otel.go │ └── metrics │ │ └── http_server.go ├── internal │ ├── server │ │ ├── handlers.go │ │ ├── get_profile.go │ │ ├── create_profile.go │ │ └── router.go │ ├── model │ │ └── profile.go │ ├── redis │ │ └── redis.go │ ├── kafka_produce │ │ └── produce.go │ ├── profile_service │ │ ├── get_profile.go │ │ ├── service.go │ │ └── create_profile.go │ ├── kafka_consume │ │ └── consumer.go │ └── postgres │ │ └── postgres.go ├── go.mod ├── config │ └── config.go └── cmd │ └── app │ └── main.go └── 3-service-hell ├── pkg ├── transaction │ └── wrap.go ├── render │ └── json.go ├── httpserver │ └── httpserver.go ├── logger │ └── logger.go ├── otel │ └── otel.go └── metrics │ └── http_server.go ├── internal ├── server │ ├── handlers.go │ ├── get_profile.go │ ├── create_profile.go │ └── router.go ├── message_service │ ├── service.go │ └── send_message.go ├── model │ └── profile.go ├── redis │ └── redis.go ├── kafka_produce │ └── produce.go ├── profile_service │ ├── get_profile.go │ ├── service.go │ └── create_profile.go ├── kafka_consume │ └── consumer.go └── postgres │ └── postgres.go ├── go.mod ├── go.sum ├── config └── config.go └── cmd └── app └── main.go /4-layers/internal/domain/errors.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrAlreadyExists = errors.New("already exists") 7 | ErrUUIDInvalid = errors.New("invalid UUID format") 8 | ) 9 | -------------------------------------------------------------------------------- /5-layers-dto/internal/domain/errors.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrAlreadyExists = errors.New("already exists") 7 | ErrUUIDInvalid = errors.New("invalid UUID format") 8 | ) 9 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/domain/errors.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrAlreadyExists = errors.New("already exists") 7 | ErrUUIDInvalid = errors.New("invalid UUID format") 8 | ) 9 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/domain/errors.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrAlreadyExists = errors.New("already exists") 7 | ErrUUIDInvalid = errors.New("invalid UUID format") 8 | ) 9 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/domain/errors.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrAlreadyExists = errors.New("already exists") 7 | ErrUUIDInvalid = errors.New("invalid UUID format") 8 | ) 9 | -------------------------------------------------------------------------------- /4-layers/pkg/transaction/wrap.go: -------------------------------------------------------------------------------- 1 | package transaction 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func Wrap(ctx context.Context, fn func(context.Context) error) error { 8 | // Обобщённая функция для обёртки транзакций 9 | 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /5-layers-dto/pkg/transaction/wrap.go: -------------------------------------------------------------------------------- 1 | package transaction 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func Wrap(ctx context.Context, fn func(context.Context) error) error { 8 | // Обобщённая функция для обёртки транзакций 9 | 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /6-layers-ddd/pkg/transaction/wrap.go: -------------------------------------------------------------------------------- 1 | package transaction 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func Wrap(ctx context.Context, fn func(context.Context) error) error { 8 | // Обобщённая функция для обёртки транзакций 9 | 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /1-handler-first/pkg/transaction/wrap.go: -------------------------------------------------------------------------------- 1 | package transaction 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func Wrap(ctx context.Context, fn func(context.Context) error) error { 8 | // Обобщённая функция для обёртки транзакций 9 | 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /2-service-first/pkg/transaction/wrap.go: -------------------------------------------------------------------------------- 1 | package transaction 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func Wrap(ctx context.Context, fn func(context.Context) error) error { 8 | // Обобщённая функция для обёртки транзакций 9 | 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /3-service-hell/pkg/transaction/wrap.go: -------------------------------------------------------------------------------- 1 | package transaction 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func Wrap(ctx context.Context, fn func(context.Context) error) error { 8 | // Обобщённая функция для обёртки транзакций 9 | 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /7-layers-cqrs/pkg/transaction/wrap.go: -------------------------------------------------------------------------------- 1 | package transaction 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func Wrap(ctx context.Context, fn func(context.Context) error) error { 8 | // Обобщённая функция для обёртки транзакций 9 | 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /8-vertical-slices/pkg/transaction/wrap.go: -------------------------------------------------------------------------------- 1 | package transaction 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func Wrap(ctx context.Context, fn func(context.Context) error) error { 8 | // Обобщённая функция для обёртки транзакций 9 | 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /5-layers-dto/internal/dto/get_profile.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "github.com/golang-school/evolution/5-layers-dto/internal/domain" 5 | ) 6 | 7 | type GetProfileOutput struct { 8 | domain.Profile 9 | } 10 | 11 | type GetProfileInput struct { 12 | ID string 13 | } 14 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/dto/get_profile.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "github.com/golang-school/evolution/6-layers-ddd/internal/domain" 5 | ) 6 | 7 | type GetProfileOutput struct { 8 | domain.Profile 9 | } 10 | 11 | type GetProfileInput struct { 12 | ID string 13 | } 14 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/dto/get_profile.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "github.com/golang-school/evolution/7-layers-cqrs/internal/domain" 5 | ) 6 | 7 | type GetProfileOutput struct { 8 | domain.Profile 9 | } 10 | 11 | type GetProfileInput struct { 12 | ID string 13 | } 14 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/profile/get_profile/dto.go: -------------------------------------------------------------------------------- 1 | package get_profile 2 | 3 | import ( 4 | "github.com/golang-school/evolution/8-vertical-slices/internal/domain" 5 | ) 6 | 7 | type Output struct { 8 | domain.Profile 9 | } 10 | 11 | type Input struct { 12 | ID string 13 | } 14 | -------------------------------------------------------------------------------- /5-layers-dto/internal/dto/create_profile.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | ) 6 | 7 | type CreateProfileOutput struct { 8 | ID uuid.UUID `json:"id"` 9 | } 10 | 11 | type CreateProfileInput struct { 12 | Name string `json:"name"` 13 | Age int `json:"age"` 14 | Email string `json:"email"` 15 | } 16 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/dto/create_profile.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | ) 6 | 7 | type CreateProfileOutput struct { 8 | ID uuid.UUID `json:"id"` 9 | } 10 | 11 | type CreateProfileInput struct { 12 | Name string `json:"name"` 13 | Age int `json:"age"` 14 | Email string `json:"email"` 15 | } 16 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/dto/create_profile.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | ) 6 | 7 | type CreateProfileOutput struct { 8 | ID uuid.UUID `json:"id"` 9 | } 10 | 11 | type CreateProfileInput struct { 12 | Name string `json:"name"` 13 | Age int `json:"age"` 14 | Email string `json:"email"` 15 | } 16 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/profile/create_profile/dto.go: -------------------------------------------------------------------------------- 1 | package create_profile 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | ) 6 | 7 | type Output struct { 8 | ID uuid.UUID `json:"id"` 9 | } 10 | 11 | type Input struct { 12 | Name string `json:"name"` 13 | Age int `json:"age"` 14 | Email string `json:"email"` 15 | } 16 | -------------------------------------------------------------------------------- /4-layers/internal/controller/http/handlers.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "github.com/golang-school/evolution/4-layers/internal/usecase" 5 | ) 6 | 7 | // Обработчики HTTP запросов 8 | type Handlers struct { 9 | profileService *usecase.Profile 10 | } 11 | 12 | func NewHandlers(profileService *usecase.Profile) *Handlers { 13 | return &Handlers{ 14 | profileService: profileService, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /5-layers-dto/internal/controller/http/handlers.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "github.com/golang-school/evolution/5-layers-dto/internal/usecase" 5 | ) 6 | 7 | // Обработчики HTTP запросов 8 | type Handlers struct { 9 | profileService *usecase.Profile 10 | } 11 | 12 | func NewHandlers(profileService *usecase.Profile) *Handlers { 13 | return &Handlers{ 14 | profileService: profileService, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/controller/http/handlers.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "github.com/golang-school/evolution/6-layers-ddd/internal/usecase" 5 | ) 6 | 7 | // Обработчики HTTP запросов 8 | type Handlers struct { 9 | profileService *usecase.Profile 10 | } 11 | 12 | func NewHandlers(profileService *usecase.Profile) *Handlers { 13 | return &Handlers{ 14 | profileService: profileService, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/controller/http/handlers.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "github.com/golang-school/evolution/7-layers-cqrs/internal/usecase" 5 | ) 6 | 7 | // Обработчики HTTP запросов 8 | type Handlers struct { 9 | profileService *usecase.Profile 10 | } 11 | 12 | func NewHandlers(profileService *usecase.Profile) *Handlers { 13 | return &Handlers{ 14 | profileService: profileService, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /3-service-hell/internal/server/handlers.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/golang-school/evolution/3-service-hell/internal/profile_service" 5 | ) 6 | 7 | // Обработчики HTTP запросов 8 | type Handlers struct { 9 | profileService *profile_service.Profile 10 | } 11 | 12 | func NewHandlers(profileService *profile_service.Profile) *Handlers { 13 | return &Handlers{ 14 | profileService: profileService, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /4-layers/pkg/render/json.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | func JSON(w http.ResponseWriter, body any, statusCode int) { 9 | w.Header().Set("Content-Type", "application/json") 10 | 11 | w.WriteHeader(statusCode) 12 | 13 | err := json.NewEncoder(w).Encode(body) 14 | if err != nil { 15 | http.Error(w, "json encode error", http.StatusBadRequest) 16 | panic(err) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2-service-first/internal/server/handlers.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/golang-school/evolution/2-service-first/internal/profile_service" 5 | ) 6 | 7 | // Обработчики HTTP запросов 8 | type Handlers struct { 9 | profileService *profile_service.Profile 10 | } 11 | 12 | func NewHandlers(profileService *profile_service.Profile) *Handlers { 13 | return &Handlers{ 14 | profileService: profileService, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /3-service-hell/pkg/render/json.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | func JSON(w http.ResponseWriter, body any, statusCode int) { 9 | w.Header().Set("Content-Type", "application/json") 10 | 11 | w.WriteHeader(statusCode) 12 | 13 | err := json.NewEncoder(w).Encode(body) 14 | if err != nil { 15 | http.Error(w, "json encode error", http.StatusBadRequest) 16 | panic(err) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /5-layers-dto/pkg/render/json.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | func JSON(w http.ResponseWriter, body any, statusCode int) { 9 | w.Header().Set("Content-Type", "application/json") 10 | 11 | w.WriteHeader(statusCode) 12 | 13 | err := json.NewEncoder(w).Encode(body) 14 | if err != nil { 15 | http.Error(w, "json encode error", http.StatusBadRequest) 16 | panic(err) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /6-layers-ddd/pkg/render/json.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | func JSON(w http.ResponseWriter, body any, statusCode int) { 9 | w.Header().Set("Content-Type", "application/json") 10 | 11 | w.WriteHeader(statusCode) 12 | 13 | err := json.NewEncoder(w).Encode(body) 14 | if err != nil { 15 | http.Error(w, "json encode error", http.StatusBadRequest) 16 | panic(err) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /7-layers-cqrs/pkg/render/json.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | func JSON(w http.ResponseWriter, body any, statusCode int) { 9 | w.Header().Set("Content-Type", "application/json") 10 | 11 | w.WriteHeader(statusCode) 12 | 13 | err := json.NewEncoder(w).Encode(body) 14 | if err != nil { 15 | http.Error(w, "json encode error", http.StatusBadRequest) 16 | panic(err) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /1-handler-first/pkg/render/json.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | func JSON(w http.ResponseWriter, body any, statusCode int) { 9 | w.Header().Set("Content-Type", "application/json") 10 | 11 | w.WriteHeader(statusCode) 12 | 13 | err := json.NewEncoder(w).Encode(body) 14 | if err != nil { 15 | http.Error(w, "json encode error", http.StatusBadRequest) 16 | panic(err) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2-service-first/pkg/render/json.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | func JSON(w http.ResponseWriter, body any, statusCode int) { 9 | w.Header().Set("Content-Type", "application/json") 10 | 11 | w.WriteHeader(statusCode) 12 | 13 | err := json.NewEncoder(w).Encode(body) 14 | if err != nil { 15 | http.Error(w, "json encode error", http.StatusBadRequest) 16 | panic(err) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /8-vertical-slices/pkg/render/json.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | func JSON(w http.ResponseWriter, body any, statusCode int) { 9 | w.Header().Set("Content-Type", "application/json") 10 | 11 | w.WriteHeader(statusCode) 12 | 13 | err := json.NewEncoder(w).Encode(body) 14 | if err != nil { 15 | http.Error(w, "json encode error", http.StatusBadRequest) 16 | panic(err) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /4-layers/pkg/httpserver/httpserver.go: -------------------------------------------------------------------------------- 1 | package httpserver 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type Config struct { 8 | Port string `default:"8080" envconfig:"HTTP_PORT"` 9 | } 10 | 11 | type Server struct { 12 | server *http.Server 13 | } 14 | 15 | func New(handler http.Handler, c Config) *Server { 16 | // Настраиваем порт и таймауты 17 | 18 | return &Server{} 19 | } 20 | 21 | func (s *Server) Close() { 22 | // Shutdown 23 | } 24 | -------------------------------------------------------------------------------- /1-handler-first/pkg/httpserver/httpserver.go: -------------------------------------------------------------------------------- 1 | package httpserver 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type Config struct { 8 | Port string `default:"8080" envconfig:"HTTP_PORT"` 9 | } 10 | 11 | type Server struct { 12 | server *http.Server 13 | } 14 | 15 | func New(handler http.Handler, c Config) *Server { 16 | // Настраиваем порт и таймауты 17 | 18 | return &Server{} 19 | } 20 | 21 | func (s *Server) Close() { 22 | // Shutdown 23 | } 24 | -------------------------------------------------------------------------------- /2-service-first/pkg/httpserver/httpserver.go: -------------------------------------------------------------------------------- 1 | package httpserver 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type Config struct { 8 | Port string `default:"8080" envconfig:"HTTP_PORT"` 9 | } 10 | 11 | type Server struct { 12 | server *http.Server 13 | } 14 | 15 | func New(handler http.Handler, c Config) *Server { 16 | // Настраиваем порт и таймауты 17 | 18 | return &Server{} 19 | } 20 | 21 | func (s *Server) Close() { 22 | // Shutdown 23 | } 24 | -------------------------------------------------------------------------------- /3-service-hell/pkg/httpserver/httpserver.go: -------------------------------------------------------------------------------- 1 | package httpserver 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type Config struct { 8 | Port string `default:"8080" envconfig:"HTTP_PORT"` 9 | } 10 | 11 | type Server struct { 12 | server *http.Server 13 | } 14 | 15 | func New(handler http.Handler, c Config) *Server { 16 | // Настраиваем порт и таймауты 17 | 18 | return &Server{} 19 | } 20 | 21 | func (s *Server) Close() { 22 | // Shutdown 23 | } 24 | -------------------------------------------------------------------------------- /5-layers-dto/pkg/httpserver/httpserver.go: -------------------------------------------------------------------------------- 1 | package httpserver 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type Config struct { 8 | Port string `default:"8080" envconfig:"HTTP_PORT"` 9 | } 10 | 11 | type Server struct { 12 | server *http.Server 13 | } 14 | 15 | func New(handler http.Handler, c Config) *Server { 16 | // Настраиваем порт и таймауты 17 | 18 | return &Server{} 19 | } 20 | 21 | func (s *Server) Close() { 22 | // Shutdown 23 | } 24 | -------------------------------------------------------------------------------- /6-layers-ddd/pkg/httpserver/httpserver.go: -------------------------------------------------------------------------------- 1 | package httpserver 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type Config struct { 8 | Port string `default:"8080" envconfig:"HTTP_PORT"` 9 | } 10 | 11 | type Server struct { 12 | server *http.Server 13 | } 14 | 15 | func New(handler http.Handler, c Config) *Server { 16 | // Настраиваем порт и таймауты 17 | 18 | return &Server{} 19 | } 20 | 21 | func (s *Server) Close() { 22 | // Shutdown 23 | } 24 | -------------------------------------------------------------------------------- /7-layers-cqrs/pkg/httpserver/httpserver.go: -------------------------------------------------------------------------------- 1 | package httpserver 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type Config struct { 8 | Port string `default:"8080" envconfig:"HTTP_PORT"` 9 | } 10 | 11 | type Server struct { 12 | server *http.Server 13 | } 14 | 15 | func New(handler http.Handler, c Config) *Server { 16 | // Настраиваем порт и таймауты 17 | 18 | return &Server{} 19 | } 20 | 21 | func (s *Server) Close() { 22 | // Shutdown 23 | } 24 | -------------------------------------------------------------------------------- /4-layers/pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | type Config struct { 4 | AppName string `envconfig:"APP_NAME" required:"true"` 5 | AppVersion string `envconfig:"APP_VERSION" required:"true"` 6 | Level string `default:"error" envconfig:"LOGGER_LEVEL"` 7 | PrettyConsole bool `default:"false" envconfig:"LOGGER_PRETTY_CONSOLE"` 8 | } 9 | 10 | func Init(c Config) { 11 | // Настраиваем level и форматирование 12 | } 13 | -------------------------------------------------------------------------------- /8-vertical-slices/pkg/httpserver/httpserver.go: -------------------------------------------------------------------------------- 1 | package httpserver 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type Config struct { 8 | Port string `default:"8080" envconfig:"HTTP_PORT"` 9 | } 10 | 11 | type Server struct { 12 | server *http.Server 13 | } 14 | 15 | func New(handler http.Handler, c Config) *Server { 16 | // Настраиваем порт и таймауты 17 | 18 | return &Server{} 19 | } 20 | 21 | func (s *Server) Close() { 22 | // Shutdown 23 | } 24 | -------------------------------------------------------------------------------- /1-handler-first/pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | type Config struct { 4 | AppName string `envconfig:"APP_NAME" required:"true"` 5 | AppVersion string `envconfig:"APP_VERSION" required:"true"` 6 | Level string `default:"error" envconfig:"LOGGER_LEVEL"` 7 | PrettyConsole bool `default:"false" envconfig:"LOGGER_PRETTY_CONSOLE"` 8 | } 9 | 10 | func Init(c Config) { 11 | // Настраиваем level и форматирование 12 | } 13 | -------------------------------------------------------------------------------- /2-service-first/pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | type Config struct { 4 | AppName string `envconfig:"APP_NAME" required:"true"` 5 | AppVersion string `envconfig:"APP_VERSION" required:"true"` 6 | Level string `default:"error" envconfig:"LOGGER_LEVEL"` 7 | PrettyConsole bool `default:"false" envconfig:"LOGGER_PRETTY_CONSOLE"` 8 | } 9 | 10 | func Init(c Config) { 11 | // Настраиваем level и форматирование 12 | } 13 | -------------------------------------------------------------------------------- /3-service-hell/pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | type Config struct { 4 | AppName string `envconfig:"APP_NAME" required:"true"` 5 | AppVersion string `envconfig:"APP_VERSION" required:"true"` 6 | Level string `default:"error" envconfig:"LOGGER_LEVEL"` 7 | PrettyConsole bool `default:"false" envconfig:"LOGGER_PRETTY_CONSOLE"` 8 | } 9 | 10 | func Init(c Config) { 11 | // Настраиваем level и форматирование 12 | } 13 | -------------------------------------------------------------------------------- /5-layers-dto/pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | type Config struct { 4 | AppName string `envconfig:"APP_NAME" required:"true"` 5 | AppVersion string `envconfig:"APP_VERSION" required:"true"` 6 | Level string `default:"error" envconfig:"LOGGER_LEVEL"` 7 | PrettyConsole bool `default:"false" envconfig:"LOGGER_PRETTY_CONSOLE"` 8 | } 9 | 10 | func Init(c Config) { 11 | // Настраиваем level и форматирование 12 | } 13 | -------------------------------------------------------------------------------- /6-layers-ddd/pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | type Config struct { 4 | AppName string `envconfig:"APP_NAME" required:"true"` 5 | AppVersion string `envconfig:"APP_VERSION" required:"true"` 6 | Level string `default:"error" envconfig:"LOGGER_LEVEL"` 7 | PrettyConsole bool `default:"false" envconfig:"LOGGER_PRETTY_CONSOLE"` 8 | } 9 | 10 | func Init(c Config) { 11 | // Настраиваем level и форматирование 12 | } 13 | -------------------------------------------------------------------------------- /7-layers-cqrs/pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | type Config struct { 4 | AppName string `envconfig:"APP_NAME" required:"true"` 5 | AppVersion string `envconfig:"APP_VERSION" required:"true"` 6 | Level string `default:"error" envconfig:"LOGGER_LEVEL"` 7 | PrettyConsole bool `default:"false" envconfig:"LOGGER_PRETTY_CONSOLE"` 8 | } 9 | 10 | func Init(c Config) { 11 | // Настраиваем level и форматирование 12 | } 13 | -------------------------------------------------------------------------------- /8-vertical-slices/pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | type Config struct { 4 | AppName string `envconfig:"APP_NAME" required:"true"` 5 | AppVersion string `envconfig:"APP_VERSION" required:"true"` 6 | Level string `default:"error" envconfig:"LOGGER_LEVEL"` 7 | PrettyConsole bool `default:"false" envconfig:"LOGGER_PRETTY_CONSOLE"` 8 | } 9 | 10 | func Init(c Config) { 11 | // Настраиваем level и форматирование 12 | } 13 | -------------------------------------------------------------------------------- /3-service-hell/internal/message_service/service.go: -------------------------------------------------------------------------------- 1 | package message_service 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/3-service-hell/internal/kafka_produce" 7 | ) 8 | 9 | type Kafka interface { 10 | Produce(ctx context.Context, msgs ...kafka_produce.Message) error 11 | } 12 | 13 | type MessageService struct { 14 | kafka Kafka 15 | } 16 | 17 | func NewMessageService(kafka *kafka_produce.Producer) *MessageService { 18 | return &MessageService{ 19 | kafka: kafka, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /4-layers/internal/domain/profile.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/google/uuid" 7 | ) 8 | 9 | type Profile struct { 10 | ID uuid.UUID `json:"id"` 11 | CreatedAt time.Time `json:"created_at"` 12 | Name string `json:"name" validate:"required,min=3,max=64"` 13 | Age int `json:"age" validate:"required,min=18,max=120"` 14 | Email string `json:"email" validate:"email"` 15 | } 16 | 17 | func (p Profile) Validate() error { 18 | // валидация 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /1-handler-first/internal/model/profile.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/google/uuid" 7 | ) 8 | 9 | type Profile struct { 10 | ID uuid.UUID `json:"id"` 11 | CreatedAt time.Time `json:"created_at"` 12 | Name string `json:"name" validate:"required,min=3,max=64"` 13 | Age int `json:"age" validate:"required,min=18,max=120"` 14 | Email string `json:"email" validate:"email"` 15 | } 16 | 17 | func (p Profile) Validate() error { 18 | // валидация 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /2-service-first/internal/model/profile.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/google/uuid" 7 | ) 8 | 9 | type Profile struct { 10 | ID uuid.UUID `json:"id"` 11 | CreatedAt time.Time `json:"created_at"` 12 | Name string `json:"name" validate:"required,min=3,max=64"` 13 | Age int `json:"age" validate:"required,min=18,max=120"` 14 | Email string `json:"email" validate:"email"` 15 | } 16 | 17 | func (p Profile) Validate() error { 18 | // валидация 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /3-service-hell/internal/model/profile.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/google/uuid" 7 | ) 8 | 9 | type Profile struct { 10 | ID uuid.UUID `json:"id"` 11 | CreatedAt time.Time `json:"created_at"` 12 | Name string `json:"name" validate:"required,min=3,max=64"` 13 | Age int `json:"age" validate:"required,min=18,max=120"` 14 | Email string `json:"email" validate:"email"` 15 | } 16 | 17 | func (p Profile) Validate() error { 18 | // валидация 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /5-layers-dto/internal/domain/profile.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/google/uuid" 7 | ) 8 | 9 | type Profile struct { 10 | ID uuid.UUID `json:"id"` 11 | CreatedAt time.Time `json:"created_at"` 12 | Name string `json:"name" validate:"required,min=3,max=64"` 13 | Age int `json:"age" validate:"required,min=18,max=120"` 14 | Email string `json:"email" validate:"email"` 15 | } 16 | 17 | func (p Profile) Validate() error { 18 | // валидация 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /4-layers/internal/controller/http/get_profile.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/4-layers/pkg/render" 7 | 8 | "github.com/go-chi/chi/v5" 9 | ) 10 | 11 | func (h *Handlers) GetProfile(w http.ResponseWriter, r *http.Request) { 12 | id := chi.URLParam(r, "id") 13 | 14 | output, err := h.profileService.GetProfile(r.Context(), id) 15 | if err != nil { 16 | http.Error(w, err.Error(), http.StatusBadRequest) 17 | 18 | return 19 | } 20 | 21 | render.JSON(w, output, http.StatusOK) 22 | } 23 | -------------------------------------------------------------------------------- /3-service-hell/internal/message_service/send_message.go: -------------------------------------------------------------------------------- 1 | package message_service 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/3-service-hell/internal/kafka_produce" 8 | ) 9 | 10 | func (m *MessageService) SendMessage(ctx context.Context, msgs ...kafka_produce.Message) error { 11 | // Что-то делаем и... 12 | 13 | // отправляем в Kafka событие создания профиля 14 | err := m.kafka.Produce(ctx, msgs...) 15 | if err != nil { 16 | return fmt.Errorf("kafka produce: %w", err) 17 | } 18 | 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /3-service-hell/internal/server/get_profile.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/3-service-hell/pkg/render" 7 | 8 | "github.com/go-chi/chi/v5" 9 | ) 10 | 11 | func (h *Handlers) GetProfile(w http.ResponseWriter, r *http.Request) { 12 | id := chi.URLParam(r, "id") 13 | 14 | output, err := h.profileService.GetProfile(r.Context(), id) 15 | if err != nil { 16 | http.Error(w, err.Error(), http.StatusBadRequest) 17 | 18 | return 19 | } 20 | 21 | render.JSON(w, output, http.StatusOK) 22 | } 23 | -------------------------------------------------------------------------------- /2-service-first/internal/server/get_profile.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/2-service-first/pkg/render" 7 | 8 | "github.com/go-chi/chi/v5" 9 | ) 10 | 11 | func (h *Handlers) GetProfile(w http.ResponseWriter, r *http.Request) { 12 | id := chi.URLParam(r, "id") 13 | 14 | output, err := h.profileService.GetProfile(r.Context(), id) 15 | if err != nil { 16 | http.Error(w, err.Error(), http.StatusBadRequest) 17 | 18 | return 19 | } 20 | 21 | render.JSON(w, output, http.StatusOK) 22 | } 23 | -------------------------------------------------------------------------------- /4-layers/pkg/otel/otel.go: -------------------------------------------------------------------------------- 1 | package otel 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | AppName string `envconfig:"APP_NAME"` 9 | AppVersion string `envconfig:"APP_VERSION"` 10 | Endpoint string `envconfig:"OTEL_ENDPOINT"` 11 | Namespace string `envconfig:"OTEL_NAMESPACE"` 12 | InstanceID string `envconfig:"OTEL_INSTANCE_ID"` 13 | Ratio float64 `default:"1.0" envconfig:"OTEL_RATIO"` 14 | } 15 | 16 | func Init(ctx context.Context, c Config) error { 17 | // Делаем настройки 18 | 19 | return nil 20 | } 21 | 22 | func Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /1-handler-first/pkg/otel/otel.go: -------------------------------------------------------------------------------- 1 | package otel 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | AppName string `envconfig:"APP_NAME"` 9 | AppVersion string `envconfig:"APP_VERSION"` 10 | Endpoint string `envconfig:"OTEL_ENDPOINT"` 11 | Namespace string `envconfig:"OTEL_NAMESPACE"` 12 | InstanceID string `envconfig:"OTEL_INSTANCE_ID"` 13 | Ratio float64 `default:"1.0" envconfig:"OTEL_RATIO"` 14 | } 15 | 16 | func Init(ctx context.Context, c Config) error { 17 | // Делаем настройки 18 | 19 | return nil 20 | } 21 | 22 | func Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /2-service-first/pkg/otel/otel.go: -------------------------------------------------------------------------------- 1 | package otel 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | AppName string `envconfig:"APP_NAME"` 9 | AppVersion string `envconfig:"APP_VERSION"` 10 | Endpoint string `envconfig:"OTEL_ENDPOINT"` 11 | Namespace string `envconfig:"OTEL_NAMESPACE"` 12 | InstanceID string `envconfig:"OTEL_INSTANCE_ID"` 13 | Ratio float64 `default:"1.0" envconfig:"OTEL_RATIO"` 14 | } 15 | 16 | func Init(ctx context.Context, c Config) error { 17 | // Делаем настройки 18 | 19 | return nil 20 | } 21 | 22 | func Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /3-service-hell/pkg/otel/otel.go: -------------------------------------------------------------------------------- 1 | package otel 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | AppName string `envconfig:"APP_NAME"` 9 | AppVersion string `envconfig:"APP_VERSION"` 10 | Endpoint string `envconfig:"OTEL_ENDPOINT"` 11 | Namespace string `envconfig:"OTEL_NAMESPACE"` 12 | InstanceID string `envconfig:"OTEL_INSTANCE_ID"` 13 | Ratio float64 `default:"1.0" envconfig:"OTEL_RATIO"` 14 | } 15 | 16 | func Init(ctx context.Context, c Config) error { 17 | // Делаем настройки 18 | 19 | return nil 20 | } 21 | 22 | func Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /5-layers-dto/pkg/otel/otel.go: -------------------------------------------------------------------------------- 1 | package otel 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | AppName string `envconfig:"APP_NAME"` 9 | AppVersion string `envconfig:"APP_VERSION"` 10 | Endpoint string `envconfig:"OTEL_ENDPOINT"` 11 | Namespace string `envconfig:"OTEL_NAMESPACE"` 12 | InstanceID string `envconfig:"OTEL_INSTANCE_ID"` 13 | Ratio float64 `default:"1.0" envconfig:"OTEL_RATIO"` 14 | } 15 | 16 | func Init(ctx context.Context, c Config) error { 17 | // Делаем настройки 18 | 19 | return nil 20 | } 21 | 22 | func Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /6-layers-ddd/pkg/otel/otel.go: -------------------------------------------------------------------------------- 1 | package otel 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | AppName string `envconfig:"APP_NAME"` 9 | AppVersion string `envconfig:"APP_VERSION"` 10 | Endpoint string `envconfig:"OTEL_ENDPOINT"` 11 | Namespace string `envconfig:"OTEL_NAMESPACE"` 12 | InstanceID string `envconfig:"OTEL_INSTANCE_ID"` 13 | Ratio float64 `default:"1.0" envconfig:"OTEL_RATIO"` 14 | } 15 | 16 | func Init(ctx context.Context, c Config) error { 17 | // Делаем настройки 18 | 19 | return nil 20 | } 21 | 22 | func Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /7-layers-cqrs/pkg/otel/otel.go: -------------------------------------------------------------------------------- 1 | package otel 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | AppName string `envconfig:"APP_NAME"` 9 | AppVersion string `envconfig:"APP_VERSION"` 10 | Endpoint string `envconfig:"OTEL_ENDPOINT"` 11 | Namespace string `envconfig:"OTEL_NAMESPACE"` 12 | InstanceID string `envconfig:"OTEL_INSTANCE_ID"` 13 | Ratio float64 `default:"1.0" envconfig:"OTEL_RATIO"` 14 | } 15 | 16 | func Init(ctx context.Context, c Config) error { 17 | // Делаем настройки 18 | 19 | return nil 20 | } 21 | 22 | func Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /8-vertical-slices/pkg/otel/otel.go: -------------------------------------------------------------------------------- 1 | package otel 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | AppName string `envconfig:"APP_NAME"` 9 | AppVersion string `envconfig:"APP_VERSION"` 10 | Endpoint string `envconfig:"OTEL_ENDPOINT"` 11 | Namespace string `envconfig:"OTEL_NAMESPACE"` 12 | InstanceID string `envconfig:"OTEL_INSTANCE_ID"` 13 | Ratio float64 `default:"1.0" envconfig:"OTEL_RATIO"` 14 | } 15 | 16 | func Init(ctx context.Context, c Config) error { 17 | // Делаем настройки 18 | 19 | return nil 20 | } 21 | 22 | func Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/profile/get_profile/http_v1.go: -------------------------------------------------------------------------------- 1 | package get_profile 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/go-chi/chi/v5" 7 | 8 | "github.com/golang-school/evolution/8-vertical-slices/pkg/render" 9 | ) 10 | 11 | var usecase *Usecase 12 | 13 | func HTTPv1(w http.ResponseWriter, r *http.Request) { 14 | input := Input{ 15 | ID: chi.URLParam(r, "id"), 16 | } 17 | 18 | output, err := usecase.GetProfile(r.Context(), input) 19 | if err != nil { 20 | http.Error(w, err.Error(), http.StatusBadRequest) 21 | 22 | return 23 | } 24 | 25 | render.JSON(w, output, http.StatusOK) 26 | } 27 | -------------------------------------------------------------------------------- /4-layers/pkg/metrics/http_server.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | ) 8 | 9 | type HTTPServer struct { 10 | total *prometheus.CounterVec 11 | current *prometheus.GaugeVec 12 | duration *prometheus.HistogramVec 13 | } 14 | 15 | func NewHTTPServer() *HTTPServer { 16 | m := &HTTPServer{} 17 | 18 | // Настройка метрик 19 | 20 | return m 21 | } 22 | 23 | func (m *HTTPServer) TotalInc(method string, code int) {} 24 | 25 | func (m *HTTPServer) CurrentSet(process string, value float64) {} 26 | 27 | func (m *HTTPServer) Duration(method string, startTime time.Time) {} 28 | -------------------------------------------------------------------------------- /1-handler-first/internal/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "context" 4 | 5 | type Config struct { 6 | Addr string `envconfig:"REDIS_ADDR" required:"true"` 7 | Password string `envconfig:"REDIS_PASSWORD"` 8 | DB int `default:"0" envconfig:"REDIS_DB"` 9 | } 10 | 11 | type Client struct{} 12 | 13 | func New(c Config) (*Client, error) { 14 | // Делаем подключение к Redis 15 | return &Client{}, nil 16 | } 17 | 18 | func (c *Client) IsExists(ctx context.Context, idempotencyKey string) bool { 19 | // Проверяем, существует ли ключ в Redis 20 | return false 21 | } 22 | 23 | func (c *Client) Close() { 24 | // Shutdown 25 | } 26 | -------------------------------------------------------------------------------- /2-service-first/internal/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "context" 4 | 5 | type Config struct { 6 | Addr string `envconfig:"REDIS_ADDR" required:"true"` 7 | Password string `envconfig:"REDIS_PASSWORD"` 8 | DB int `default:"0" envconfig:"REDIS_DB"` 9 | } 10 | 11 | type Client struct{} 12 | 13 | func New(c Config) (*Client, error) { 14 | // Делаем подключение к Redis 15 | return &Client{}, nil 16 | } 17 | 18 | func (c *Client) IsExists(ctx context.Context, idempotencyKey string) bool { 19 | // Проверяем, существует ли ключ в Redis 20 | return false 21 | } 22 | 23 | func (c *Client) Close() { 24 | // Shutdown 25 | } 26 | -------------------------------------------------------------------------------- /3-service-hell/internal/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "context" 4 | 5 | type Config struct { 6 | Addr string `envconfig:"REDIS_ADDR" required:"true"` 7 | Password string `envconfig:"REDIS_PASSWORD"` 8 | DB int `default:"0" envconfig:"REDIS_DB"` 9 | } 10 | 11 | type Client struct{} 12 | 13 | func New(c Config) (*Client, error) { 14 | // Делаем подключение к Redis 15 | return &Client{}, nil 16 | } 17 | 18 | func (c *Client) IsExists(ctx context.Context, idempotencyKey string) bool { 19 | // Проверяем, существует ли ключ в Redis 20 | return false 21 | } 22 | 23 | func (c *Client) Close() { 24 | // Shutdown 25 | } 26 | -------------------------------------------------------------------------------- /3-service-hell/pkg/metrics/http_server.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | ) 8 | 9 | type HTTPServer struct { 10 | total *prometheus.CounterVec 11 | current *prometheus.GaugeVec 12 | duration *prometheus.HistogramVec 13 | } 14 | 15 | func NewHTTPServer() *HTTPServer { 16 | m := &HTTPServer{} 17 | 18 | // Настройка метрик 19 | 20 | return m 21 | } 22 | 23 | func (m *HTTPServer) TotalInc(method string, code int) {} 24 | 25 | func (m *HTTPServer) CurrentSet(process string, value float64) {} 26 | 27 | func (m *HTTPServer) Duration(method string, startTime time.Time) {} 28 | -------------------------------------------------------------------------------- /4-layers/internal/adapter/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "context" 4 | 5 | type Config struct { 6 | Addr string `envconfig:"REDIS_ADDR" required:"true"` 7 | Password string `envconfig:"REDIS_PASSWORD"` 8 | DB int `default:"0" envconfig:"REDIS_DB"` 9 | } 10 | 11 | type Client struct{} 12 | 13 | func New(c Config) (*Client, error) { 14 | // Делаем подключение к Redis 15 | return &Client{}, nil 16 | } 17 | 18 | func (c *Client) IsExists(ctx context.Context, idempotencyKey string) bool { 19 | // Проверяем, существует ли ключ в Redis 20 | return false 21 | } 22 | 23 | func (c *Client) Close() { 24 | // Shutdown 25 | } 26 | -------------------------------------------------------------------------------- /5-layers-dto/pkg/metrics/http_server.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | ) 8 | 9 | type HTTPServer struct { 10 | total *prometheus.CounterVec 11 | current *prometheus.GaugeVec 12 | duration *prometheus.HistogramVec 13 | } 14 | 15 | func NewHTTPServer() *HTTPServer { 16 | m := &HTTPServer{} 17 | 18 | // Настройка метрик 19 | 20 | return m 21 | } 22 | 23 | func (m *HTTPServer) TotalInc(method string, code int) {} 24 | 25 | func (m *HTTPServer) CurrentSet(process string, value float64) {} 26 | 27 | func (m *HTTPServer) Duration(method string, startTime time.Time) {} 28 | -------------------------------------------------------------------------------- /6-layers-ddd/pkg/metrics/http_server.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | ) 8 | 9 | type HTTPServer struct { 10 | total *prometheus.CounterVec 11 | current *prometheus.GaugeVec 12 | duration *prometheus.HistogramVec 13 | } 14 | 15 | func NewHTTPServer() *HTTPServer { 16 | m := &HTTPServer{} 17 | 18 | // Настройка метрик 19 | 20 | return m 21 | } 22 | 23 | func (m *HTTPServer) TotalInc(method string, code int) {} 24 | 25 | func (m *HTTPServer) CurrentSet(process string, value float64) {} 26 | 27 | func (m *HTTPServer) Duration(method string, startTime time.Time) {} 28 | -------------------------------------------------------------------------------- /7-layers-cqrs/pkg/metrics/http_server.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | ) 8 | 9 | type HTTPServer struct { 10 | total *prometheus.CounterVec 11 | current *prometheus.GaugeVec 12 | duration *prometheus.HistogramVec 13 | } 14 | 15 | func NewHTTPServer() *HTTPServer { 16 | m := &HTTPServer{} 17 | 18 | // Настройка метрик 19 | 20 | return m 21 | } 22 | 23 | func (m *HTTPServer) TotalInc(method string, code int) {} 24 | 25 | func (m *HTTPServer) CurrentSet(process string, value float64) {} 26 | 27 | func (m *HTTPServer) Duration(method string, startTime time.Time) {} 28 | -------------------------------------------------------------------------------- /1-handler-first/pkg/metrics/http_server.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | ) 8 | 9 | type HTTPServer struct { 10 | total *prometheus.CounterVec 11 | current *prometheus.GaugeVec 12 | duration *prometheus.HistogramVec 13 | } 14 | 15 | func NewHTTPServer() *HTTPServer { 16 | m := &HTTPServer{} 17 | 18 | // Настройка метрик 19 | 20 | return m 21 | } 22 | 23 | func (m *HTTPServer) TotalInc(method string, code int) {} 24 | 25 | func (m *HTTPServer) CurrentSet(process string, value float64) {} 26 | 27 | func (m *HTTPServer) Duration(method string, startTime time.Time) {} 28 | -------------------------------------------------------------------------------- /2-service-first/pkg/metrics/http_server.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | ) 8 | 9 | type HTTPServer struct { 10 | total *prometheus.CounterVec 11 | current *prometheus.GaugeVec 12 | duration *prometheus.HistogramVec 13 | } 14 | 15 | func NewHTTPServer() *HTTPServer { 16 | m := &HTTPServer{} 17 | 18 | // Настройка метрик 19 | 20 | return m 21 | } 22 | 23 | func (m *HTTPServer) TotalInc(method string, code int) {} 24 | 25 | func (m *HTTPServer) CurrentSet(process string, value float64) {} 26 | 27 | func (m *HTTPServer) Duration(method string, startTime time.Time) {} 28 | -------------------------------------------------------------------------------- /5-layers-dto/internal/adapter/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "context" 4 | 5 | type Config struct { 6 | Addr string `envconfig:"REDIS_ADDR" required:"true"` 7 | Password string `envconfig:"REDIS_PASSWORD"` 8 | DB int `default:"0" envconfig:"REDIS_DB"` 9 | } 10 | 11 | type Client struct{} 12 | 13 | func New(c Config) (*Client, error) { 14 | // Делаем подключение к Redis 15 | return &Client{}, nil 16 | } 17 | 18 | func (c *Client) IsExists(ctx context.Context, idempotencyKey string) bool { 19 | // Проверяем, существует ли ключ в Redis 20 | return false 21 | } 22 | 23 | func (c *Client) Close() { 24 | // Shutdown 25 | } 26 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/adapter/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "context" 4 | 5 | type Config struct { 6 | Addr string `envconfig:"REDIS_ADDR" required:"true"` 7 | Password string `envconfig:"REDIS_PASSWORD"` 8 | DB int `default:"0" envconfig:"REDIS_DB"` 9 | } 10 | 11 | type Client struct{} 12 | 13 | func New(c Config) (*Client, error) { 14 | // Делаем подключение к Redis 15 | return &Client{}, nil 16 | } 17 | 18 | func (c *Client) IsExists(ctx context.Context, idempotencyKey string) bool { 19 | // Проверяем, существует ли ключ в Redis 20 | return false 21 | } 22 | 23 | func (c *Client) Close() { 24 | // Shutdown 25 | } 26 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/adapter/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "context" 4 | 5 | type Config struct { 6 | Addr string `envconfig:"REDIS_ADDR" required:"true"` 7 | Password string `envconfig:"REDIS_PASSWORD"` 8 | DB int `default:"0" envconfig:"REDIS_DB"` 9 | } 10 | 11 | type Client struct{} 12 | 13 | func New(c Config) (*Client, error) { 14 | // Делаем подключение к Redis 15 | return &Client{}, nil 16 | } 17 | 18 | func (c *Client) IsExists(ctx context.Context, idempotencyKey string) bool { 19 | // Проверяем, существует ли ключ в Redis 20 | return false 21 | } 22 | 23 | func (c *Client) Close() { 24 | // Shutdown 25 | } 26 | -------------------------------------------------------------------------------- /8-vertical-slices/pkg/metrics/http_server.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | ) 8 | 9 | type HTTPServer struct { 10 | total *prometheus.CounterVec 11 | current *prometheus.GaugeVec 12 | duration *prometheus.HistogramVec 13 | } 14 | 15 | func NewHTTPServer() *HTTPServer { 16 | m := &HTTPServer{} 17 | 18 | // Настройка метрик 19 | 20 | return m 21 | } 22 | 23 | func (m *HTTPServer) TotalInc(method string, code int) {} 24 | 25 | func (m *HTTPServer) CurrentSet(process string, value float64) {} 26 | 27 | func (m *HTTPServer) Duration(method string, startTime time.Time) {} 28 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/adapter/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "context" 4 | 5 | type Config struct { 6 | Addr string `envconfig:"REDIS_ADDR" required:"true"` 7 | Password string `envconfig:"REDIS_PASSWORD"` 8 | DB int `default:"0" envconfig:"REDIS_DB"` 9 | } 10 | 11 | type Client struct{} 12 | 13 | func New(c Config) (*Client, error) { 14 | // Делаем подключение к Redis 15 | return &Client{}, nil 16 | } 17 | 18 | func (c *Client) IsExists(ctx context.Context, idempotencyKey string) bool { 19 | // Проверяем, существует ли ключ в Redis 20 | return false 21 | } 22 | 23 | func (c *Client) Close() { 24 | // Shutdown 25 | } 26 | -------------------------------------------------------------------------------- /5-layers-dto/internal/controller/http/get_profile.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/5-layers-dto/internal/dto" 7 | 8 | "github.com/golang-school/evolution/5-layers-dto/pkg/render" 9 | 10 | "github.com/go-chi/chi/v5" 11 | ) 12 | 13 | func (h *Handlers) GetProfile(w http.ResponseWriter, r *http.Request) { 14 | input := dto.GetProfileInput{ 15 | ID: chi.URLParam(r, "id"), 16 | } 17 | 18 | output, err := h.profileService.GetProfile(r.Context(), input) 19 | if err != nil { 20 | http.Error(w, err.Error(), http.StatusBadRequest) 21 | 22 | return 23 | } 24 | 25 | render.JSON(w, output, http.StatusOK) 26 | } 27 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/controller/http/get_profile.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/6-layers-ddd/internal/dto" 7 | 8 | "github.com/golang-school/evolution/6-layers-ddd/pkg/render" 9 | 10 | "github.com/go-chi/chi/v5" 11 | ) 12 | 13 | func (h *Handlers) GetProfile(w http.ResponseWriter, r *http.Request) { 14 | input := dto.GetProfileInput{ 15 | ID: chi.URLParam(r, "id"), 16 | } 17 | 18 | output, err := h.profileService.GetProfile(r.Context(), input) 19 | if err != nil { 20 | http.Error(w, err.Error(), http.StatusBadRequest) 21 | 22 | return 23 | } 24 | 25 | render.JSON(w, output, http.StatusOK) 26 | } 27 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/controller/http/get_profile.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/7-layers-cqrs/internal/dto" 7 | 8 | "github.com/golang-school/evolution/7-layers-cqrs/pkg/render" 9 | 10 | "github.com/go-chi/chi/v5" 11 | ) 12 | 13 | func (h *Handlers) GetProfile(w http.ResponseWriter, r *http.Request) { 14 | input := dto.GetProfileInput{ 15 | ID: chi.URLParam(r, "id"), 16 | } 17 | 18 | output, err := h.profileService.GetProfile(r.Context(), input) 19 | if err != nil { 20 | http.Error(w, err.Error(), http.StatusBadRequest) 21 | 22 | return 23 | } 24 | 25 | render.JSON(w, output, http.StatusOK) 26 | } 27 | -------------------------------------------------------------------------------- /1-handler-first/internal/kafka_produce/produce.go: -------------------------------------------------------------------------------- 1 | package kafka_produce 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_WRITER_ADDR" required:"true"` 9 | Topic string `envconfig:"KAFKA_WRITER_TOPIC"` 10 | } 11 | 12 | type Producer struct { 13 | config Config 14 | } 15 | 16 | func NewProducer(c Config) *Producer { 17 | // Настройка топика, адресов и других параметров 18 | return &Producer{} 19 | } 20 | 21 | type Message struct{} 22 | 23 | func (p *Producer) Produce(ctx context.Context, msgs ...Message) error { 24 | // Отправляем данные в Кафку 25 | return nil 26 | } 27 | 28 | func (p *Producer) Close() { 29 | // Shutdown 30 | } 31 | -------------------------------------------------------------------------------- /2-service-first/internal/kafka_produce/produce.go: -------------------------------------------------------------------------------- 1 | package kafka_produce 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_WRITER_ADDR" required:"true"` 9 | Topic string `envconfig:"KAFKA_WRITER_TOPIC"` 10 | } 11 | 12 | type Producer struct { 13 | config Config 14 | } 15 | 16 | func NewProducer(c Config) *Producer { 17 | // Настройка топика, адресов и других параметров 18 | return &Producer{} 19 | } 20 | 21 | type Message struct{} 22 | 23 | func (p *Producer) Produce(ctx context.Context, msgs ...Message) error { 24 | // Отправляем данные в Кафку 25 | return nil 26 | } 27 | 28 | func (p *Producer) Close() { 29 | // Shutdown 30 | } 31 | -------------------------------------------------------------------------------- /3-service-hell/internal/kafka_produce/produce.go: -------------------------------------------------------------------------------- 1 | package kafka_produce 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_WRITER_ADDR" required:"true"` 9 | Topic string `envconfig:"KAFKA_WRITER_TOPIC"` 10 | } 11 | 12 | type Producer struct { 13 | config Config 14 | } 15 | 16 | func NewProducer(c Config) *Producer { 17 | // Настройка топика, адресов и других параметров 18 | return &Producer{} 19 | } 20 | 21 | type Message struct{} 22 | 23 | func (p *Producer) Produce(ctx context.Context, msgs ...Message) error { 24 | // Отправляем данные в Кафку 25 | return nil 26 | } 27 | 28 | func (p *Producer) Close() { 29 | // Shutdown 30 | } 31 | -------------------------------------------------------------------------------- /4-layers/internal/adapter/kafka_produce/produce.go: -------------------------------------------------------------------------------- 1 | package kafka_produce 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_WRITER_ADDR" required:"true"` 9 | Topic string `envconfig:"KAFKA_WRITER_TOPIC"` 10 | } 11 | 12 | type Producer struct { 13 | config Config 14 | } 15 | 16 | func NewProducer(c Config) *Producer { 17 | // Настройка топика, адресов и других параметров 18 | return &Producer{} 19 | } 20 | 21 | type Message struct{} 22 | 23 | func (p *Producer) Produce(ctx context.Context, msgs ...Message) error { 24 | // Отправляем данные в Кафку 25 | return nil 26 | } 27 | 28 | func (p *Producer) Close() { 29 | // Shutdown 30 | } 31 | -------------------------------------------------------------------------------- /4-layers/internal/usecase/get_profile.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/4-layers/internal/domain" 8 | 9 | "github.com/google/uuid" 10 | ) 11 | 12 | func (p *Profile) GetProfile(ctx context.Context, id string) (domain.Profile, error) { 13 | // Валидируем ID 14 | profileID, err := uuid.Parse(id) 15 | if err != nil { 16 | return domain.Profile{}, domain.ErrUUIDInvalid 17 | } 18 | 19 | // Достаём профиль из БД 20 | profile, err := p.postgres.GetProfile(ctx, profileID) 21 | if err != nil { 22 | return domain.Profile{}, fmt.Errorf("get profile from postgres: %w", err) 23 | } 24 | 25 | return profile, nil 26 | } 27 | -------------------------------------------------------------------------------- /4-layers/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/golang-school/evolution/4-layers 2 | 3 | go 1.23.4 4 | 5 | require ( 6 | github.com/go-chi/chi/v5 v5.2.2 7 | github.com/google/uuid v1.6.0 8 | github.com/prometheus/client_golang v1.22.0 9 | ) 10 | 11 | require ( 12 | github.com/beorn7/perks v1.0.1 // indirect 13 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 14 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 15 | github.com/prometheus/client_model v0.6.1 // indirect 16 | github.com/prometheus/common v0.62.0 // indirect 17 | github.com/prometheus/procfs v0.15.1 // indirect 18 | golang.org/x/sys v0.32.0 // indirect 19 | google.golang.org/protobuf v1.36.5 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /5-layers-dto/internal/adapter/kafka_produce/produce.go: -------------------------------------------------------------------------------- 1 | package kafka_produce 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_WRITER_ADDR" required:"true"` 9 | Topic string `envconfig:"KAFKA_WRITER_TOPIC"` 10 | } 11 | 12 | type Producer struct { 13 | config Config 14 | } 15 | 16 | func NewProducer(c Config) *Producer { 17 | // Настройка топика, адресов и других параметров 18 | return &Producer{} 19 | } 20 | 21 | type Message struct{} 22 | 23 | func (p *Producer) Produce(ctx context.Context, msgs ...Message) error { 24 | // Отправляем данные в Кафку 25 | return nil 26 | } 27 | 28 | func (p *Producer) Close() { 29 | // Shutdown 30 | } 31 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/adapter/kafka_produce/produce.go: -------------------------------------------------------------------------------- 1 | package kafka_produce 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_WRITER_ADDR" required:"true"` 9 | Topic string `envconfig:"KAFKA_WRITER_TOPIC"` 10 | } 11 | 12 | type Producer struct { 13 | config Config 14 | } 15 | 16 | func NewProducer(c Config) *Producer { 17 | // Настройка топика, адресов и других параметров 18 | return &Producer{} 19 | } 20 | 21 | type Message struct{} 22 | 23 | func (p *Producer) Produce(ctx context.Context, msgs ...Message) error { 24 | // Отправляем данные в Кафку 25 | return nil 26 | } 27 | 28 | func (p *Producer) Close() { 29 | // Shutdown 30 | } 31 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/adapter/kafka_produce/produce.go: -------------------------------------------------------------------------------- 1 | package kafka_produce 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_WRITER_ADDR" required:"true"` 9 | Topic string `envconfig:"KAFKA_WRITER_TOPIC"` 10 | } 11 | 12 | type Producer struct { 13 | config Config 14 | } 15 | 16 | func NewProducer(c Config) *Producer { 17 | // Настройка топика, адресов и других параметров 18 | return &Producer{} 19 | } 20 | 21 | type Message struct{} 22 | 23 | func (p *Producer) Produce(ctx context.Context, msgs ...Message) error { 24 | // Отправляем данные в Кафку 25 | return nil 26 | } 27 | 28 | func (p *Producer) Close() { 29 | // Shutdown 30 | } 31 | -------------------------------------------------------------------------------- /2-service-first/internal/profile_service/get_profile.go: -------------------------------------------------------------------------------- 1 | package profile_service 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/2-service-first/internal/model" 8 | "github.com/google/uuid" 9 | ) 10 | 11 | func (p *Profile) GetProfile(ctx context.Context, id string) (model.Profile, error) { 12 | // Валидируем ID 13 | profileID, err := uuid.Parse(id) 14 | if err != nil { 15 | return model.Profile{}, ErrUUIDInvalid 16 | } 17 | 18 | // Достаём профиль из БД 19 | profile, err := p.postgres.GetProfile(ctx, profileID) 20 | if err != nil { 21 | return model.Profile{}, fmt.Errorf("get profile from postgres: %w", err) 22 | } 23 | 24 | return profile, nil 25 | } 26 | -------------------------------------------------------------------------------- /3-service-hell/internal/profile_service/get_profile.go: -------------------------------------------------------------------------------- 1 | package profile_service 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/3-service-hell/internal/model" 8 | "github.com/google/uuid" 9 | ) 10 | 11 | func (p *Profile) GetProfile(ctx context.Context, id string) (model.Profile, error) { 12 | // Валидируем ID 13 | profileID, err := uuid.Parse(id) 14 | if err != nil { 15 | return model.Profile{}, ErrUUIDInvalid 16 | } 17 | 18 | // Достаём профиль из БД 19 | profile, err := p.postgres.GetProfile(ctx, profileID) 20 | if err != nil { 21 | return model.Profile{}, fmt.Errorf("get profile from postgres: %w", err) 22 | } 23 | 24 | return profile, nil 25 | } 26 | -------------------------------------------------------------------------------- /5-layers-dto/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/golang-school/evolution/5-layers-dto 2 | 3 | go 1.23.4 4 | 5 | require ( 6 | github.com/go-chi/chi/v5 v5.2.2 7 | github.com/google/uuid v1.6.0 8 | github.com/prometheus/client_golang v1.22.0 9 | ) 10 | 11 | require ( 12 | github.com/beorn7/perks v1.0.1 // indirect 13 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 14 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 15 | github.com/prometheus/client_model v0.6.1 // indirect 16 | github.com/prometheus/common v0.62.0 // indirect 17 | github.com/prometheus/procfs v0.15.1 // indirect 18 | golang.org/x/sys v0.32.0 // indirect 19 | google.golang.org/protobuf v1.36.5 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/adapter/kafka_produce/produce.go: -------------------------------------------------------------------------------- 1 | package kafka_produce 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_WRITER_ADDR" required:"true"` 9 | Topic string `envconfig:"KAFKA_WRITER_TOPIC"` 10 | } 11 | 12 | type Producer struct { 13 | config Config 14 | } 15 | 16 | func NewProducer(c Config) *Producer { 17 | // Настройка топика, адресов и других параметров 18 | return &Producer{} 19 | } 20 | 21 | type Message struct{} 22 | 23 | func (p *Producer) Produce(ctx context.Context, msgs ...Message) error { 24 | // Отправляем данные в Кафку 25 | return nil 26 | } 27 | 28 | func (p *Producer) Close() { 29 | // Shutdown 30 | } 31 | -------------------------------------------------------------------------------- /1-handler-first/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/golang-school/evolution/1-handler-first 2 | 3 | go 1.23.4 4 | 5 | require ( 6 | github.com/go-chi/chi/v5 v5.2.2 7 | github.com/google/uuid v1.6.0 8 | github.com/prometheus/client_golang v1.22.0 9 | ) 10 | 11 | require ( 12 | github.com/beorn7/perks v1.0.1 // indirect 13 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 14 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 15 | github.com/prometheus/client_model v0.6.1 // indirect 16 | github.com/prometheus/common v0.62.0 // indirect 17 | github.com/prometheus/procfs v0.15.1 // indirect 18 | golang.org/x/sys v0.32.0 // indirect 19 | google.golang.org/protobuf v1.36.5 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /2-service-first/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/golang-school/evolution/2-service-first 2 | 3 | go 1.23.4 4 | 5 | require ( 6 | github.com/go-chi/chi/v5 v5.2.2 7 | github.com/google/uuid v1.6.0 8 | github.com/prometheus/client_golang v1.22.0 9 | ) 10 | 11 | require ( 12 | github.com/beorn7/perks v1.0.1 // indirect 13 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 14 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 15 | github.com/prometheus/client_model v0.6.1 // indirect 16 | github.com/prometheus/common v0.62.0 // indirect 17 | github.com/prometheus/procfs v0.15.1 // indirect 18 | golang.org/x/sys v0.32.0 // indirect 19 | google.golang.org/protobuf v1.36.5 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /3-service-hell/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/golang-school/evolution/3-service-hell 2 | 3 | go 1.23.4 4 | 5 | require ( 6 | github.com/go-chi/chi/v5 v5.2.2 7 | github.com/google/uuid v1.6.0 8 | github.com/prometheus/client_golang v1.22.0 9 | ) 10 | 11 | require ( 12 | github.com/beorn7/perks v1.0.1 // indirect 13 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 14 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 15 | github.com/prometheus/client_model v0.6.1 // indirect 16 | github.com/prometheus/common v0.62.0 // indirect 17 | github.com/prometheus/procfs v0.15.1 // indirect 18 | golang.org/x/sys v0.32.0 // indirect 19 | google.golang.org/protobuf v1.36.5 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/profile/create_profile/http_v1.go: -------------------------------------------------------------------------------- 1 | package create_profile 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/golang-school/evolution/8-vertical-slices/pkg/render" 8 | ) 9 | 10 | var usecase *Usecase 11 | 12 | func HTTPv1(w http.ResponseWriter, r *http.Request) { 13 | input := Input{} 14 | 15 | err := json.NewDecoder(r.Body).Decode(&input) 16 | if err != nil { 17 | http.Error(w, err.Error(), http.StatusBadRequest) 18 | 19 | return 20 | } 21 | 22 | output, err := usecase.CreateProfile(r.Context(), input) 23 | if err != nil { 24 | http.Error(w, err.Error(), http.StatusBadRequest) 25 | 26 | return 27 | } 28 | 29 | render.JSON(w, output, http.StatusOK) 30 | } 31 | -------------------------------------------------------------------------------- /1-handler-first/internal/server/get_profile.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/1-handler-first/pkg/render" 7 | 8 | "github.com/go-chi/chi/v5" 9 | "github.com/google/uuid" 10 | ) 11 | 12 | func (h *Handlers) GetProfile(w http.ResponseWriter, r *http.Request) { 13 | id := chi.URLParam(r, "id") 14 | 15 | profileID, err := uuid.Parse(id) 16 | if err != nil { 17 | http.Error(w, ErrUUIDInvalid.Error(), http.StatusBadRequest) 18 | 19 | return 20 | } 21 | 22 | profile, err := h.postgres.GetProfile(r.Context(), profileID) 23 | if err != nil { 24 | http.Error(w, err.Error(), http.StatusBadRequest) 25 | 26 | return 27 | } 28 | 29 | render.JSON(w, profile, http.StatusOK) 30 | } 31 | -------------------------------------------------------------------------------- /2-service-first/internal/kafka_consume/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka_consume 2 | 3 | import "github.com/golang-school/evolution/2-service-first/internal/profile_service" 4 | 5 | type Config struct { 6 | Addr []string `envconfig:"KAFKA_CONSUMER_ADDR" required:"true"` 7 | Topic string `default:"mnepryakhin-my-app-topic" envconfig:"KAFKA_CONSUMER_TOPIC"` 8 | Group string `default:"mnepryakhin-my-app-group" envconfig:"KAFKA_CONSUMER_GROUP"` 9 | } 10 | 11 | // Кафка консьюмер 12 | type Consumer struct{} 13 | 14 | func New(cfg Config, profile *profile_service.Profile) *Consumer { 15 | // Настройки 16 | // Запуск горутины для приёма сообщений и передачи их в сервис 17 | return &Consumer{} 18 | } 19 | 20 | func (c *Consumer) Close() { 21 | // Shutdown 22 | } 23 | -------------------------------------------------------------------------------- /3-service-hell/internal/kafka_consume/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka_consume 2 | 3 | import "github.com/golang-school/evolution/3-service-hell/internal/profile_service" 4 | 5 | type Config struct { 6 | Addr []string `envconfig:"KAFKA_CONSUMER_ADDR" required:"true"` 7 | Topic string `default:"mnepryakhin-my-app-topic" envconfig:"KAFKA_CONSUMER_TOPIC"` 8 | Group string `default:"mnepryakhin-my-app-group" envconfig:"KAFKA_CONSUMER_GROUP"` 9 | } 10 | 11 | // Кафка консьюмер 12 | type Consumer struct{} 13 | 14 | func New(cfg Config, profile *profile_service.Profile) *Consumer { 15 | // Настройки 16 | // Запуск горутины для приёма сообщений и передачи их в сервис 17 | return &Consumer{} 18 | } 19 | 20 | func (c *Consumer) Close() { 21 | // Shutdown 22 | } 23 | -------------------------------------------------------------------------------- /4-layers/internal/controller/kafka_consume/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka_consume 2 | 3 | import ( 4 | "github.com/golang-school/evolution/4-layers/internal/usecase" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_CONSUMER_ADDR" required:"true"` 9 | Topic string `default:"mnepryakhin-my-app-topic" envconfig:"KAFKA_CONSUMER_TOPIC"` 10 | Group string `default:"mnepryakhin-my-app-group" envconfig:"KAFKA_CONSUMER_GROUP"` 11 | } 12 | 13 | // Кафка консьюмер 14 | type Consumer struct{} 15 | 16 | func New(cfg Config, profile *usecase.Profile) *Consumer { 17 | // Настройки 18 | // Запуск горутины для приёма сообщений и передачи их в сервис 19 | return &Consumer{} 20 | } 21 | 22 | func (c *Consumer) Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /5-layers-dto/internal/controller/kafka_consume/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka_consume 2 | 3 | import ( 4 | "github.com/golang-school/evolution/5-layers-dto/internal/usecase" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_CONSUMER_ADDR" required:"true"` 9 | Topic string `default:"mnepryakhin-my-app-topic" envconfig:"KAFKA_CONSUMER_TOPIC"` 10 | Group string `default:"mnepryakhin-my-app-group" envconfig:"KAFKA_CONSUMER_GROUP"` 11 | } 12 | 13 | // Кафка консьюмер 14 | type Consumer struct{} 15 | 16 | func New(cfg Config, profile *usecase.Profile) *Consumer { 17 | // Настройки 18 | // Запуск горутины для приёма сообщений и передачи их в сервис 19 | return &Consumer{} 20 | } 21 | 22 | func (c *Consumer) Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/controller/kafka_consume/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka_consume 2 | 3 | import ( 4 | "github.com/golang-school/evolution/6-layers-ddd/internal/usecase" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_CONSUMER_ADDR" required:"true"` 9 | Topic string `default:"mnepryakhin-my-app-topic" envconfig:"KAFKA_CONSUMER_TOPIC"` 10 | Group string `default:"mnepryakhin-my-app-group" envconfig:"KAFKA_CONSUMER_GROUP"` 11 | } 12 | 13 | // Кафка консьюмер 14 | type Consumer struct{} 15 | 16 | func New(cfg Config, profile *usecase.Profile) *Consumer { 17 | // Настройки 18 | // Запуск горутины для приёма сообщений и передачи их в сервис 19 | return &Consumer{} 20 | } 21 | 22 | func (c *Consumer) Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/controller/kafka_consume/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka_consume 2 | 3 | import ( 4 | "github.com/golang-school/evolution/7-layers-cqrs/internal/usecase" 5 | ) 6 | 7 | type Config struct { 8 | Addr []string `envconfig:"KAFKA_CONSUMER_ADDR" required:"true"` 9 | Topic string `default:"mnepryakhin-my-app-topic" envconfig:"KAFKA_CONSUMER_TOPIC"` 10 | Group string `default:"mnepryakhin-my-app-group" envconfig:"KAFKA_CONSUMER_GROUP"` 11 | } 12 | 13 | // Кафка консьюмер 14 | type Consumer struct{} 15 | 16 | func New(cfg Config, profile *usecase.Profile) *Consumer { 17 | // Настройки 18 | // Запуск горутины для приёма сообщений и передачи их в сервис 19 | return &Consumer{} 20 | } 21 | 22 | func (c *Consumer) Close() { 23 | // Shutdown 24 | } 25 | -------------------------------------------------------------------------------- /5-layers-dto/internal/controller/http/create_profile.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/golang-school/evolution/5-layers-dto/internal/dto" 8 | 9 | "github.com/golang-school/evolution/5-layers-dto/pkg/render" 10 | ) 11 | 12 | func (h *Handlers) CreateProfile(w http.ResponseWriter, r *http.Request) { 13 | input := dto.CreateProfileInput{} 14 | 15 | err := json.NewDecoder(r.Body).Decode(&input) 16 | if err != nil { 17 | http.Error(w, err.Error(), http.StatusBadRequest) 18 | 19 | return 20 | } 21 | 22 | output, err := h.profileService.CreateProfile(r.Context(), input) 23 | if err != nil { 24 | http.Error(w, err.Error(), http.StatusBadRequest) 25 | 26 | return 27 | } 28 | 29 | render.JSON(w, output, http.StatusOK) 30 | } 31 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/controller/http/create_profile.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/golang-school/evolution/6-layers-ddd/internal/dto" 8 | 9 | "github.com/golang-school/evolution/6-layers-ddd/pkg/render" 10 | ) 11 | 12 | func (h *Handlers) CreateProfile(w http.ResponseWriter, r *http.Request) { 13 | input := dto.CreateProfileInput{} 14 | 15 | err := json.NewDecoder(r.Body).Decode(&input) 16 | if err != nil { 17 | http.Error(w, err.Error(), http.StatusBadRequest) 18 | 19 | return 20 | } 21 | 22 | output, err := h.profileService.CreateProfile(r.Context(), input) 23 | if err != nil { 24 | http.Error(w, err.Error(), http.StatusBadRequest) 25 | 26 | return 27 | } 28 | 29 | render.JSON(w, output, http.StatusOK) 30 | } 31 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/controller/http/create_profile.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/golang-school/evolution/7-layers-cqrs/internal/dto" 8 | 9 | "github.com/golang-school/evolution/7-layers-cqrs/pkg/render" 10 | ) 11 | 12 | func (h *Handlers) CreateProfile(w http.ResponseWriter, r *http.Request) { 13 | input := dto.CreateProfileInput{} 14 | 15 | err := json.NewDecoder(r.Body).Decode(&input) 16 | if err != nil { 17 | http.Error(w, err.Error(), http.StatusBadRequest) 18 | 19 | return 20 | } 21 | 22 | output, err := h.profileService.CreateProfile(r.Context(), input) 23 | if err != nil { 24 | http.Error(w, err.Error(), http.StatusBadRequest) 25 | 26 | return 27 | } 28 | 29 | render.JSON(w, output, http.StatusOK) 30 | } 31 | -------------------------------------------------------------------------------- /1-handler-first/internal/server/handlers.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/golang-school/evolution/1-handler-first/internal/kafka_produce" 7 | "github.com/golang-school/evolution/1-handler-first/internal/postgres" 8 | "github.com/golang-school/evolution/1-handler-first/internal/redis" 9 | ) 10 | 11 | var ( 12 | ErrAlreadyExists = errors.New("already exists") 13 | ErrUUIDInvalid = errors.New("invalid UUID format") 14 | ) 15 | 16 | type Handlers struct { 17 | postgres *postgres.Pool 18 | kafka *kafka_produce.Producer 19 | redis *redis.Client 20 | } 21 | 22 | func NewHandlers(postgres *postgres.Pool, kafka *kafka_produce.Producer, redis *redis.Client) *Handlers { 23 | return &Handlers{ 24 | postgres: postgres, 25 | kafka: kafka, 26 | redis: redis, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /4-layers/internal/controller/http/create_profile.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/golang-school/evolution/4-layers/pkg/render" 8 | ) 9 | 10 | func (h *Handlers) CreateProfile(w http.ResponseWriter, r *http.Request) { 11 | type Input struct { 12 | Name string `json:"name"` 13 | Age int `json:"age"` 14 | Email string `json:"email"` 15 | } 16 | 17 | input := Input{} 18 | 19 | err := json.NewDecoder(r.Body).Decode(&input) 20 | if err != nil { 21 | http.Error(w, err.Error(), http.StatusBadRequest) 22 | 23 | return 24 | } 25 | 26 | output, err := h.profileService.CreateProfile(r.Context(), input.Name, input.Age, input.Email) 27 | if err != nil { 28 | http.Error(w, err.Error(), http.StatusBadRequest) 29 | 30 | return 31 | } 32 | 33 | render.JSON(w, output, http.StatusOK) 34 | } 35 | -------------------------------------------------------------------------------- /5-layers-dto/internal/usecase/get_profile.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/5-layers-dto/internal/dto" 8 | 9 | "github.com/golang-school/evolution/5-layers-dto/internal/domain" 10 | 11 | "github.com/google/uuid" 12 | ) 13 | 14 | func (p *Profile) GetProfile(ctx context.Context, input dto.GetProfileInput) (dto.GetProfileOutput, error) { 15 | // Валидируем ID 16 | profileID, err := uuid.Parse(input.ID) 17 | if err != nil { 18 | return dto.GetProfileOutput{}, domain.ErrUUIDInvalid 19 | } 20 | 21 | // Достаём профиль из БД 22 | profile, err := p.postgres.GetProfile(ctx, profileID) 23 | if err != nil { 24 | return dto.GetProfileOutput{}, fmt.Errorf("get profile from postgres: %w", err) 25 | } 26 | 27 | return dto.GetProfileOutput{ 28 | Profile: profile, 29 | }, nil 30 | } 31 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/usecase/get_profile.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/6-layers-ddd/internal/dto" 8 | 9 | "github.com/golang-school/evolution/6-layers-ddd/internal/domain" 10 | 11 | "github.com/google/uuid" 12 | ) 13 | 14 | func (p *Profile) GetProfile(ctx context.Context, input dto.GetProfileInput) (dto.GetProfileOutput, error) { 15 | // Валидируем ID 16 | profileID, err := uuid.Parse(input.ID) 17 | if err != nil { 18 | return dto.GetProfileOutput{}, domain.ErrUUIDInvalid 19 | } 20 | 21 | // Достаём профиль из БД 22 | profile, err := p.postgres.GetProfile(ctx, profileID) 23 | if err != nil { 24 | return dto.GetProfileOutput{}, fmt.Errorf("get profile from postgres: %w", err) 25 | } 26 | 27 | return dto.GetProfileOutput{ 28 | Profile: profile, 29 | }, nil 30 | } 31 | -------------------------------------------------------------------------------- /3-service-hell/internal/server/create_profile.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/golang-school/evolution/3-service-hell/pkg/render" 8 | ) 9 | 10 | func (h *Handlers) CreateProfile(w http.ResponseWriter, r *http.Request) { 11 | type Input struct { 12 | Name string `json:"name"` 13 | Age int `json:"age"` 14 | Email string `json:"email"` 15 | } 16 | 17 | input := Input{} 18 | 19 | err := json.NewDecoder(r.Body).Decode(&input) 20 | if err != nil { 21 | http.Error(w, err.Error(), http.StatusBadRequest) 22 | 23 | return 24 | } 25 | 26 | output, err := h.profileService.CreateProfile(r.Context(), input.Name, input.Age, input.Email) 27 | if err != nil { 28 | http.Error(w, err.Error(), http.StatusBadRequest) 29 | 30 | return 31 | } 32 | 33 | render.JSON(w, output, http.StatusOK) 34 | } 35 | -------------------------------------------------------------------------------- /2-service-first/internal/server/create_profile.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/golang-school/evolution/2-service-first/pkg/render" 8 | ) 9 | 10 | func (h *Handlers) CreateProfile(w http.ResponseWriter, r *http.Request) { 11 | type Input struct { 12 | Name string `json:"name"` 13 | Age int `json:"age"` 14 | Email string `json:"email"` 15 | } 16 | 17 | input := Input{} 18 | 19 | err := json.NewDecoder(r.Body).Decode(&input) 20 | if err != nil { 21 | http.Error(w, err.Error(), http.StatusBadRequest) 22 | 23 | return 24 | } 25 | 26 | output, err := h.profileService.CreateProfile(r.Context(), input.Name, input.Age, input.Email) 27 | if err != nil { 28 | http.Error(w, err.Error(), http.StatusBadRequest) 29 | 30 | return 31 | } 32 | 33 | render.JSON(w, output, http.StatusOK) 34 | } 35 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/usecase/get_profile.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/7-layers-cqrs/internal/dto" 8 | 9 | "github.com/golang-school/evolution/7-layers-cqrs/internal/domain" 10 | 11 | "github.com/google/uuid" 12 | ) 13 | 14 | func (p *Profile) GetProfile(ctx context.Context, input dto.GetProfileInput) (dto.GetProfileOutput, error) { 15 | // Валидируем ID 16 | profileID, err := uuid.Parse(input.ID) 17 | if err != nil { 18 | return dto.GetProfileOutput{}, domain.ErrUUIDInvalid 19 | } 20 | 21 | // Достаём профиль из БД 22 | profile, err := p.postgresReplica.GetProfile(ctx, profileID) 23 | if err != nil { 24 | return dto.GetProfileOutput{}, fmt.Errorf("get profile from postgres: %w", err) 25 | } 26 | 27 | return dto.GetProfileOutput{ 28 | Profile: profile, 29 | }, nil 30 | } 31 | -------------------------------------------------------------------------------- /4-layers/internal/controller/http/router.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/4-layers/internal/usecase" 7 | 8 | "github.com/go-chi/chi/v5" 9 | "github.com/go-chi/chi/v5/middleware" 10 | "github.com/prometheus/client_golang/prometheus/promhttp" 11 | ) 12 | 13 | // Роутинг 14 | func Router(service *usecase.Profile) http.Handler { 15 | r := chi.NewRouter() 16 | r.Use(middleware.Recoverer) 17 | 18 | r.Get("/live", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 19 | r.Get("/ready", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 20 | 21 | r.Handle("/metrics", promhttp.Handler()) 22 | 23 | handlers := NewHandlers(service) 24 | 25 | r.Route("/api", func(r chi.Router) { 26 | r.Route("/v1", func(r chi.Router) { 27 | r.Post("/profile", handlers.CreateProfile) 28 | r.Get("/profile/{id}", handlers.GetProfile) 29 | }) 30 | }) 31 | 32 | return r 33 | } 34 | -------------------------------------------------------------------------------- /5-layers-dto/internal/controller/http/router.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/5-layers-dto/internal/usecase" 7 | 8 | "github.com/go-chi/chi/v5" 9 | "github.com/go-chi/chi/v5/middleware" 10 | "github.com/prometheus/client_golang/prometheus/promhttp" 11 | ) 12 | 13 | // Роутинг 14 | func Router(service *usecase.Profile) http.Handler { 15 | r := chi.NewRouter() 16 | r.Use(middleware.Recoverer) 17 | 18 | r.Get("/live", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 19 | r.Get("/ready", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 20 | 21 | r.Handle("/metrics", promhttp.Handler()) 22 | 23 | handlers := NewHandlers(service) 24 | 25 | r.Route("/api", func(r chi.Router) { 26 | r.Route("/v1", func(r chi.Router) { 27 | r.Post("/profile", handlers.CreateProfile) 28 | r.Get("/profile/{id}", handlers.GetProfile) 29 | }) 30 | }) 31 | 32 | return r 33 | } 34 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/controller/http/router.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/6-layers-ddd/internal/usecase" 7 | 8 | "github.com/go-chi/chi/v5" 9 | "github.com/go-chi/chi/v5/middleware" 10 | "github.com/prometheus/client_golang/prometheus/promhttp" 11 | ) 12 | 13 | // Роутинг 14 | func Router(service *usecase.Profile) http.Handler { 15 | r := chi.NewRouter() 16 | r.Use(middleware.Recoverer) 17 | 18 | r.Get("/live", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 19 | r.Get("/ready", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 20 | 21 | r.Handle("/metrics", promhttp.Handler()) 22 | 23 | handlers := NewHandlers(service) 24 | 25 | r.Route("/api", func(r chi.Router) { 26 | r.Route("/v1", func(r chi.Router) { 27 | r.Post("/profile", handlers.CreateProfile) 28 | r.Get("/profile/{id}", handlers.GetProfile) 29 | }) 30 | }) 31 | 32 | return r 33 | } 34 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/controller/http/router.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/7-layers-cqrs/internal/usecase" 7 | 8 | "github.com/go-chi/chi/v5" 9 | "github.com/go-chi/chi/v5/middleware" 10 | "github.com/prometheus/client_golang/prometheus/promhttp" 11 | ) 12 | 13 | // Роутинг 14 | func Router(service *usecase.Profile) http.Handler { 15 | r := chi.NewRouter() 16 | r.Use(middleware.Recoverer) 17 | 18 | r.Get("/live", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 19 | r.Get("/ready", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 20 | 21 | r.Handle("/metrics", promhttp.Handler()) 22 | 23 | handlers := NewHandlers(service) 24 | 25 | r.Route("/api", func(r chi.Router) { 26 | r.Route("/v1", func(r chi.Router) { 27 | r.Post("/profile", handlers.CreateProfile) 28 | r.Get("/profile/{id}", handlers.GetProfile) 29 | }) 30 | }) 31 | 32 | return r 33 | } 34 | -------------------------------------------------------------------------------- /2-service-first/internal/server/router.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/go-chi/chi/v5" 7 | "github.com/go-chi/chi/v5/middleware" 8 | "github.com/golang-school/evolution/2-service-first/internal/profile_service" 9 | "github.com/prometheus/client_golang/prometheus/promhttp" 10 | ) 11 | 12 | // Роутинг 13 | func Router(service *profile_service.Profile) http.Handler { 14 | r := chi.NewRouter() 15 | r.Use(middleware.Recoverer) 16 | 17 | r.Get("/live", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 18 | r.Get("/ready", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 19 | 20 | r.Handle("/metrics", promhttp.Handler()) 21 | 22 | handlers := NewHandlers(service) 23 | 24 | r.Route("/api", func(r chi.Router) { 25 | r.Route("/v1", func(r chi.Router) { 26 | r.Post("/profile", handlers.CreateProfile) 27 | r.Get("/profile/{id}", handlers.GetProfile) 28 | }) 29 | }) 30 | 31 | return r 32 | } 33 | -------------------------------------------------------------------------------- /3-service-hell/internal/server/router.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/go-chi/chi/v5" 7 | "github.com/go-chi/chi/v5/middleware" 8 | "github.com/golang-school/evolution/3-service-hell/internal/profile_service" 9 | "github.com/prometheus/client_golang/prometheus/promhttp" 10 | ) 11 | 12 | // Роутинг 13 | func Router(service *profile_service.Profile) http.Handler { 14 | r := chi.NewRouter() 15 | r.Use(middleware.Recoverer) 16 | 17 | r.Get("/live", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 18 | r.Get("/ready", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 19 | 20 | r.Handle("/metrics", promhttp.Handler()) 21 | 22 | handlers := NewHandlers(service) 23 | 24 | r.Route("/api", func(r chi.Router) { 25 | r.Route("/v1", func(r chi.Router) { 26 | r.Post("/profile", handlers.CreateProfile) 27 | r.Get("/profile/{id}", handlers.GetProfile) 28 | }) 29 | }) 30 | 31 | return r 32 | } 33 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/controller/http/router.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/golang-school/evolution/8-vertical-slices/internal/profile/get_profile" 7 | 8 | "github.com/golang-school/evolution/8-vertical-slices/internal/profile/create_profile" 9 | 10 | "github.com/go-chi/chi/v5" 11 | "github.com/go-chi/chi/v5/middleware" 12 | "github.com/prometheus/client_golang/prometheus/promhttp" 13 | ) 14 | 15 | // Роутинг 16 | func Router() http.Handler { 17 | r := chi.NewRouter() 18 | r.Use(middleware.Recoverer) 19 | 20 | r.Get("/live", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 21 | r.Get("/ready", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 22 | 23 | r.Handle("/metrics", promhttp.Handler()) 24 | 25 | r.Route("/api", func(r chi.Router) { 26 | r.Route("/v1", func(r chi.Router) { 27 | r.Post("/profile", create_profile.HTTPv1) 28 | r.Get("/profile/{id}", get_profile.HTTPv1) 29 | }) 30 | }) 31 | 32 | return r 33 | } 34 | -------------------------------------------------------------------------------- /4-layers/go.sum: -------------------------------------------------------------------------------- 1 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 2 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 3 | github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= 4 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 5 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 6 | github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= 7 | github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 8 | github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= 9 | github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 10 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 11 | google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 12 | -------------------------------------------------------------------------------- /5-layers-dto/go.sum: -------------------------------------------------------------------------------- 1 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 2 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 3 | github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= 4 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 5 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 6 | github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= 7 | github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 8 | github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= 9 | github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 10 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 11 | google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 12 | -------------------------------------------------------------------------------- /3-service-hell/go.sum: -------------------------------------------------------------------------------- 1 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 2 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 3 | github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= 4 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 5 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 6 | github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= 7 | github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 8 | github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= 9 | github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 10 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 11 | google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 12 | -------------------------------------------------------------------------------- /1-handler-first/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/golang-school/evolution/1-handler-first/internal/kafka_produce" 5 | "github.com/golang-school/evolution/1-handler-first/internal/postgres" 6 | "github.com/golang-school/evolution/1-handler-first/internal/redis" 7 | "github.com/golang-school/evolution/1-handler-first/pkg/httpserver" 8 | "github.com/golang-school/evolution/1-handler-first/pkg/logger" 9 | "github.com/golang-school/evolution/1-handler-first/pkg/otel" 10 | ) 11 | 12 | // Конфиг приложения 13 | type App struct { 14 | Name string `envconfig:"APP_NAME" required:"true"` 15 | Version string `envconfig:"APP_VERSION" required:"true"` 16 | } 17 | 18 | type Config struct { 19 | App App 20 | HTTP httpserver.Config 21 | Logger logger.Config 22 | OTEL otel.Config 23 | Postgres postgres.Config 24 | Redis redis.Config 25 | KafkaProducer kafka_produce.Config 26 | } 27 | 28 | func InitConfig() (Config, error) { 29 | // Парсим и валидируем конфиг 30 | return Config{}, nil 31 | } 32 | -------------------------------------------------------------------------------- /1-handler-first/internal/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/1-handler-first/internal/model" 7 | "github.com/google/uuid" 8 | ) 9 | 10 | type Config struct { 11 | User string `envconfig:"POSTGRES_USER" required:"true"` 12 | Password string `envconfig:"POSTGRES_PASSWORD" required:"true"` 13 | Port string `envconfig:"POSTGRES_PORT" required:"true"` 14 | Host string `envconfig:"POSTGRES_HOST" required:"true"` 15 | DBName string `envconfig:"POSTGRES_DB_NAME" required:"true"` 16 | } 17 | 18 | type Pool struct{} 19 | 20 | func New(ctx context.Context, c Config) (*Pool, error) { 21 | // Делаем настройки подключения и пингуем БД на доступность 22 | return &Pool{}, nil 23 | } 24 | 25 | func (p *Pool) CreateProfile(ctx context.Context, profile model.Profile) error { 26 | return nil 27 | } 28 | 29 | func (p *Pool) GetProfile(ctx context.Context, id uuid.UUID) (model.Profile, error) { 30 | return model.Profile{}, nil 31 | } 32 | 33 | func (p *Pool) Close() { 34 | // Shutdown 35 | } 36 | -------------------------------------------------------------------------------- /2-service-first/internal/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/2-service-first/internal/model" 7 | "github.com/google/uuid" 8 | ) 9 | 10 | type Config struct { 11 | User string `envconfig:"POSTGRES_USER" required:"true"` 12 | Password string `envconfig:"POSTGRES_PASSWORD" required:"true"` 13 | Port string `envconfig:"POSTGRES_PORT" required:"true"` 14 | Host string `envconfig:"POSTGRES_HOST" required:"true"` 15 | DBName string `envconfig:"POSTGRES_DB_NAME" required:"true"` 16 | } 17 | 18 | type Pool struct{} 19 | 20 | func New(ctx context.Context, c Config) (*Pool, error) { 21 | // Делаем настройки подключения и пингуем БД на доступность 22 | return &Pool{}, nil 23 | } 24 | 25 | func (p *Pool) CreateProfile(ctx context.Context, profile model.Profile) error { 26 | return nil 27 | } 28 | 29 | func (p *Pool) GetProfile(ctx context.Context, id uuid.UUID) (model.Profile, error) { 30 | return model.Profile{}, nil 31 | } 32 | 33 | func (p *Pool) Close() { 34 | // Shutdown 35 | } 36 | -------------------------------------------------------------------------------- /3-service-hell/internal/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/3-service-hell/internal/model" 7 | "github.com/google/uuid" 8 | ) 9 | 10 | type Config struct { 11 | User string `envconfig:"POSTGRES_USER" required:"true"` 12 | Password string `envconfig:"POSTGRES_PASSWORD" required:"true"` 13 | Port string `envconfig:"POSTGRES_PORT" required:"true"` 14 | Host string `envconfig:"POSTGRES_HOST" required:"true"` 15 | DBName string `envconfig:"POSTGRES_DB_NAME" required:"true"` 16 | } 17 | 18 | type Pool struct{} 19 | 20 | func New(ctx context.Context, c Config) (*Pool, error) { 21 | // Делаем настройки подключения и пингуем БД на доступность 22 | return &Pool{}, nil 23 | } 24 | 25 | func (p *Pool) CreateProfile(ctx context.Context, profile model.Profile) error { 26 | return nil 27 | } 28 | 29 | func (p *Pool) GetProfile(ctx context.Context, id uuid.UUID) (model.Profile, error) { 30 | return model.Profile{}, nil 31 | } 32 | 33 | func (p *Pool) Close() { 34 | // Shutdown 35 | } 36 | -------------------------------------------------------------------------------- /4-layers/internal/adapter/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/4-layers/internal/domain" 7 | 8 | "github.com/google/uuid" 9 | ) 10 | 11 | type Config struct { 12 | User string `envconfig:"POSTGRES_USER" required:"true"` 13 | Password string `envconfig:"POSTGRES_PASSWORD" required:"true"` 14 | Port string `envconfig:"POSTGRES_PORT" required:"true"` 15 | Host string `envconfig:"POSTGRES_HOST" required:"true"` 16 | DBName string `envconfig:"POSTGRES_DB_NAME" required:"true"` 17 | } 18 | 19 | type Pool struct{} 20 | 21 | func New(ctx context.Context, c Config) (*Pool, error) { 22 | // Делаем настройки подключения и пингуем БД на доступность 23 | return &Pool{}, nil 24 | } 25 | 26 | func (p *Pool) CreateProfile(ctx context.Context, profile domain.Profile) error { 27 | return nil 28 | } 29 | 30 | func (p *Pool) GetProfile(ctx context.Context, id uuid.UUID) (domain.Profile, error) { 31 | return domain.Profile{}, nil 32 | } 33 | 34 | func (p *Pool) Close() { 35 | // Shutdown 36 | } 37 | -------------------------------------------------------------------------------- /5-layers-dto/internal/adapter/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/5-layers-dto/internal/domain" 7 | 8 | "github.com/google/uuid" 9 | ) 10 | 11 | type Config struct { 12 | User string `envconfig:"POSTGRES_USER" required:"true"` 13 | Password string `envconfig:"POSTGRES_PASSWORD" required:"true"` 14 | Port string `envconfig:"POSTGRES_PORT" required:"true"` 15 | Host string `envconfig:"POSTGRES_HOST" required:"true"` 16 | DBName string `envconfig:"POSTGRES_DB_NAME" required:"true"` 17 | } 18 | 19 | type Pool struct{} 20 | 21 | func New(ctx context.Context, c Config) (*Pool, error) { 22 | // Делаем настройки подключения и пингуем БД на доступность 23 | return &Pool{}, nil 24 | } 25 | 26 | func (p *Pool) CreateProfile(ctx context.Context, profile domain.Profile) error { 27 | return nil 28 | } 29 | 30 | func (p *Pool) GetProfile(ctx context.Context, id uuid.UUID) (domain.Profile, error) { 31 | return domain.Profile{}, nil 32 | } 33 | 34 | func (p *Pool) Close() { 35 | // Shutdown 36 | } 37 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/adapter/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/6-layers-ddd/internal/domain" 7 | 8 | "github.com/google/uuid" 9 | ) 10 | 11 | type Config struct { 12 | User string `envconfig:"POSTGRES_USER" required:"true"` 13 | Password string `envconfig:"POSTGRES_PASSWORD" required:"true"` 14 | Port string `envconfig:"POSTGRES_PORT" required:"true"` 15 | Host string `envconfig:"POSTGRES_HOST" required:"true"` 16 | DBName string `envconfig:"POSTGRES_DB_NAME" required:"true"` 17 | } 18 | 19 | type Pool struct{} 20 | 21 | func New(ctx context.Context, c Config) (*Pool, error) { 22 | // Делаем настройки подключения и пингуем БД на доступность 23 | return &Pool{}, nil 24 | } 25 | 26 | func (p *Pool) CreateProfile(ctx context.Context, profile domain.Profile) error { 27 | return nil 28 | } 29 | 30 | func (p *Pool) GetProfile(ctx context.Context, id uuid.UUID) (domain.Profile, error) { 31 | return domain.Profile{}, nil 32 | } 33 | 34 | func (p *Pool) Close() { 35 | // Shutdown 36 | } 37 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/adapter/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/7-layers-cqrs/internal/domain" 7 | 8 | "github.com/google/uuid" 9 | ) 10 | 11 | type Config struct { 12 | User string `envconfig:"POSTGRES_USER" required:"true"` 13 | Password string `envconfig:"POSTGRES_PASSWORD" required:"true"` 14 | Port string `envconfig:"POSTGRES_PORT" required:"true"` 15 | Host string `envconfig:"POSTGRES_HOST" required:"true"` 16 | DBName string `envconfig:"POSTGRES_DB_NAME" required:"true"` 17 | } 18 | 19 | type Pool struct{} 20 | 21 | func New(ctx context.Context, c Config) (*Pool, error) { 22 | // Делаем настройки подключения и пингуем БД на доступность 23 | return &Pool{}, nil 24 | } 25 | 26 | func (p *Pool) CreateProfile(ctx context.Context, profile domain.Profile) error { 27 | return nil 28 | } 29 | 30 | func (p *Pool) GetProfile(ctx context.Context, id uuid.UUID) (domain.Profile, error) { 31 | return domain.Profile{}, nil 32 | } 33 | 34 | func (p *Pool) Close() { 35 | // Shutdown 36 | } 37 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/adapter/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/8-vertical-slices/internal/domain" 7 | 8 | "github.com/google/uuid" 9 | ) 10 | 11 | type Config struct { 12 | User string `envconfig:"POSTGRES_USER" required:"true"` 13 | Password string `envconfig:"POSTGRES_PASSWORD" required:"true"` 14 | Port string `envconfig:"POSTGRES_PORT" required:"true"` 15 | Host string `envconfig:"POSTGRES_HOST" required:"true"` 16 | DBName string `envconfig:"POSTGRES_DB_NAME" required:"true"` 17 | } 18 | 19 | type Pool struct{} 20 | 21 | func New(ctx context.Context, c Config) (*Pool, error) { 22 | // Делаем настройки подключения и пингуем БД на доступность 23 | return &Pool{}, nil 24 | } 25 | 26 | func (p *Pool) CreateProfile(ctx context.Context, profile domain.Profile) error { 27 | return nil 28 | } 29 | 30 | func (p *Pool) GetProfile(ctx context.Context, id uuid.UUID) (domain.Profile, error) { 31 | return domain.Profile{}, nil 32 | } 33 | 34 | func (p *Pool) Close() { 35 | // Shutdown 36 | } 37 | -------------------------------------------------------------------------------- /6-layers-ddd/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/golang-school/evolution/6-layers-ddd 2 | 3 | go 1.23.4 4 | 5 | require ( 6 | github.com/go-chi/chi/v5 v5.2.2 7 | github.com/go-playground/validator/v10 v10.27.0 8 | github.com/google/uuid v1.6.0 9 | github.com/prometheus/client_golang v1.22.0 10 | ) 11 | 12 | require ( 13 | github.com/beorn7/perks v1.0.1 // indirect 14 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 15 | github.com/gabriel-vasile/mimetype v1.4.8 // indirect 16 | github.com/go-playground/locales v0.14.1 // indirect 17 | github.com/go-playground/universal-translator v0.18.1 // indirect 18 | github.com/leodido/go-urn v1.4.0 // indirect 19 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 20 | github.com/prometheus/client_model v0.6.1 // indirect 21 | github.com/prometheus/common v0.62.0 // indirect 22 | github.com/prometheus/procfs v0.15.1 // indirect 23 | golang.org/x/crypto v0.33.0 // indirect 24 | golang.org/x/net v0.34.0 // indirect 25 | golang.org/x/sys v0.32.0 // indirect 26 | golang.org/x/text v0.22.0 // indirect 27 | google.golang.org/protobuf v1.36.5 // indirect 28 | ) 29 | -------------------------------------------------------------------------------- /7-layers-cqrs/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/golang-school/evolution/7-layers-cqrs 2 | 3 | go 1.23.4 4 | 5 | require ( 6 | github.com/go-chi/chi/v5 v5.2.2 7 | github.com/go-playground/validator/v10 v10.27.0 8 | github.com/google/uuid v1.6.0 9 | github.com/prometheus/client_golang v1.22.0 10 | ) 11 | 12 | require ( 13 | github.com/beorn7/perks v1.0.1 // indirect 14 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 15 | github.com/gabriel-vasile/mimetype v1.4.8 // indirect 16 | github.com/go-playground/locales v0.14.1 // indirect 17 | github.com/go-playground/universal-translator v0.18.1 // indirect 18 | github.com/leodido/go-urn v1.4.0 // indirect 19 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 20 | github.com/prometheus/client_model v0.6.1 // indirect 21 | github.com/prometheus/common v0.62.0 // indirect 22 | github.com/prometheus/procfs v0.15.1 // indirect 23 | golang.org/x/crypto v0.33.0 // indirect 24 | golang.org/x/net v0.34.0 // indirect 25 | golang.org/x/sys v0.32.0 // indirect 26 | golang.org/x/text v0.22.0 // indirect 27 | google.golang.org/protobuf v1.36.5 // indirect 28 | ) 29 | -------------------------------------------------------------------------------- /4-layers/internal/usecase/usecase.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/4-layers/internal/adapter/kafka_produce" 7 | "github.com/golang-school/evolution/4-layers/internal/adapter/postgres" 8 | "github.com/golang-school/evolution/4-layers/internal/adapter/redis" 9 | 10 | "github.com/golang-school/evolution/4-layers/internal/domain" 11 | "github.com/google/uuid" 12 | ) 13 | 14 | type Redis interface { 15 | IsExists(ctx context.Context, idempotencyKey string) bool 16 | } 17 | 18 | type Kafka interface { 19 | Produce(ctx context.Context, msgs ...kafka_produce.Message) error 20 | } 21 | 22 | type Postgres interface { 23 | CreateProfile(ctx context.Context, profile domain.Profile) error 24 | GetProfile(ctx context.Context, id uuid.UUID) (domain.Profile, error) 25 | } 26 | 27 | type Profile struct { 28 | postgres Postgres 29 | kafka Kafka 30 | redis Redis 31 | } 32 | 33 | func NewProfile(postgres *postgres.Pool, kafka *kafka_produce.Producer, redis *redis.Client) *Profile { 34 | return &Profile{ 35 | postgres: postgres, 36 | kafka: kafka, 37 | redis: redis, 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /4-layers/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/golang-school/evolution/4-layers/internal/adapter/kafka_produce" 5 | "github.com/golang-school/evolution/4-layers/internal/adapter/postgres" 6 | "github.com/golang-school/evolution/4-layers/internal/adapter/redis" 7 | "github.com/golang-school/evolution/4-layers/internal/controller/kafka_consume" 8 | "github.com/golang-school/evolution/4-layers/pkg/httpserver" 9 | "github.com/golang-school/evolution/4-layers/pkg/logger" 10 | "github.com/golang-school/evolution/4-layers/pkg/otel" 11 | ) 12 | 13 | // Конфиг приложения 14 | type App struct { 15 | Name string `envconfig:"APP_NAME" required:"true"` 16 | Version string `envconfig:"APP_VERSION" required:"true"` 17 | } 18 | 19 | type Config struct { 20 | App App 21 | HTTP httpserver.Config 22 | Logger logger.Config 23 | OTEL otel.Config 24 | Postgres postgres.Config 25 | Redis redis.Config 26 | KafkaProducer kafka_produce.Config 27 | KafkaConsumer kafka_consume.Config 28 | } 29 | 30 | func InitConfig() (Config, error) { 31 | // Парсим и валидируем конфиг 32 | return Config{}, nil 33 | } 34 | -------------------------------------------------------------------------------- /5-layers-dto/internal/usecase/usecase.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/5-layers-dto/internal/adapter/kafka_produce" 7 | "github.com/golang-school/evolution/5-layers-dto/internal/adapter/postgres" 8 | "github.com/golang-school/evolution/5-layers-dto/internal/adapter/redis" 9 | 10 | "github.com/golang-school/evolution/5-layers-dto/internal/domain" 11 | "github.com/google/uuid" 12 | ) 13 | 14 | type Redis interface { 15 | IsExists(ctx context.Context, idempotencyKey string) bool 16 | } 17 | 18 | type Kafka interface { 19 | Produce(ctx context.Context, msgs ...kafka_produce.Message) error 20 | } 21 | 22 | type Postgres interface { 23 | CreateProfile(ctx context.Context, profile domain.Profile) error 24 | GetProfile(ctx context.Context, id uuid.UUID) (domain.Profile, error) 25 | } 26 | 27 | type Profile struct { 28 | postgres Postgres 29 | kafka Kafka 30 | redis Redis 31 | } 32 | 33 | func NewProfile(postgres *postgres.Pool, kafka *kafka_produce.Producer, redis *redis.Client) *Profile { 34 | return &Profile{ 35 | postgres: postgres, 36 | kafka: kafka, 37 | redis: redis, 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/usecase/usecase.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/6-layers-ddd/internal/adapter/kafka_produce" 7 | "github.com/golang-school/evolution/6-layers-ddd/internal/adapter/postgres" 8 | "github.com/golang-school/evolution/6-layers-ddd/internal/adapter/redis" 9 | 10 | "github.com/golang-school/evolution/6-layers-ddd/internal/domain" 11 | "github.com/google/uuid" 12 | ) 13 | 14 | type Redis interface { 15 | IsExists(ctx context.Context, idempotencyKey string) bool 16 | } 17 | 18 | type Kafka interface { 19 | Produce(ctx context.Context, msgs ...kafka_produce.Message) error 20 | } 21 | 22 | type Postgres interface { 23 | CreateProfile(ctx context.Context, profile domain.Profile) error 24 | GetProfile(ctx context.Context, id uuid.UUID) (domain.Profile, error) 25 | } 26 | 27 | type Profile struct { 28 | postgres Postgres 29 | kafka Kafka 30 | redis Redis 31 | } 32 | 33 | func NewProfile(postgres *postgres.Pool, kafka *kafka_produce.Producer, redis *redis.Client) *Profile { 34 | return &Profile{ 35 | postgres: postgres, 36 | kafka: kafka, 37 | redis: redis, 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /3-service-hell/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/golang-school/evolution/3-service-hell/internal/kafka_consume" 5 | "github.com/golang-school/evolution/3-service-hell/internal/kafka_produce" 6 | "github.com/golang-school/evolution/3-service-hell/internal/postgres" 7 | "github.com/golang-school/evolution/3-service-hell/internal/redis" 8 | "github.com/golang-school/evolution/3-service-hell/pkg/httpserver" 9 | "github.com/golang-school/evolution/3-service-hell/pkg/logger" 10 | "github.com/golang-school/evolution/3-service-hell/pkg/otel" 11 | ) 12 | 13 | // Конфиг приложения 14 | type App struct { 15 | Name string `envconfig:"APP_NAME" required:"true"` 16 | Version string `envconfig:"APP_VERSION" required:"true"` 17 | } 18 | 19 | type Config struct { 20 | App App 21 | HTTP httpserver.Config 22 | Logger logger.Config 23 | OTEL otel.Config 24 | Postgres postgres.Config 25 | Redis redis.Config 26 | KafkaProducer kafka_produce.Config 27 | KafkaConsumer kafka_consume.Config 28 | } 29 | 30 | func InitConfig() (Config, error) { 31 | // Парсим и валидируем конфиг 32 | return Config{}, nil 33 | } 34 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/profile/get_profile/usecase.go: -------------------------------------------------------------------------------- 1 | package get_profile 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/8-vertical-slices/internal/adapter/postgres" 8 | "github.com/golang-school/evolution/8-vertical-slices/internal/domain" 9 | "github.com/google/uuid" 10 | ) 11 | 12 | type Postgres interface { 13 | GetProfile(ctx context.Context, id uuid.UUID) (domain.Profile, error) 14 | } 15 | 16 | type Usecase struct { 17 | postgres Postgres 18 | } 19 | 20 | func New(postgres *postgres.Pool) *Usecase { 21 | uc := &Usecase{ 22 | postgres: postgres, 23 | } 24 | 25 | usecase = uc // global for handlers 26 | 27 | return uc 28 | } 29 | 30 | func (u *Usecase) GetProfile(ctx context.Context, input Input) (Output, error) { 31 | // Валидируем ID 32 | profileID, err := uuid.Parse(input.ID) 33 | if err != nil { 34 | return Output{}, domain.ErrUUIDInvalid 35 | } 36 | 37 | // Достаём профиль из БД 38 | profile, err := u.postgres.GetProfile(ctx, profileID) 39 | if err != nil { 40 | return Output{}, fmt.Errorf("get profile from postgres: %w", err) 41 | } 42 | 43 | return Output{ 44 | Profile: profile, 45 | }, nil 46 | } 47 | -------------------------------------------------------------------------------- /1-handler-first/internal/server/router.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/go-chi/chi/v5" 7 | "github.com/go-chi/chi/v5/middleware" 8 | "github.com/golang-school/evolution/1-handler-first/internal/kafka_produce" 9 | "github.com/golang-school/evolution/1-handler-first/internal/postgres" 10 | "github.com/golang-school/evolution/1-handler-first/internal/redis" 11 | "github.com/prometheus/client_golang/prometheus/promhttp" 12 | ) 13 | 14 | func Router(postgres *postgres.Pool, kafka *kafka_produce.Producer, redis *redis.Client) http.Handler { 15 | r := chi.NewRouter() 16 | r.Use(middleware.Recoverer) 17 | 18 | r.Get("/live", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 19 | r.Get("/ready", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) 20 | 21 | r.Handle("/metrics", promhttp.Handler()) 22 | 23 | handlers := NewHandlers(postgres, kafka, redis) 24 | 25 | r.Route("/api", func(r chi.Router) { 26 | r.Route("/v1", func(r chi.Router) { 27 | r.Post("/profile", handlers.CreateProfile) 28 | r.Get("/profile/{id}", handlers.GetProfile) 29 | }) 30 | }) 31 | 32 | return r 33 | } 34 | -------------------------------------------------------------------------------- /2-service-first/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/golang-school/evolution/2-service-first/internal/kafka_consume" 5 | "github.com/golang-school/evolution/2-service-first/internal/kafka_produce" 6 | "github.com/golang-school/evolution/2-service-first/internal/postgres" 7 | "github.com/golang-school/evolution/2-service-first/internal/redis" 8 | "github.com/golang-school/evolution/2-service-first/pkg/httpserver" 9 | "github.com/golang-school/evolution/2-service-first/pkg/logger" 10 | "github.com/golang-school/evolution/2-service-first/pkg/otel" 11 | ) 12 | 13 | // Конфиг приложения 14 | type App struct { 15 | Name string `envconfig:"APP_NAME" required:"true"` 16 | Version string `envconfig:"APP_VERSION" required:"true"` 17 | } 18 | 19 | type Config struct { 20 | App App 21 | HTTP httpserver.Config 22 | Logger logger.Config 23 | OTEL otel.Config 24 | Postgres postgres.Config 25 | Redis redis.Config 26 | KafkaProducer kafka_produce.Config 27 | KafkaConsumer kafka_consume.Config 28 | } 29 | 30 | func InitConfig() (Config, error) { 31 | // Парсим и валидируем конфиг 32 | return Config{}, nil 33 | } 34 | -------------------------------------------------------------------------------- /5-layers-dto/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/golang-school/evolution/5-layers-dto/internal/adapter/kafka_produce" 5 | "github.com/golang-school/evolution/5-layers-dto/internal/adapter/postgres" 6 | "github.com/golang-school/evolution/5-layers-dto/internal/adapter/redis" 7 | "github.com/golang-school/evolution/5-layers-dto/internal/controller/kafka_consume" 8 | "github.com/golang-school/evolution/5-layers-dto/pkg/httpserver" 9 | "github.com/golang-school/evolution/5-layers-dto/pkg/logger" 10 | "github.com/golang-school/evolution/5-layers-dto/pkg/otel" 11 | ) 12 | 13 | // Конфиг приложения 14 | type App struct { 15 | Name string `envconfig:"APP_NAME" required:"true"` 16 | Version string `envconfig:"APP_VERSION" required:"true"` 17 | } 18 | 19 | type Config struct { 20 | App App 21 | HTTP httpserver.Config 22 | Logger logger.Config 23 | OTEL otel.Config 24 | Postgres postgres.Config 25 | Redis redis.Config 26 | KafkaProducer kafka_produce.Config 27 | KafkaConsumer kafka_consume.Config 28 | } 29 | 30 | func InitConfig() (Config, error) { 31 | // Парсим и валидируем конфиг 32 | return Config{}, nil 33 | } 34 | -------------------------------------------------------------------------------- /6-layers-ddd/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/golang-school/evolution/6-layers-ddd/internal/adapter/kafka_produce" 5 | "github.com/golang-school/evolution/6-layers-ddd/internal/adapter/postgres" 6 | "github.com/golang-school/evolution/6-layers-ddd/internal/adapter/redis" 7 | "github.com/golang-school/evolution/6-layers-ddd/internal/controller/kafka_consume" 8 | "github.com/golang-school/evolution/6-layers-ddd/pkg/httpserver" 9 | "github.com/golang-school/evolution/6-layers-ddd/pkg/logger" 10 | "github.com/golang-school/evolution/6-layers-ddd/pkg/otel" 11 | ) 12 | 13 | // Конфиг приложения 14 | type App struct { 15 | Name string `envconfig:"APP_NAME" required:"true"` 16 | Version string `envconfig:"APP_VERSION" required:"true"` 17 | } 18 | 19 | type Config struct { 20 | App App 21 | HTTP httpserver.Config 22 | Logger logger.Config 23 | OTEL otel.Config 24 | Postgres postgres.Config 25 | Redis redis.Config 26 | KafkaProducer kafka_produce.Config 27 | KafkaConsumer kafka_consume.Config 28 | } 29 | 30 | func InitConfig() (Config, error) { 31 | // Парсим и валидируем конфиг 32 | return Config{}, nil 33 | } 34 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/domain/profile.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/go-playground/validator/v10" 8 | "github.com/google/uuid" 9 | ) 10 | 11 | type Name string 12 | 13 | type Age int 14 | 15 | type Email string 16 | 17 | type Profile struct { 18 | ID uuid.UUID `json:"id"` 19 | CreatedAt time.Time `json:"created_at"` 20 | Name Name `json:"name" validate:"required,min=3,max=64"` 21 | Age Age `json:"age" validate:"required,min=18,max=120"` 22 | Email Email `json:"email" validate:"email"` 23 | } 24 | 25 | var validate = validator.New(validator.WithRequiredStructEnabled()) 26 | 27 | func NewProfile(name string, age int, email string) (Profile, error) { 28 | p := Profile{ 29 | ID: uuid.New(), 30 | Name: Name(name), 31 | Age: Age(age), 32 | Email: Email(email), 33 | } 34 | 35 | if err := p.Validate(); err != nil { 36 | return Profile{}, fmt.Errorf("p.Validate: %w", err) 37 | } 38 | 39 | return p, nil 40 | } 41 | 42 | func (p Profile) Validate() error { 43 | err := validate.Struct(p) 44 | if err != nil { 45 | return fmt.Errorf("validate.Struct: %w", err) 46 | } 47 | 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/domain/profile.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/go-playground/validator/v10" 8 | "github.com/google/uuid" 9 | ) 10 | 11 | type Name string 12 | 13 | type Age int 14 | 15 | type Email string 16 | 17 | type Profile struct { 18 | ID uuid.UUID `json:"id"` 19 | CreatedAt time.Time `json:"created_at"` 20 | Name Name `json:"name" validate:"required,min=3,max=64"` 21 | Age Age `json:"age" validate:"required,min=18,max=120"` 22 | Email Email `json:"email" validate:"email"` 23 | } 24 | 25 | var validate = validator.New(validator.WithRequiredStructEnabled()) 26 | 27 | func NewProfile(name string, age int, email string) (Profile, error) { 28 | p := Profile{ 29 | ID: uuid.New(), 30 | Name: Name(name), 31 | Age: Age(age), 32 | Email: Email(email), 33 | } 34 | 35 | if err := p.Validate(); err != nil { 36 | return Profile{}, fmt.Errorf("p.Validate: %w", err) 37 | } 38 | 39 | return p, nil 40 | } 41 | 42 | func (p Profile) Validate() error { 43 | err := validate.Struct(p) 44 | if err != nil { 45 | return fmt.Errorf("validate.Struct: %w", err) 46 | } 47 | 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/domain/profile.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/go-playground/validator/v10" 8 | "github.com/google/uuid" 9 | ) 10 | 11 | type Name string 12 | 13 | type Age int 14 | 15 | type Email string 16 | 17 | type Profile struct { 18 | ID uuid.UUID `json:"id"` 19 | CreatedAt time.Time `json:"created_at"` 20 | Name Name `json:"name" validate:"required,min=3,max=64"` 21 | Age Age `json:"age" validate:"required,min=18,max=120"` 22 | Email Email `json:"email" validate:"email"` 23 | } 24 | 25 | var validate = validator.New(validator.WithRequiredStructEnabled()) 26 | 27 | func NewProfile(name string, age int, email string) (Profile, error) { 28 | p := Profile{ 29 | ID: uuid.New(), 30 | Name: Name(name), 31 | Age: Age(age), 32 | Email: Email(email), 33 | } 34 | 35 | if err := p.Validate(); err != nil { 36 | return Profile{}, fmt.Errorf("p.Validate: %w", err) 37 | } 38 | 39 | return p, nil 40 | } 41 | 42 | func (p Profile) Validate() error { 43 | err := validate.Struct(p) 44 | if err != nil { 45 | return fmt.Errorf("validate.Struct: %w", err) 46 | } 47 | 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /7-layers-cqrs/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/golang-school/evolution/7-layers-cqrs/internal/adapter/kafka_produce" 5 | "github.com/golang-school/evolution/7-layers-cqrs/internal/adapter/postgres" 6 | "github.com/golang-school/evolution/7-layers-cqrs/internal/adapter/redis" 7 | "github.com/golang-school/evolution/7-layers-cqrs/internal/controller/kafka_consume" 8 | "github.com/golang-school/evolution/7-layers-cqrs/pkg/httpserver" 9 | "github.com/golang-school/evolution/7-layers-cqrs/pkg/logger" 10 | "github.com/golang-school/evolution/7-layers-cqrs/pkg/otel" 11 | ) 12 | 13 | // Конфиг приложения 14 | type App struct { 15 | Name string `envconfig:"APP_NAME" required:"true"` 16 | Version string `envconfig:"APP_VERSION" required:"true"` 17 | } 18 | 19 | type Config struct { 20 | App App 21 | HTTP httpserver.Config 22 | Logger logger.Config 23 | OTEL otel.Config 24 | Postgres postgres.Config 25 | Redis redis.Config 26 | KafkaProducer kafka_produce.Config 27 | KafkaConsumer kafka_consume.Config 28 | } 29 | 30 | func InitConfig() (Config, error) { 31 | // Парсим и валидируем конфиг 32 | return Config{}, nil 33 | } 34 | -------------------------------------------------------------------------------- /8-vertical-slices/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/golang-school/evolution/8-vertical-slices/internal/adapter/kafka_produce" 5 | "github.com/golang-school/evolution/8-vertical-slices/internal/adapter/postgres" 6 | "github.com/golang-school/evolution/8-vertical-slices/internal/adapter/redis" 7 | "github.com/golang-school/evolution/8-vertical-slices/internal/controller/kafka_consume" 8 | "github.com/golang-school/evolution/8-vertical-slices/pkg/httpserver" 9 | "github.com/golang-school/evolution/8-vertical-slices/pkg/logger" 10 | "github.com/golang-school/evolution/8-vertical-slices/pkg/otel" 11 | ) 12 | 13 | // Конфиг приложения 14 | type App struct { 15 | Name string `envconfig:"APP_NAME" required:"true"` 16 | Version string `envconfig:"APP_VERSION" required:"true"` 17 | } 18 | 19 | type Config struct { 20 | App App 21 | HTTP httpserver.Config 22 | Logger logger.Config 23 | OTEL otel.Config 24 | Postgres postgres.Config 25 | Redis redis.Config 26 | KafkaProducer kafka_produce.Config 27 | KafkaConsumer kafka_consume.Config 28 | } 29 | 30 | func InitConfig() (Config, error) { 31 | // Парсим и валидируем конфиг 32 | return Config{}, nil 33 | } 34 | -------------------------------------------------------------------------------- /2-service-first/internal/profile_service/service.go: -------------------------------------------------------------------------------- 1 | package profile_service 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/golang-school/evolution/2-service-first/internal/kafka_produce" 8 | "github.com/golang-school/evolution/2-service-first/internal/model" 9 | "github.com/golang-school/evolution/2-service-first/internal/postgres" 10 | "github.com/golang-school/evolution/2-service-first/internal/redis" 11 | "github.com/google/uuid" 12 | ) 13 | 14 | var ( 15 | ErrAlreadyExists = errors.New("already exists") 16 | ErrUUIDInvalid = errors.New("invalid UUID format") 17 | ) 18 | 19 | type Redis interface { 20 | IsExists(ctx context.Context, idempotencyKey string) bool 21 | } 22 | 23 | type Kafka interface { 24 | Produce(ctx context.Context, msgs ...kafka_produce.Message) error 25 | } 26 | 27 | type Postgres interface { 28 | CreateProfile(ctx context.Context, profile model.Profile) error 29 | GetProfile(ctx context.Context, id uuid.UUID) (model.Profile, error) 30 | } 31 | 32 | type Profile struct { 33 | postgres Postgres 34 | kafka Kafka 35 | redis Redis 36 | } 37 | 38 | func NewProfile(postgres *postgres.Pool, kafka *kafka_produce.Producer, redis *redis.Client) *Profile { 39 | return &Profile{ 40 | postgres: postgres, 41 | kafka: kafka, 42 | redis: redis, 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /6-layers-ddd/internal/usecase/create_profile.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/6-layers-ddd/internal/dto" 8 | 9 | "github.com/golang-school/evolution/6-layers-ddd/internal/adapter/kafka_produce" 10 | "github.com/golang-school/evolution/6-layers-ddd/internal/domain" 11 | ) 12 | 13 | func (p *Profile) CreateProfile(ctx context.Context, input dto.CreateProfileInput) (dto.CreateProfileOutput, error) { 14 | var output dto.CreateProfileOutput 15 | 16 | // Проверяем в Redis ключу идемпотентности 17 | if p.redis.IsExists(ctx, input.Email) { 18 | return output, domain.ErrAlreadyExists 19 | } 20 | 21 | // Создаём профиль 22 | profile, err := domain.NewProfile(input.Name, input.Age, input.Email) 23 | if err != nil { 24 | return output, fmt.Errorf("new profile: %w", err) 25 | } 26 | 27 | // Сохраняем в БД 28 | err = p.postgres.CreateProfile(ctx, profile) 29 | if err != nil { 30 | return output, fmt.Errorf("create profile in postgres: %w", err) 31 | } 32 | 33 | // Отправляем в Kafka событие создания профиля 34 | err = p.kafka.Produce(ctx, kafka_produce.Message{}) 35 | if err != nil { 36 | return output, fmt.Errorf("kafka produce: %w", err) 37 | } 38 | 39 | return dto.CreateProfileOutput{ 40 | ID: profile.ID, 41 | }, nil 42 | } 43 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/usecase/create_profile.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/7-layers-cqrs/internal/dto" 8 | 9 | "github.com/golang-school/evolution/7-layers-cqrs/internal/adapter/kafka_produce" 10 | "github.com/golang-school/evolution/7-layers-cqrs/internal/domain" 11 | ) 12 | 13 | func (p *Profile) CreateProfile(ctx context.Context, input dto.CreateProfileInput) (dto.CreateProfileOutput, error) { 14 | var output dto.CreateProfileOutput 15 | 16 | // Проверяем в Redis ключу идемпотентности 17 | if p.redis.IsExists(ctx, input.Email) { 18 | return output, domain.ErrAlreadyExists 19 | } 20 | 21 | // Создаём профиль 22 | profile, err := domain.NewProfile(input.Name, input.Age, input.Email) 23 | if err != nil { 24 | return output, fmt.Errorf("new profile: %w", err) 25 | } 26 | 27 | // Сохраняем в БД 28 | err = p.postgresMaster.CreateProfile(ctx, profile) 29 | if err != nil { 30 | return output, fmt.Errorf("create profile in postgres: %w", err) 31 | } 32 | 33 | // Отправляем в Kafka событие создания профиля 34 | err = p.kafka.Produce(ctx, kafka_produce.Message{}) 35 | if err != nil { 36 | return output, fmt.Errorf("kafka produce: %w", err) 37 | } 38 | 39 | return dto.CreateProfileOutput{ 40 | ID: profile.ID, 41 | }, nil 42 | } 43 | -------------------------------------------------------------------------------- /4-layers/internal/usecase/create_profile.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/golang-school/evolution/4-layers/internal/adapter/kafka_produce" 9 | "github.com/golang-school/evolution/4-layers/internal/domain" 10 | "github.com/google/uuid" 11 | ) 12 | 13 | func (p *Profile) CreateProfile(ctx context.Context, name string, age int, email string) (uuid.UUID, error) { 14 | // Проверяем в Redis ключ идемпотентности 15 | if p.redis.IsExists(ctx, name+email) { 16 | return uuid.Nil, domain.ErrAlreadyExists 17 | } 18 | 19 | // Создаём профиль 20 | profile := domain.Profile{ 21 | ID: uuid.New(), 22 | CreatedAt: time.Now(), 23 | Name: name, 24 | Age: age, 25 | Email: email, 26 | } 27 | 28 | // Валидируем 29 | err := profile.Validate() 30 | if err != nil { 31 | return uuid.Nil, fmt.Errorf("validate profile: %w", err) 32 | } 33 | 34 | // Сохраняем в БД 35 | err = p.postgres.CreateProfile(ctx, profile) 36 | if err != nil { 37 | return uuid.Nil, fmt.Errorf("create profile in postgres: %w", err) 38 | } 39 | 40 | // Отправляем в Kafka событие создания профиля 41 | err = p.kafka.Produce(ctx, kafka_produce.Message{}) 42 | if err != nil { 43 | return uuid.Nil, fmt.Errorf("kafka produce: %w", err) 44 | } 45 | 46 | return profile.ID, nil 47 | } 48 | -------------------------------------------------------------------------------- /7-layers-cqrs/internal/usecase/usecase.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golang-school/evolution/7-layers-cqrs/internal/adapter/kafka_produce" 7 | "github.com/golang-school/evolution/7-layers-cqrs/internal/adapter/postgres" 8 | "github.com/golang-school/evolution/7-layers-cqrs/internal/adapter/redis" 9 | "github.com/golang-school/evolution/7-layers-cqrs/internal/domain" 10 | "github.com/google/uuid" 11 | ) 12 | 13 | type Redis interface { 14 | IsExists(ctx context.Context, idempotencyKey string) bool 15 | } 16 | 17 | type Kafka interface { 18 | Produce(ctx context.Context, msgs ...kafka_produce.Message) error 19 | } 20 | 21 | type PostgresMaster interface { 22 | CreateProfile(ctx context.Context, profile domain.Profile) error 23 | } 24 | 25 | type PostgresReplica interface { 26 | GetProfile(ctx context.Context, id uuid.UUID) (domain.Profile, error) 27 | } 28 | 29 | type Profile struct { 30 | postgresMaster PostgresMaster 31 | postgresReplica PostgresReplica 32 | kafka Kafka 33 | redis Redis 34 | } 35 | 36 | func NewProfile(master, replica *postgres.Pool, kafka *kafka_produce.Producer, redis *redis.Client) *Profile { 37 | return &Profile{ 38 | postgresMaster: master, 39 | postgresReplica: replica, 40 | kafka: kafka, 41 | redis: redis, 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /2-service-first/internal/profile_service/create_profile.go: -------------------------------------------------------------------------------- 1 | package profile_service 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/golang-school/evolution/2-service-first/internal/kafka_produce" 9 | 10 | "github.com/golang-school/evolution/2-service-first/internal/model" 11 | "github.com/google/uuid" 12 | ) 13 | 14 | func (p *Profile) CreateProfile(ctx context.Context, name string, age int, email string) (uuid.UUID, error) { 15 | // Проверяем в Redis ключу идемпотентности 16 | if p.redis.IsExists(ctx, name+email) { 17 | return uuid.Nil, ErrAlreadyExists 18 | } 19 | 20 | // Создаём профиль 21 | profile := model.Profile{ 22 | ID: uuid.New(), 23 | CreatedAt: time.Now(), 24 | Name: name, 25 | Age: age, 26 | Email: email, 27 | } 28 | 29 | // Валидируем 30 | err := profile.Validate() 31 | if err != nil { 32 | return uuid.Nil, fmt.Errorf("validate profile: %w", err) 33 | } 34 | 35 | // Сохраняем в БД 36 | err = p.postgres.CreateProfile(ctx, profile) 37 | if err != nil { 38 | return uuid.Nil, fmt.Errorf("create profile in postgres: %w", err) 39 | } 40 | 41 | // Отправляем в Kafka событие создания профиля 42 | err = p.kafka.Produce(ctx, kafka_produce.Message{}) 43 | if err != nil { 44 | return uuid.Nil, fmt.Errorf("kafka produce: %w", err) 45 | } 46 | 47 | return profile.ID, nil 48 | } 49 | -------------------------------------------------------------------------------- /3-service-hell/internal/profile_service/service.go: -------------------------------------------------------------------------------- 1 | package profile_service 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/golang-school/evolution/3-service-hell/internal/kafka_produce" 8 | "github.com/golang-school/evolution/3-service-hell/internal/model" 9 | "github.com/golang-school/evolution/3-service-hell/internal/postgres" 10 | "github.com/golang-school/evolution/3-service-hell/internal/redis" 11 | "github.com/google/uuid" 12 | ) 13 | 14 | var ( 15 | ErrAlreadyExists = errors.New("already exists") 16 | ErrUUIDInvalid = errors.New("invalid UUID format") 17 | ) 18 | 19 | type Redis interface { 20 | IsExists(ctx context.Context, idempotencyKey string) bool 21 | } 22 | 23 | type Postgres interface { 24 | CreateProfile(ctx context.Context, profile model.Profile) error 25 | GetProfile(ctx context.Context, id uuid.UUID) (model.Profile, error) 26 | } 27 | 28 | type MessageService interface { 29 | SendMessage(ctx context.Context, msgs ...kafka_produce.Message) error 30 | } 31 | 32 | type Profile struct { 33 | postgres Postgres 34 | redis Redis 35 | messageService MessageService 36 | } 37 | 38 | func NewProfile(postgres *postgres.Pool, messageService MessageService, redis *redis.Client) *Profile { 39 | return &Profile{ 40 | postgres: postgres, 41 | messageService: messageService, 42 | redis: redis, 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /3-service-hell/internal/profile_service/create_profile.go: -------------------------------------------------------------------------------- 1 | package profile_service 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/golang-school/evolution/3-service-hell/internal/kafka_produce" 9 | 10 | "github.com/golang-school/evolution/3-service-hell/internal/model" 11 | "github.com/google/uuid" 12 | ) 13 | 14 | func (p *Profile) CreateProfile(ctx context.Context, name string, age int, email string) (uuid.UUID, error) { 15 | // Проверяем в Redis ключу идемпотентности 16 | if p.redis.IsExists(ctx, name+email) { 17 | return uuid.Nil, ErrAlreadyExists 18 | } 19 | 20 | // Создаём профиль 21 | profile := model.Profile{ 22 | ID: uuid.New(), 23 | CreatedAt: time.Now(), 24 | Name: name, 25 | Age: age, 26 | Email: email, 27 | } 28 | 29 | // Валидируем 30 | err := profile.Validate() 31 | if err != nil { 32 | return uuid.Nil, fmt.Errorf("validate profile: %w", err) 33 | } 34 | 35 | // Сохраняем в БД 36 | err = p.postgres.CreateProfile(ctx, profile) 37 | if err != nil { 38 | return uuid.Nil, fmt.Errorf("create profile in postgres: %w", err) 39 | } 40 | 41 | // Отправляем в MessageService событие создания профиля 42 | err = p.messageService.SendMessage(ctx, kafka_produce.Message{}) 43 | if err != nil { 44 | return uuid.Nil, fmt.Errorf("send message: %w", err) 45 | } 46 | 47 | return profile.ID, nil 48 | } 49 | -------------------------------------------------------------------------------- /8-vertical-slices/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/golang-school/evolution/8-vertical-slices 2 | 3 | go 1.23.4 4 | 5 | require ( 6 | github.com/go-chi/chi/v5 v5.2.2 7 | github.com/go-playground/validator/v10 v10.27.0 8 | github.com/google/uuid v1.6.0 9 | github.com/prometheus/client_golang v1.22.0 10 | ) 11 | 12 | require ( 13 | github.com/beorn7/perks v1.0.1 // indirect 14 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 15 | github.com/gabriel-vasile/mimetype v1.4.8 // indirect 16 | github.com/go-playground/locales v0.14.1 // indirect 17 | github.com/go-playground/universal-translator v0.18.1 // indirect 18 | github.com/klauspost/compress v1.18.0 // indirect 19 | github.com/leodido/go-urn v1.4.0 // indirect 20 | github.com/mattn/go-colorable v0.1.13 // indirect 21 | github.com/mattn/go-isatty v0.0.19 // indirect 22 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 23 | github.com/pierrec/lz4/v4 v4.1.15 // indirect 24 | github.com/prometheus/client_model v0.6.1 // indirect 25 | github.com/prometheus/common v0.62.0 // indirect 26 | github.com/prometheus/procfs v0.15.1 // indirect 27 | github.com/rs/zerolog v1.34.0 // indirect 28 | github.com/segmentio/kafka-go v0.4.48 // indirect 29 | golang.org/x/crypto v0.33.0 // indirect 30 | golang.org/x/net v0.34.0 // indirect 31 | golang.org/x/sys v0.32.0 // indirect 32 | golang.org/x/text v0.22.0 // indirect 33 | google.golang.org/protobuf v1.36.5 // indirect 34 | ) 35 | -------------------------------------------------------------------------------- /5-layers-dto/internal/usecase/create_profile.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/golang-school/evolution/5-layers-dto/internal/dto" 9 | 10 | "github.com/golang-school/evolution/5-layers-dto/internal/adapter/kafka_produce" 11 | "github.com/golang-school/evolution/5-layers-dto/internal/domain" 12 | "github.com/google/uuid" 13 | ) 14 | 15 | func (p *Profile) CreateProfile(ctx context.Context, input dto.CreateProfileInput) (dto.CreateProfileOutput, error) { 16 | var output dto.CreateProfileOutput 17 | 18 | // Проверяем в Redis ключу идемпотентности 19 | if p.redis.IsExists(ctx, input.Email) { 20 | return output, domain.ErrAlreadyExists 21 | } 22 | 23 | // Создаём профиль 24 | profile := domain.Profile{ 25 | ID: uuid.New(), 26 | CreatedAt: time.Now(), 27 | Name: input.Name, 28 | Age: input.Age, 29 | Email: input.Email, 30 | } 31 | 32 | // Валидируем 33 | err := profile.Validate() 34 | if err != nil { 35 | return output, fmt.Errorf("validate profile: %w", err) 36 | } 37 | 38 | // Сохраняем в БД 39 | err = p.postgres.CreateProfile(ctx, profile) 40 | if err != nil { 41 | return output, fmt.Errorf("create profile in postgres: %w", err) 42 | } 43 | 44 | // Отправляем в Kafka событие создания профиля 45 | err = p.kafka.Produce(ctx, kafka_produce.Message{}) 46 | if err != nil { 47 | return output, fmt.Errorf("kafka produce: %w", err) 48 | } 49 | 50 | return dto.CreateProfileOutput{ 51 | ID: profile.ID, 52 | }, nil 53 | } 54 | -------------------------------------------------------------------------------- /1-handler-first/internal/server/create_profile.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/golang-school/evolution/1-handler-first/pkg/render" 9 | 10 | "github.com/golang-school/evolution/1-handler-first/internal/kafka_produce" 11 | "github.com/golang-school/evolution/1-handler-first/internal/model" 12 | "github.com/google/uuid" 13 | ) 14 | 15 | func (h *Handlers) CreateProfile(w http.ResponseWriter, r *http.Request) { 16 | ctx := r.Context() 17 | 18 | type Input struct { 19 | Name string `json:"name"` 20 | Age int `json:"age"` 21 | Email string `json:"email"` 22 | } 23 | 24 | input := Input{} 25 | 26 | err := json.NewDecoder(r.Body).Decode(&input) 27 | if err != nil { 28 | http.Error(w, err.Error(), http.StatusBadRequest) 29 | 30 | return 31 | } 32 | 33 | // Проверяем в Redis ключу идемпотентности 34 | if h.redis.IsExists(ctx, input.Email) { 35 | http.Error(w, ErrAlreadyExists.Error(), http.StatusBadRequest) 36 | 37 | return 38 | } 39 | 40 | // Создаём профиль 41 | profile := model.Profile{ 42 | ID: uuid.New(), 43 | CreatedAt: time.Now(), 44 | Name: input.Name, 45 | Age: input.Age, 46 | Email: input.Email, 47 | } 48 | 49 | // Валидируем 50 | err = profile.Validate() 51 | if err != nil { 52 | http.Error(w, err.Error(), http.StatusBadRequest) 53 | 54 | return 55 | } 56 | 57 | // Сохраняем в БД 58 | err = h.postgres.CreateProfile(ctx, profile) 59 | if err != nil { 60 | http.Error(w, err.Error(), http.StatusBadRequest) 61 | 62 | return 63 | } 64 | 65 | // Отправляем в Kafka событие создания профиля 66 | err = h.kafka.Produce(ctx, kafka_produce.Message{}) 67 | if err != nil { 68 | http.Error(w, err.Error(), http.StatusBadRequest) 69 | 70 | return 71 | } 72 | 73 | render.JSON(w, profile.ID, http.StatusOK) 74 | } 75 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/profile/create_profile/usecase.go: -------------------------------------------------------------------------------- 1 | package create_profile 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/golang-school/evolution/8-vertical-slices/internal/adapter/kafka_produce" 8 | "github.com/golang-school/evolution/8-vertical-slices/internal/adapter/postgres" 9 | "github.com/golang-school/evolution/8-vertical-slices/internal/adapter/redis" 10 | "github.com/golang-school/evolution/8-vertical-slices/internal/domain" 11 | ) 12 | 13 | type Redis interface { 14 | IsExists(ctx context.Context, idempotencyKey string) bool 15 | } 16 | 17 | type Kafka interface { 18 | Produce(ctx context.Context, msgs ...kafka_produce.Message) error 19 | } 20 | 21 | type Postgres interface { 22 | CreateProfile(ctx context.Context, profile domain.Profile) error 23 | } 24 | 25 | type Usecase struct { 26 | postgres Postgres 27 | kafka Kafka 28 | redis Redis 29 | } 30 | 31 | func New(postgres *postgres.Pool, kafka *kafka_produce.Producer, redis *redis.Client) *Usecase { 32 | uc := &Usecase{ 33 | postgres: postgres, 34 | kafka: kafka, 35 | redis: redis, 36 | } 37 | 38 | usecase = uc // global for handlers 39 | 40 | return uc 41 | } 42 | 43 | func (u *Usecase) CreateProfile(ctx context.Context, input Input) (Output, error) { 44 | if u.redis.IsExists(ctx, input.Email) { 45 | return Output{}, domain.ErrAlreadyExists 46 | } 47 | 48 | profile, err := domain.NewProfile(input.Name, input.Age, input.Email) 49 | if err != nil { 50 | return Output{}, fmt.Errorf("new profile: %w", err) 51 | } 52 | 53 | err = u.postgres.CreateProfile(ctx, profile) 54 | if err != nil { 55 | return Output{}, fmt.Errorf("create profile in postgres: %w", err) 56 | } 57 | 58 | err = u.kafka.Produce(ctx, kafka_produce.Message{}) 59 | if err != nil { 60 | return Output{}, fmt.Errorf("kafka produce: %w", err) 61 | } 62 | 63 | return Output{ 64 | ID: profile.ID, 65 | }, nil 66 | } 67 | -------------------------------------------------------------------------------- /1-handler-first/cmd/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/golang-school/evolution/1-handler-first/config" 11 | "github.com/golang-school/evolution/1-handler-first/internal/kafka_produce" 12 | "github.com/golang-school/evolution/1-handler-first/internal/postgres" 13 | "github.com/golang-school/evolution/1-handler-first/internal/redis" 14 | "github.com/golang-school/evolution/1-handler-first/internal/server" 15 | "github.com/golang-school/evolution/1-handler-first/pkg/httpserver" 16 | "github.com/golang-school/evolution/1-handler-first/pkg/logger" 17 | ) 18 | 19 | // Main функция приложения 20 | func main() { 21 | // Конфиг 22 | c, err := config.InitConfig() 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | // Логгер 28 | logger.Init(c.Logger) 29 | 30 | // Билдим и запускаем приложение 31 | err = AppRun(context.Background(), c) 32 | if err != nil { 33 | panic(err) 34 | } 35 | } 36 | 37 | // Запускаем приложение 38 | func AppRun(ctx context.Context, c config.Config) error { 39 | // Postgres 40 | pgPool, err := postgres.New(ctx, c.Postgres) 41 | if err != nil { 42 | return fmt.Errorf("postgres.New: %w", err) 43 | } 44 | 45 | // Redis 46 | redisClient, err := redis.New(c.Redis) 47 | if err != nil { 48 | return fmt.Errorf("redis.New: %w", err) 49 | } 50 | 51 | // Kafka producer 52 | kafkaProducer := kafka_produce.NewProducer(c.KafkaProducer) 53 | 54 | // HTTP сервер 55 | router := server.Router(pgPool, kafkaProducer, redisClient) 56 | httpServer := httpserver.New(router, c.HTTP) 57 | 58 | // Приложение запущено и готово к работе 59 | 60 | sig := make(chan os.Signal, 1) 61 | signal.Notify(sig, os.Interrupt, syscall.SIGTERM) 62 | 63 | <-sig // ждём здесь сигнала (Ctrl+C или SIGTERM) 64 | 65 | // Закрываем ресурсы 66 | httpServer.Close() 67 | redisClient.Close() 68 | kafkaProducer.Close() 69 | pgPool.Close() 70 | 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /8-vertical-slices/internal/profile/create_profile/consumer.go: -------------------------------------------------------------------------------- 1 | package create_profile 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "io" 7 | "time" 8 | 9 | "github.com/rs/zerolog/log" 10 | "github.com/segmentio/kafka-go" 11 | ) 12 | 13 | type Config struct { 14 | Addr []string `envconfig:"KAFKA_CONSUMER_ADDR" required:"true"` 15 | Topic string `default:"my-topic" envconfig:"KAFKA_CONSUMER_TOPIC"` 16 | Group string `default:"my-group" envconfig:"KAFKA_CONSUMER_GROUP"` 17 | } 18 | 19 | type Consumer struct { 20 | config Config 21 | reader *kafka.Reader 22 | stop context.CancelFunc 23 | done chan struct{} 24 | } 25 | 26 | func NewConsumer(cfg Config) *Consumer { 27 | r := kafka.NewReader(kafka.ReaderConfig{ 28 | Brokers: cfg.Addr, 29 | Topic: cfg.Topic, 30 | GroupID: cfg.Group, 31 | ReadBatchTimeout: time.Second, 32 | CommitInterval: time.Second, 33 | }) 34 | 35 | ctx, stop := context.WithCancel(context.Background()) 36 | 37 | c := &Consumer{ 38 | config: cfg, 39 | reader: r, 40 | stop: stop, 41 | done: make(chan struct{}), 42 | } 43 | 44 | go c.run(ctx) 45 | 46 | return c 47 | } 48 | 49 | func (c *Consumer) run(ctx context.Context) { 50 | log.Info().Msg("kafka consumer: started") 51 | 52 | for { 53 | m, err := c.reader.FetchMessage(ctx) 54 | if err != nil { 55 | log.Error().Err(err).Msg("kafka consumer: FetchMessage") 56 | 57 | if errors.Is(err, io.EOF) || errors.Is(err, context.Canceled) { 58 | break 59 | } 60 | } 61 | 62 | _, err = usecase.CreateProfile(ctx, Input{}) 63 | if err != nil { 64 | log.Error().Err(err).Msg("kafka consumer: create profile usecase") 65 | } 66 | 67 | if err = c.reader.CommitMessages(ctx, m); err != nil { 68 | log.Error().Err(err).Msg("kafka consumer: CommitMessages") 69 | } 70 | } 71 | 72 | close(c.done) 73 | } 74 | 75 | func (c *Consumer) Close() { 76 | log.Info().Msg("kafka consumer: closing") 77 | 78 | c.stop() 79 | 80 | if err := c.reader.Close(); err != nil { 81 | log.Error().Err(err).Msg("kafka consumer: reader.Close") 82 | } 83 | 84 | <-c.done 85 | 86 | log.Info().Msg("kafka consumer: closed") 87 | } 88 | -------------------------------------------------------------------------------- /4-layers/cmd/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/golang-school/evolution/4-layers/config" 11 | "github.com/golang-school/evolution/4-layers/internal/adapter/kafka_produce" 12 | "github.com/golang-school/evolution/4-layers/internal/adapter/postgres" 13 | "github.com/golang-school/evolution/4-layers/internal/adapter/redis" 14 | "github.com/golang-school/evolution/4-layers/internal/controller/http" 15 | "github.com/golang-school/evolution/4-layers/internal/controller/kafka_consume" 16 | "github.com/golang-school/evolution/4-layers/internal/usecase" 17 | "github.com/golang-school/evolution/4-layers/pkg/httpserver" 18 | "github.com/golang-school/evolution/4-layers/pkg/logger" 19 | ) 20 | 21 | // Main функция приложения 22 | func main() { 23 | // Конфиг 24 | c, err := config.InitConfig() 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | // Логгер 30 | logger.Init(c.Logger) 31 | 32 | // Билдим и запускаем приложение 33 | err = AppRun(context.Background(), c) 34 | if err != nil { 35 | panic(err) 36 | } 37 | } 38 | 39 | // Запускаем приложение 40 | func AppRun(ctx context.Context, c config.Config) error { 41 | // Postgres 42 | pgPool, err := postgres.New(ctx, c.Postgres) 43 | if err != nil { 44 | return fmt.Errorf("postgres.New: %w", err) 45 | } 46 | 47 | // Redis 48 | redisClient, err := redis.New(c.Redis) 49 | if err != nil { 50 | return fmt.Errorf("redis.New: %w", err) 51 | } 52 | 53 | // Kafka producer 54 | kafkaProducer := kafka_produce.NewProducer(c.KafkaProducer) 55 | 56 | // Usecase (Service) 57 | profileUsecase := usecase.NewProfile(pgPool, kafkaProducer, redisClient) 58 | 59 | // Kafka consumer 60 | kafkaConsumer := kafka_consume.New(c.KafkaConsumer, profileUsecase) 61 | 62 | // HTTP сервер 63 | router := http.Router(profileUsecase) 64 | httpServer := httpserver.New(router, c.HTTP) 65 | 66 | // Приложение запущено и готово к работе 67 | 68 | sig := make(chan os.Signal, 1) 69 | signal.Notify(sig, os.Interrupt, syscall.SIGTERM) 70 | 71 | <-sig // ждём здесь сигнала (Ctrl+C или SIGTERM) 72 | 73 | // Закрываем ресурсы 74 | kafkaConsumer.Close() 75 | httpServer.Close() 76 | redisClient.Close() 77 | kafkaProducer.Close() 78 | pgPool.Close() 79 | 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /2-service-first/cmd/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/golang-school/evolution/2-service-first/config" 11 | "github.com/golang-school/evolution/2-service-first/internal/kafka_consume" 12 | "github.com/golang-school/evolution/2-service-first/internal/kafka_produce" 13 | "github.com/golang-school/evolution/2-service-first/internal/postgres" 14 | "github.com/golang-school/evolution/2-service-first/internal/profile_service" 15 | "github.com/golang-school/evolution/2-service-first/internal/redis" 16 | "github.com/golang-school/evolution/2-service-first/internal/server" 17 | "github.com/golang-school/evolution/2-service-first/pkg/httpserver" 18 | "github.com/golang-school/evolution/2-service-first/pkg/logger" 19 | ) 20 | 21 | // Main функция приложения 22 | func main() { 23 | // Конфиг 24 | c, err := config.InitConfig() 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | // Логгер 30 | logger.Init(c.Logger) 31 | 32 | // Билдим и запускаем приложение 33 | err = AppRun(context.Background(), c) 34 | if err != nil { 35 | panic(err) 36 | } 37 | } 38 | 39 | // Запускаем приложение 40 | func AppRun(ctx context.Context, c config.Config) error { 41 | // Postgres 42 | pgPool, err := postgres.New(ctx, c.Postgres) 43 | if err != nil { 44 | return fmt.Errorf("postgres.New: %w", err) 45 | } 46 | 47 | // Redis 48 | redisClient, err := redis.New(c.Redis) 49 | if err != nil { 50 | return fmt.Errorf("redis.New: %w", err) 51 | } 52 | 53 | // Kafka producer 54 | kafkaProducer := kafka_produce.NewProducer(c.KafkaProducer) 55 | 56 | // Service 57 | profileService := profile_service.NewProfile(pgPool, kafkaProducer, redisClient) 58 | 59 | // Kafka consumer 60 | kafkaConsumer := kafka_consume.New(c.KafkaConsumer, profileService) 61 | 62 | // HTTP сервер 63 | router := server.Router(profileService) 64 | httpServer := httpserver.New(router, c.HTTP) 65 | 66 | // Приложение запущено и готово к работе 67 | 68 | sig := make(chan os.Signal, 1) 69 | signal.Notify(sig, os.Interrupt, syscall.SIGTERM) 70 | 71 | <-sig // ждём здесь сигнала (Ctrl+C или SIGTERM) 72 | 73 | // Закрываем ресурсы 74 | kafkaConsumer.Close() 75 | httpServer.Close() 76 | redisClient.Close() 77 | kafkaProducer.Close() 78 | pgPool.Close() 79 | 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /5-layers-dto/cmd/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/golang-school/evolution/5-layers-dto/config" 11 | "github.com/golang-school/evolution/5-layers-dto/internal/adapter/kafka_produce" 12 | "github.com/golang-school/evolution/5-layers-dto/internal/adapter/postgres" 13 | "github.com/golang-school/evolution/5-layers-dto/internal/adapter/redis" 14 | "github.com/golang-school/evolution/5-layers-dto/internal/controller/http" 15 | "github.com/golang-school/evolution/5-layers-dto/internal/controller/kafka_consume" 16 | "github.com/golang-school/evolution/5-layers-dto/internal/usecase" 17 | "github.com/golang-school/evolution/5-layers-dto/pkg/httpserver" 18 | "github.com/golang-school/evolution/5-layers-dto/pkg/logger" 19 | ) 20 | 21 | // Main функция приложения 22 | func main() { 23 | // Конфиг 24 | c, err := config.InitConfig() 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | // Логгер 30 | logger.Init(c.Logger) 31 | 32 | // Билдим и запускаем приложение 33 | err = AppRun(context.Background(), c) 34 | if err != nil { 35 | panic(err) 36 | } 37 | } 38 | 39 | // Запускаем приложение 40 | func AppRun(ctx context.Context, c config.Config) error { 41 | // Postgres 42 | pgPool, err := postgres.New(ctx, c.Postgres) 43 | if err != nil { 44 | return fmt.Errorf("postgres.New: %w", err) 45 | } 46 | 47 | // Redis 48 | redisClient, err := redis.New(c.Redis) 49 | if err != nil { 50 | return fmt.Errorf("redis.New: %w", err) 51 | } 52 | 53 | // Kafka producer 54 | kafkaProducer := kafka_produce.NewProducer(c.KafkaProducer) 55 | 56 | // Usecase (Service) 57 | profileUsecase := usecase.NewProfile(pgPool, kafkaProducer, redisClient) 58 | 59 | // Kafka consumer 60 | kafkaConsumer := kafka_consume.New(c.KafkaConsumer, profileUsecase) 61 | 62 | // HTTP сервер 63 | router := http.Router(profileUsecase) 64 | httpServer := httpserver.New(router, c.HTTP) 65 | 66 | // Приложение запущено и готово к работе 67 | 68 | sig := make(chan os.Signal, 1) 69 | signal.Notify(sig, os.Interrupt, syscall.SIGTERM) 70 | 71 | <-sig // ждём здесь сигнала (Ctrl+C или SIGTERM) 72 | 73 | // Закрываем ресурсы 74 | kafkaConsumer.Close() 75 | httpServer.Close() 76 | redisClient.Close() 77 | kafkaProducer.Close() 78 | pgPool.Close() 79 | 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /6-layers-ddd/cmd/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/golang-school/evolution/6-layers-ddd/config" 11 | "github.com/golang-school/evolution/6-layers-ddd/internal/adapter/kafka_produce" 12 | "github.com/golang-school/evolution/6-layers-ddd/internal/adapter/postgres" 13 | "github.com/golang-school/evolution/6-layers-ddd/internal/adapter/redis" 14 | "github.com/golang-school/evolution/6-layers-ddd/internal/controller/http" 15 | "github.com/golang-school/evolution/6-layers-ddd/internal/controller/kafka_consume" 16 | "github.com/golang-school/evolution/6-layers-ddd/internal/usecase" 17 | "github.com/golang-school/evolution/6-layers-ddd/pkg/httpserver" 18 | "github.com/golang-school/evolution/6-layers-ddd/pkg/logger" 19 | ) 20 | 21 | // Main функция приложения 22 | func main() { 23 | // Конфиг 24 | c, err := config.InitConfig() 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | // Логгер 30 | logger.Init(c.Logger) 31 | 32 | // Билдим и запускаем приложение 33 | err = AppRun(context.Background(), c) 34 | if err != nil { 35 | panic(err) 36 | } 37 | } 38 | 39 | // Запускаем приложение 40 | func AppRun(ctx context.Context, c config.Config) error { 41 | // Postgres 42 | pgPool, err := postgres.New(ctx, c.Postgres) 43 | if err != nil { 44 | return fmt.Errorf("postgres.New: %w", err) 45 | } 46 | 47 | // Redis 48 | redisClient, err := redis.New(c.Redis) 49 | if err != nil { 50 | return fmt.Errorf("redis.New: %w", err) 51 | } 52 | 53 | // Kafka producer 54 | kafkaProducer := kafka_produce.NewProducer(c.KafkaProducer) 55 | 56 | // Usecase (Service) 57 | profileUsecase := usecase.NewProfile(pgPool, kafkaProducer, redisClient) 58 | 59 | // Kafka consumer 60 | kafkaConsumer := kafka_consume.New(c.KafkaConsumer, profileUsecase) 61 | 62 | // HTTP сервер 63 | router := http.Router(profileUsecase) 64 | httpServer := httpserver.New(router, c.HTTP) 65 | 66 | // Приложение запущено и готово к работе 67 | 68 | sig := make(chan os.Signal, 1) 69 | signal.Notify(sig, os.Interrupt, syscall.SIGTERM) 70 | 71 | <-sig // ждём здесь сигнала (Ctrl+C или SIGTERM) 72 | 73 | // Закрываем ресурсы 74 | kafkaConsumer.Close() 75 | httpServer.Close() 76 | redisClient.Close() 77 | kafkaProducer.Close() 78 | pgPool.Close() 79 | 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /8-vertical-slices/cmd/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/golang-school/evolution/8-vertical-slices/internal/profile/get_profile" 11 | 12 | "github.com/golang-school/evolution/8-vertical-slices/internal/profile/create_profile" 13 | 14 | "github.com/golang-school/evolution/8-vertical-slices/config" 15 | "github.com/golang-school/evolution/8-vertical-slices/internal/adapter/kafka_produce" 16 | "github.com/golang-school/evolution/8-vertical-slices/internal/adapter/postgres" 17 | "github.com/golang-school/evolution/8-vertical-slices/internal/adapter/redis" 18 | "github.com/golang-school/evolution/8-vertical-slices/internal/controller/http" 19 | "github.com/golang-school/evolution/8-vertical-slices/pkg/httpserver" 20 | "github.com/golang-school/evolution/8-vertical-slices/pkg/logger" 21 | ) 22 | 23 | // Main функция приложения 24 | func main() { 25 | // Конфиг 26 | c, err := config.InitConfig() 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | // Логгер 32 | logger.Init(c.Logger) 33 | 34 | // Билдим и запускаем приложение 35 | err = AppRun(context.Background(), c) 36 | if err != nil { 37 | panic(err) 38 | } 39 | } 40 | 41 | // Запускаем приложение 42 | func AppRun(ctx context.Context, c config.Config) error { 43 | // Postgres 44 | pgPool, err := postgres.New(ctx, c.Postgres) 45 | if err != nil { 46 | return fmt.Errorf("postgres.New: %w", err) 47 | } 48 | 49 | // Redis 50 | redisClient, err := redis.New(c.Redis) 51 | if err != nil { 52 | return fmt.Errorf("redis.New: %w", err) 53 | } 54 | 55 | // Kafka producer 56 | kafkaProducer := kafka_produce.NewProducer(c.KafkaProducer) 57 | 58 | // Create profile usecase 59 | create_profile.New(pgPool, kafkaProducer, redisClient) 60 | createProfileConsumer := create_profile.NewConsumer(c.KafkaConsumer) 61 | 62 | // Get profile usecase 63 | get_profile.New(pgPool) 64 | 65 | // HTTP сервер 66 | router := http.Router() 67 | httpServer := httpserver.New(router, c.HTTP) 68 | 69 | // Приложение запущено и готово к работе 70 | 71 | sig := make(chan os.Signal, 1) 72 | signal.Notify(sig, os.Interrupt, syscall.SIGTERM) 73 | 74 | <-sig // ждём здесь сигнала (Ctrl+C или SIGTERM) 75 | 76 | // Закрываем ресурсы 77 | createProfileConsumer.Close() 78 | httpServer.Close() 79 | redisClient.Close() 80 | kafkaProducer.Close() 81 | pgPool.Close() 82 | 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /3-service-hell/cmd/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/golang-school/evolution/3-service-hell/internal/message_service" 11 | 12 | "github.com/golang-school/evolution/3-service-hell/config" 13 | "github.com/golang-school/evolution/3-service-hell/internal/kafka_consume" 14 | "github.com/golang-school/evolution/3-service-hell/internal/kafka_produce" 15 | "github.com/golang-school/evolution/3-service-hell/internal/postgres" 16 | "github.com/golang-school/evolution/3-service-hell/internal/profile_service" 17 | "github.com/golang-school/evolution/3-service-hell/internal/redis" 18 | "github.com/golang-school/evolution/3-service-hell/internal/server" 19 | "github.com/golang-school/evolution/3-service-hell/pkg/httpserver" 20 | "github.com/golang-school/evolution/3-service-hell/pkg/logger" 21 | ) 22 | 23 | // Main функция приложения 24 | func main() { 25 | // Конфиг 26 | c, err := config.InitConfig() 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | // Логгер 32 | logger.Init(c.Logger) 33 | 34 | // Билдим и запускаем приложение 35 | err = AppRun(context.Background(), c) 36 | if err != nil { 37 | panic(err) 38 | } 39 | } 40 | 41 | // Запускаем приложение 42 | func AppRun(ctx context.Context, c config.Config) error { 43 | // Postgres 44 | pgPool, err := postgres.New(ctx, c.Postgres) 45 | if err != nil { 46 | return fmt.Errorf("postgres.New: %w", err) 47 | } 48 | 49 | // Redis 50 | redisClient, err := redis.New(c.Redis) 51 | if err != nil { 52 | return fmt.Errorf("redis.New: %w", err) 53 | } 54 | 55 | // Kafka producer 56 | kafkaProducer := kafka_produce.NewProducer(c.KafkaProducer) 57 | 58 | // MessageService 59 | messageService := message_service.NewMessageService(kafkaProducer) 60 | 61 | // ProfileService 62 | profileService := profile_service.NewProfile(pgPool, messageService, redisClient) 63 | 64 | // Kafka consumer 65 | kafkaConsumer := kafka_consume.New(c.KafkaConsumer, profileService) 66 | 67 | // HTTP сервер 68 | router := server.Router(profileService) 69 | httpServer := httpserver.New(router, c.HTTP) 70 | 71 | // Приложение запущено и готово к работе 72 | 73 | sig := make(chan os.Signal, 1) 74 | signal.Notify(sig, os.Interrupt, syscall.SIGTERM) 75 | 76 | <-sig // ждём здесь сигнала (Ctrl+C или SIGTERM) 77 | 78 | // Закрываем ресурсы 79 | kafkaConsumer.Close() 80 | httpServer.Close() 81 | redisClient.Close() 82 | kafkaProducer.Close() 83 | pgPool.Close() 84 | 85 | return nil 86 | } 87 | -------------------------------------------------------------------------------- /7-layers-cqrs/cmd/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/golang-school/evolution/7-layers-cqrs/config" 11 | "github.com/golang-school/evolution/7-layers-cqrs/internal/adapter/kafka_produce" 12 | "github.com/golang-school/evolution/7-layers-cqrs/internal/adapter/postgres" 13 | "github.com/golang-school/evolution/7-layers-cqrs/internal/adapter/redis" 14 | "github.com/golang-school/evolution/7-layers-cqrs/internal/controller/http" 15 | "github.com/golang-school/evolution/7-layers-cqrs/internal/controller/kafka_consume" 16 | "github.com/golang-school/evolution/7-layers-cqrs/internal/usecase" 17 | "github.com/golang-school/evolution/7-layers-cqrs/pkg/httpserver" 18 | "github.com/golang-school/evolution/7-layers-cqrs/pkg/logger" 19 | ) 20 | 21 | // Main функция приложения 22 | func main() { 23 | // Конфиг 24 | c, err := config.InitConfig() 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | // Логгер 30 | logger.Init(c.Logger) 31 | 32 | // Билдим и запускаем приложение 33 | err = AppRun(context.Background(), c) 34 | if err != nil { 35 | panic(err) 36 | } 37 | } 38 | 39 | // Запускаем приложение 40 | func AppRun(ctx context.Context, c config.Config) error { 41 | // Postgres master 42 | master, err := postgres.New(ctx, c.Postgres) 43 | if err != nil { 44 | return fmt.Errorf("postgres.New master: %w", err) 45 | } 46 | 47 | // Postgres replica 48 | replica, err := postgres.New(ctx, c.Postgres) 49 | if err != nil { 50 | return fmt.Errorf("postgres.New replica: %w", err) 51 | } 52 | 53 | // Redis 54 | redisClient, err := redis.New(c.Redis) 55 | if err != nil { 56 | return fmt.Errorf("redis.New: %w", err) 57 | } 58 | 59 | // Kafka producer 60 | kafkaProducer := kafka_produce.NewProducer(c.KafkaProducer) 61 | 62 | // Usecase 63 | profileUsecase := usecase.NewProfile(master, replica, kafkaProducer, redisClient) 64 | 65 | // Kafka consumer 66 | kafkaConsumer := kafka_consume.New(c.KafkaConsumer, profileUsecase) 67 | 68 | // HTTP сервер 69 | router := http.Router(profileUsecase) 70 | httpServer := httpserver.New(router, c.HTTP) 71 | 72 | // Приложение запущено и готово к работе 73 | 74 | sig := make(chan os.Signal, 1) 75 | signal.Notify(sig, os.Interrupt, syscall.SIGTERM) 76 | 77 | <-sig // ждём здесь сигнала (Ctrl+C или SIGTERM) 78 | 79 | // Закрываем ресурсы 80 | kafkaConsumer.Close() 81 | httpServer.Close() 82 | redisClient.Close() 83 | kafkaProducer.Close() 84 | master.Close() 85 | replica.Close() 86 | 87 | return nil 88 | } 89 | -------------------------------------------------------------------------------- /1-handler-first/go.sum: -------------------------------------------------------------------------------- 1 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 2 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 3 | github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 4 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 5 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 6 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= 8 | github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= 9 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 10 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 11 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 12 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 13 | github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= 14 | github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= 15 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 16 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 17 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 18 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 19 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 20 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 21 | github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= 22 | github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= 23 | github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= 24 | github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 25 | github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= 26 | github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= 27 | github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= 28 | github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 29 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 30 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 31 | golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= 32 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 33 | google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= 34 | google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 35 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 36 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 37 | -------------------------------------------------------------------------------- /6-layers-ddd/go.sum: -------------------------------------------------------------------------------- 1 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 2 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 3 | github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 4 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 5 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 6 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= 8 | github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= 9 | github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= 10 | github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= 11 | github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= 12 | github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 13 | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= 14 | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 15 | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= 16 | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= 17 | github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= 18 | github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= 19 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 20 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 21 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 22 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 23 | github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= 24 | github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= 25 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 26 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 27 | github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= 28 | github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= 29 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 30 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 31 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 32 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 33 | github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= 34 | github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= 35 | github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= 36 | github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 37 | github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= 38 | github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= 39 | github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= 40 | github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 41 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 42 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 43 | golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= 44 | golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= 45 | golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= 46 | golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= 47 | golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= 48 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 49 | golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= 50 | golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= 51 | google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= 52 | google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 53 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 54 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 55 | -------------------------------------------------------------------------------- /7-layers-cqrs/go.sum: -------------------------------------------------------------------------------- 1 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 2 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 3 | github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 4 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 5 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 6 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= 8 | github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= 9 | github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= 10 | github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= 11 | github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= 12 | github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 13 | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= 14 | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 15 | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= 16 | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= 17 | github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= 18 | github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= 19 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 20 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 21 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 22 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 23 | github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= 24 | github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= 25 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 26 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 27 | github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= 28 | github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= 29 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 30 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 31 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 32 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 33 | github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= 34 | github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= 35 | github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= 36 | github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 37 | github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= 38 | github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= 39 | github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= 40 | github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 41 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 42 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 43 | golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= 44 | golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= 45 | golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= 46 | golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= 47 | golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= 48 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 49 | golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= 50 | golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= 51 | google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= 52 | google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 53 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 54 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 55 | -------------------------------------------------------------------------------- /8-vertical-slices/go.sum: -------------------------------------------------------------------------------- 1 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 2 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 3 | github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 4 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 5 | github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 8 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= 10 | github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= 11 | github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= 12 | github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= 13 | github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= 14 | github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 15 | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= 16 | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 17 | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= 18 | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= 19 | github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= 20 | github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= 21 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 22 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 23 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 24 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 25 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 26 | github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= 27 | github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= 28 | github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= 29 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 30 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 31 | github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= 32 | github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= 33 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 34 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 35 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 36 | github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= 37 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 38 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 39 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 40 | github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= 41 | github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 42 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 43 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 44 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 45 | github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= 46 | github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= 47 | github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= 48 | github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 49 | github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= 50 | github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= 51 | github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= 52 | github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 53 | github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= 54 | github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= 55 | github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= 56 | github.com/segmentio/kafka-go v0.4.48 h1:9jyu9CWK4W5W+SroCe8EffbrRZVqAOkuaLd/ApID4Vs= 57 | github.com/segmentio/kafka-go v0.4.48/go.mod h1:HjF6XbOKh0Pjlkr5GVZxt6CsjjwnmhVOfURM5KMd8qg= 58 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 59 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 60 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 61 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 62 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 63 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 64 | github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= 65 | github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= 66 | github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= 67 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 68 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 69 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 70 | golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= 71 | golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= 72 | golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= 73 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 74 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 75 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 76 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 77 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 78 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 79 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 80 | golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= 81 | golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= 82 | golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= 83 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 84 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 85 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 86 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 87 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 88 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 89 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 90 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 91 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 92 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 93 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 94 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 95 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 96 | golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 97 | golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= 98 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 99 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 100 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 101 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 102 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 103 | golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= 104 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 105 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 106 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 107 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 108 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 109 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 110 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 111 | golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= 112 | golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= 113 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 114 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 115 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 116 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 117 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 118 | google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= 119 | google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 120 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 121 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 122 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 123 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 124 | --------------------------------------------------------------------------------