├── .gitignore ├── .idea ├── .gitignore ├── golang-architecture.iml ├── modules.xml └── vcs.xml ├── factory ├── factory.go ├── go.mod └── test │ └── test.go ├── hexagonal-news-api ├── .idea │ ├── .gitignore │ ├── hexagonal-news-api.iml │ ├── modules.xml │ └── vcs.xml ├── adapter │ ├── input │ │ ├── controller │ │ │ └── news_controller.go │ │ ├── model │ │ │ └── request │ │ │ │ └── news_request.go │ │ └── routes │ │ │ └── routes.go │ └── output │ │ ├── model │ │ └── response │ │ │ └── news_client_response.go │ │ └── news_http │ │ └── news_api_client.go ├── application │ ├── domain │ │ └── news_domain.go │ ├── port │ │ ├── input │ │ │ └── news_use_case.go │ │ └── output │ │ │ └── news_port.go │ └── service │ │ └── news_service.go ├── configuration │ ├── env │ │ └── get_env.go │ ├── logger │ │ └── logger.go │ ├── rest_err │ │ └── rest_err.go │ └── validation │ │ └── validate.go ├── go.mod ├── go.sum └── main.go ├── hexagonal ├── .gitignore ├── adapter │ ├── input │ │ ├── controller │ │ │ ├── create_user_controller.go │ │ │ ├── find_user_controller.go │ │ │ ├── middlewares │ │ │ │ └── jwt_middleware.go │ │ │ └── routes │ │ │ │ └── routes.go │ │ ├── converter │ │ │ └── convert_domain_to_response.go │ │ └── model │ │ │ ├── request │ │ │ └── user_request.go │ │ │ └── response │ │ │ └── user_response.go │ └── output │ │ ├── converter │ │ ├── convert_domain_to_entity.go │ │ └── convert_entity_to_domain.go │ │ ├── model │ │ └── entity │ │ │ └── user_entity.go │ │ └── repository │ │ ├── create_user_repository.go │ │ └── find_user_repository.go ├── application │ ├── constants │ │ └── token.go │ ├── domain │ │ ├── user_domain.go │ │ └── user_token_domain.go │ ├── port │ │ ├── input │ │ │ └── users_use_case.go │ │ └── output │ │ │ └── user_port.go │ └── services │ │ ├── create_user.go │ │ └── find_user.go ├── configuration │ ├── database │ │ └── mongodb │ │ │ └── mongodb_connection.go │ ├── logger │ │ └── logger.go │ ├── rest_errors │ │ └── rest_errors.go │ └── validation │ │ └── validate.go ├── crud_users.http ├── go.mod ├── go.sum └── main.go ├── mvc ├── go.mod ├── go.sum ├── main.go └── src │ ├── controller │ ├── user-form.go │ └── user.go │ ├── models │ ├── repository │ │ └── user.go │ └── user.go │ └── views │ ├── errors.go │ └── user.go ├── singleton ├── .env ├── go.mod ├── go.sum └── singleton.go └── solid ├── dependency-inversion-principle └── dip.go ├── go.mod ├── interface-segregration-principle └── main.go ├── liskov-substitution-principle └── main.go ├── open-closed-principle ├── right_way.go └── wrong_way.go └── single-responsibility-principle ├── god_object.go ├── journal.go ├── load_news.go └── printer.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/golang-architecture.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /factory/factory.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/HunCoding/golang-architecture/factory/test" 7 | ) 8 | 9 | func main() { 10 | c := test.NovoVeiculo(20) 11 | fmt.Println(c) 12 | } 13 | -------------------------------------------------------------------------------- /factory/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/HunCoding/golang-architecture/factory 2 | 3 | go 1.18 4 | -------------------------------------------------------------------------------- /factory/test/test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import "fmt" 4 | 5 | type Veiculo interface { 6 | PrintarQuantidadeRodas() 7 | } 8 | 9 | func NovoVeiculo(qtdRodas int) Veiculo { 10 | if qtdRodas < 0 || qtdRodas > 4 { 11 | return nil 12 | } 13 | 14 | if qtdRodas == 2 { 15 | return &moto{qtdRodas: qtdRodas} 16 | } else if qtdRodas == 4 { 17 | return &carro{qtdRodas: qtdRodas} 18 | } 19 | 20 | return nil 21 | } 22 | 23 | type moto struct { 24 | qtdRodas int 25 | preco float64 26 | } 27 | 28 | func (c *moto) PrintarQuantidadeRodas() { 29 | fmt.Println(c.qtdRodas) 30 | } 31 | 32 | func (c *carro) PrintarQuantidadeRodas() { 33 | fmt.Println(c.qtdRodas) 34 | } 35 | 36 | type carro struct { 37 | qtdRodas int 38 | preco float64 39 | } 40 | 41 | func (c *carro) DefinePreco(preco float64) { 42 | if preco < 5000 || preco > 1000000000 { 43 | fmt.Println("Nao é permitido esse valor") 44 | return 45 | } 46 | 47 | c.preco = preco 48 | } 49 | 50 | func (c *carro) DefineQtdRodas(qtdRodas int) { 51 | if qtdRodas < 0 || qtdRodas > 4 { 52 | fmt.Println("Nao é permitido esse valor") 53 | return 54 | } 55 | 56 | c.qtdRodas = qtdRodas 57 | } 58 | -------------------------------------------------------------------------------- /hexagonal-news-api/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /hexagonal-news-api/.idea/hexagonal-news-api.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /hexagonal-news-api/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /hexagonal-news-api/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /hexagonal-news-api/adapter/input/controller/news_controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/adapter/input/model/request" 7 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/application/domain" 8 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/application/port/input" 9 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/configuration/logger" 10 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/configuration/validation" 11 | "github.com/gin-gonic/gin" 12 | ) 13 | 14 | type newsController struct { 15 | newsUseCase input.NewsUseCase 16 | } 17 | 18 | func NewNewsController( 19 | newsUseCase input.NewsUseCase, 20 | ) *newsController { 21 | return &newsController{newsUseCase} 22 | } 23 | 24 | func (nc *newsController) GetNews(c *gin.Context) { 25 | //q=tesla&from=2023-08-20&apiKey=df969581143d4958a630cb3d0efeaf21 26 | logger.Info("Init GetNews controller api") 27 | newsRequest := request.NewsRequest{} 28 | 29 | if err := c.ShouldBindQuery(&newsRequest); err != nil { 30 | logger.Error("Error trying to validate fields from request", err) 31 | errRest := validation.ValidateUserError(err) 32 | c.JSON(errRest.Code, errRest) 33 | return 34 | } 35 | 36 | newsDomain := domain.NewsReqDomain{ 37 | Subject: newsRequest.Subject, 38 | From: newsRequest.From.Format("2006-01-02"), 39 | } 40 | 41 | newsResponseDomain, err := nc.newsUseCase.GetNewsService(newsDomain) 42 | if err != nil { 43 | c.JSON(err.Code, err) 44 | return 45 | } 46 | 47 | c.JSON(http.StatusOK, newsResponseDomain) 48 | } 49 | -------------------------------------------------------------------------------- /hexagonal-news-api/adapter/input/model/request/news_request.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import "time" 4 | 5 | type NewsRequest struct { 6 | Subject string `form:"subject" binding:"required,min=2" ` 7 | From time.Time `form:"from" binding:"required" time_format:"2006-01-02"` 8 | } 9 | -------------------------------------------------------------------------------- /hexagonal-news-api/adapter/input/routes/routes.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/adapter/input/controller" 5 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/adapter/output/news_http" 6 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/application/service" 7 | "github.com/gin-gonic/gin" 8 | ) 9 | 10 | func InitRoutes(r *gin.Engine) { 11 | newsClient := news_http.NewNewsClient() 12 | newsService := service.NewNewsService(newsClient) 13 | newsController := controller.NewNewsController(newsService) 14 | 15 | r.GET("/news", newsController.GetNews) 16 | } 17 | -------------------------------------------------------------------------------- /hexagonal-news-api/adapter/output/model/response/news_client_response.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | type NewsClientResponse struct { 4 | Status string 5 | TotalResults int64 6 | Articles []ArticleResponse 7 | } 8 | 9 | type ArticleResponse struct { 10 | Source ArticleSourceResponse 11 | Author string 12 | Title string 13 | Description string 14 | URL string 15 | URLToImage string 16 | PublishedAt string 17 | Content string 18 | } 19 | 20 | type ArticleSourceResponse struct { 21 | ID *string 22 | Name string 23 | } 24 | -------------------------------------------------------------------------------- /hexagonal-news-api/adapter/output/news_http/news_api_client.go: -------------------------------------------------------------------------------- 1 | package news_http 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/adapter/output/model/response" 7 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/application/domain" 8 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/configuration/env" 9 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/configuration/rest_err" 10 | "github.com/go-resty/resty/v2" 11 | "github.com/jinzhu/copier" 12 | ) 13 | 14 | type newsClient struct{} 15 | 16 | func NewNewsClient() *newsClient { 17 | client = resty.New().SetBaseURL("https://newsapi.org/v2") 18 | return &newsClient{} 19 | } 20 | 21 | var ( 22 | client *resty.Client 23 | ) 24 | 25 | func (nc *newsClient) GetNewsPort( 26 | newsDomain domain.NewsReqDomain) (*domain.NewsDomain, *rest_err.RestErr) { 27 | 28 | newsResponse := &response.NewsClientResponse{} 29 | 30 | _, err := client.R(). 31 | SetQueryParams(map[string]string{ 32 | "q": newsDomain.Subject, 33 | "from": newsDomain.From, 34 | "apiKey": env.GetNewsTokenAPI(), 35 | }). 36 | SetResult(newsResponse). 37 | Get("/everything") 38 | 39 | fmt.Println(err) 40 | if err != nil { 41 | return nil, rest_err.NewInternalServerError("Error trying to call NewsAPI with params") 42 | } 43 | 44 | newsResponseDomain := &domain.NewsDomain{} 45 | copier.Copy(newsResponseDomain, newsResponse) 46 | 47 | return newsResponseDomain, nil 48 | } 49 | -------------------------------------------------------------------------------- /hexagonal-news-api/application/domain/news_domain.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | type NewsReqDomain struct { 4 | Subject string 5 | From string 6 | } 7 | 8 | type NewsDomain struct { 9 | Status string 10 | TotalResults string 11 | Articles []Article 12 | } 13 | 14 | type Article struct { 15 | Source ArticleSourceResponse 16 | Author string 17 | Title string 18 | Description string 19 | URL string 20 | URLToImage string 21 | PublishedAt string 22 | Content string 23 | } 24 | 25 | type ArticleSourceResponse struct { 26 | ID *string 27 | Name string 28 | } 29 | -------------------------------------------------------------------------------- /hexagonal-news-api/application/port/input/news_use_case.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import ( 4 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/application/domain" 5 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/configuration/rest_err" 6 | ) 7 | 8 | type NewsUseCase interface { 9 | GetNewsService( 10 | domain.NewsReqDomain, 11 | ) (*domain.NewsDomain, *rest_err.RestErr) 12 | } 13 | -------------------------------------------------------------------------------- /hexagonal-news-api/application/port/output/news_port.go: -------------------------------------------------------------------------------- 1 | package output 2 | 3 | import ( 4 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/application/domain" 5 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/configuration/rest_err" 6 | ) 7 | 8 | type NewsPort interface { 9 | GetNewsPort(domain.NewsReqDomain) (*domain.NewsDomain, *rest_err.RestErr) 10 | } 11 | -------------------------------------------------------------------------------- /hexagonal-news-api/application/service/news_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/application/domain" 7 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/application/port/output" 8 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/configuration/logger" 9 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/configuration/rest_err" 10 | ) 11 | 12 | type newsService struct { 13 | newsPort output.NewsPort 14 | } 15 | 16 | func NewNewsService(newsPort output.NewsPort) *newsService { 17 | return &newsService{newsPort} 18 | } 19 | 20 | func (ns *newsService) GetNewsService( 21 | newsDomain domain.NewsReqDomain, 22 | ) (*domain.NewsDomain, *rest_err.RestErr) { 23 | logger.Info( 24 | fmt.Sprintf("Init getNewsService function, subject=%s, from=%s", 25 | newsDomain.Subject, newsDomain.From)) 26 | 27 | newsDomainResponse, err := ns.newsPort.GetNewsPort(newsDomain) 28 | return newsDomainResponse, err 29 | } 30 | -------------------------------------------------------------------------------- /hexagonal-news-api/configuration/env/get_env.go: -------------------------------------------------------------------------------- 1 | package env 2 | 3 | import "os" 4 | 5 | func GetNewsTokenAPI() string { 6 | return os.Getenv("NEWS_API_KEY") 7 | } 8 | -------------------------------------------------------------------------------- /hexagonal-news-api/configuration/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "os" 5 | "strings" 6 | 7 | "go.uber.org/zap" 8 | "go.uber.org/zap/zapcore" 9 | ) 10 | 11 | var ( 12 | log *zap.Logger 13 | 14 | LOG_OUTPUT = "LOG_OUTPUT" 15 | LOG_LEVEL = "LOG_LEVEL" 16 | ) 17 | 18 | func init() { 19 | logConfig := zap.Config{ 20 | OutputPaths: []string{getOutputLogs()}, 21 | Level: zap.NewAtomicLevelAt(getLevelLogs()), 22 | Encoding: "json", 23 | EncoderConfig: zapcore.EncoderConfig{ 24 | LevelKey: "level", 25 | TimeKey: "time", 26 | MessageKey: "message", 27 | EncodeTime: zapcore.ISO8601TimeEncoder, 28 | EncodeLevel: zapcore.LowercaseLevelEncoder, 29 | EncodeCaller: zapcore.ShortCallerEncoder, 30 | }, 31 | } 32 | 33 | log, _ = logConfig.Build() 34 | } 35 | 36 | func Info(message string, tags ...zap.Field) { 37 | log.Info(message, tags...) 38 | log.Sync() 39 | } 40 | 41 | func Error(message string, err error, tags ...zap.Field) { 42 | tags = append(tags, zap.NamedError("error", err)) 43 | log.Info(message, tags...) 44 | log.Sync() 45 | } 46 | 47 | func getOutputLogs() string { 48 | output := strings.ToLower(strings.TrimSpace(os.Getenv(LOG_OUTPUT))) 49 | if output == "" { 50 | return "stdout" 51 | } 52 | 53 | return output 54 | } 55 | 56 | func getLevelLogs() zapcore.Level { 57 | switch strings.ToLower(strings.TrimSpace(os.Getenv(LOG_LEVEL))) { 58 | case "info": 59 | return zapcore.InfoLevel 60 | case "error": 61 | return zapcore.ErrorLevel 62 | case "debug": 63 | return zapcore.DebugLevel 64 | default: 65 | return zapcore.InfoLevel 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /hexagonal-news-api/configuration/rest_err/rest_err.go: -------------------------------------------------------------------------------- 1 | package rest_err 2 | 3 | import "net/http" 4 | 5 | type RestErr struct { 6 | Message string `json:"message"` 7 | Err string `json:"error"` 8 | Code int `json:"code"` 9 | Causes []Causes `json:"causes"` 10 | } 11 | 12 | type Causes struct { 13 | Field string `json:"field"` 14 | Message string `json:"message"` 15 | } 16 | 17 | func (r *RestErr) Error() string { 18 | return r.Message 19 | } 20 | 21 | func NewRestErr(message, err string, code int, causes []Causes) *RestErr { 22 | return &RestErr{ 23 | Message: message, 24 | Err: err, 25 | Code: code, 26 | Causes: causes, 27 | } 28 | } 29 | 30 | func NewBadRequestError(message string) *RestErr { 31 | return &RestErr{ 32 | Message: message, 33 | Err: "bad_request", 34 | Code: http.StatusBadRequest, 35 | } 36 | } 37 | 38 | func NewUnauthorizedRequestError(message string) *RestErr { 39 | return &RestErr{ 40 | Message: message, 41 | Err: "unauthorized", 42 | Code: http.StatusUnauthorized, 43 | } 44 | } 45 | 46 | func NewBadRequestValidationError(message string, causes []Causes) *RestErr { 47 | return &RestErr{ 48 | Message: message, 49 | Err: "bad_request", 50 | Code: http.StatusBadRequest, 51 | Causes: causes, 52 | } 53 | } 54 | 55 | func NewInternalServerError(message string) *RestErr { 56 | return &RestErr{ 57 | Message: message, 58 | Err: "internal_server_error", 59 | Code: http.StatusInternalServerError, 60 | } 61 | } 62 | 63 | func NewNotFoundError(message string) *RestErr { 64 | return &RestErr{ 65 | Message: message, 66 | Err: "not_found", 67 | Code: http.StatusNotFound, 68 | } 69 | } 70 | 71 | func NewForbiddenError(message string) *RestErr { 72 | return &RestErr{ 73 | Message: message, 74 | Err: "forbidden", 75 | Code: http.StatusForbidden, 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /hexagonal-news-api/configuration/validation/validate.go: -------------------------------------------------------------------------------- 1 | package validation 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | 7 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/configuration/rest_err" 8 | "github.com/gin-gonic/gin/binding" 9 | "github.com/go-playground/locales/en" 10 | ut "github.com/go-playground/universal-translator" 11 | "github.com/go-playground/validator/v10" 12 | 13 | en_translation "github.com/go-playground/validator/v10/translations/en" 14 | ) 15 | 16 | var ( 17 | Validate = validator.New() 18 | transl ut.Translator 19 | ) 20 | 21 | func init() { 22 | if val, ok := binding.Validator.Engine().(*validator.Validate); ok { 23 | en := en.New() 24 | unt := ut.New(en, en) 25 | transl, _ = unt.GetTranslator("en") 26 | en_translation.RegisterDefaultTranslations(val, transl) 27 | } 28 | } 29 | 30 | func ValidateUserError( 31 | validation_err error, 32 | ) *rest_err.RestErr { 33 | 34 | var jsonErr *json.UnmarshalTypeError 35 | var jsonValidationError validator.ValidationErrors 36 | 37 | if errors.As(validation_err, &jsonErr) { 38 | return rest_err.NewBadRequestError("Invalid field type") 39 | } else if errors.As(validation_err, &jsonValidationError) { 40 | errorsCauses := []rest_err.Causes{} 41 | 42 | for _, e := range validation_err.(validator.ValidationErrors) { 43 | cause := rest_err.Causes{ 44 | Message: e.Translate(transl), 45 | Field: e.Field(), 46 | } 47 | 48 | errorsCauses = append(errorsCauses, cause) 49 | } 50 | 51 | return rest_err.NewBadRequestValidationError("Some fields are invalid", errorsCauses) 52 | } else { 53 | return rest_err.NewBadRequestError("Error trying to convert fields") 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /hexagonal-news-api/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/HunCoding/golang-architecture/hexagonal-news-api 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.9.1 7 | go.uber.org/zap v1.26.0 8 | ) 9 | 10 | require github.com/joho/godotenv v1.5.1 // indirect 11 | 12 | require ( 13 | github.com/bytedance/sonic v1.9.1 // indirect 14 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect 15 | github.com/gabriel-vasile/mimetype v1.4.2 // indirect 16 | github.com/gin-contrib/sse v0.1.0 // indirect 17 | github.com/go-playground/locales v0.14.1 // indirect 18 | github.com/go-playground/universal-translator v0.18.1 // indirect 19 | github.com/go-playground/validator/v10 v10.14.0 // indirect 20 | github.com/go-resty/resty/v2 v2.8.0 21 | github.com/goccy/go-json v0.10.2 // indirect 22 | github.com/jinzhu/copier v0.4.0 23 | github.com/json-iterator/go v1.1.12 // indirect 24 | github.com/klauspost/cpuid/v2 v2.2.4 // indirect 25 | github.com/leodido/go-urn v1.2.4 // indirect 26 | github.com/mattn/go-isatty v0.0.19 // indirect 27 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 28 | github.com/modern-go/reflect2 v1.0.2 // indirect 29 | github.com/pelletier/go-toml/v2 v2.0.8 // indirect 30 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 31 | github.com/ugorji/go/codec v1.2.11 // indirect 32 | go.uber.org/multierr v1.10.0 // indirect 33 | golang.org/x/arch v0.3.0 // indirect 34 | golang.org/x/crypto v0.13.0 // indirect 35 | golang.org/x/net v0.15.0 // indirect 36 | golang.org/x/sys v0.12.0 // indirect 37 | golang.org/x/text v0.13.0 // indirect 38 | google.golang.org/protobuf v1.30.0 // indirect 39 | gopkg.in/yaml.v3 v3.0.1 // indirect 40 | ) 41 | -------------------------------------------------------------------------------- /hexagonal-news-api/go.sum: -------------------------------------------------------------------------------- 1 | github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= 2 | github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= 3 | github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= 4 | github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= 5 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= 6 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= 7 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 8 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 9 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 10 | github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= 11 | github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= 12 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 13 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 14 | github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= 15 | github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= 16 | github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= 17 | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= 18 | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 19 | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= 20 | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= 21 | github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= 22 | github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= 23 | github.com/go-resty/resty/v2 v2.8.0 h1:J29d0JFWwSWrDCysnOK/YjsPMLQTx0TvgJEHVGvf2L8= 24 | github.com/go-resty/resty/v2 v2.8.0/go.mod h1:UCui0cMHekLrSntoMyofdSTaPpinlRHFtPpizuyDW2w= 25 | github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= 26 | github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 27 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 28 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 29 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 30 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 31 | github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= 32 | github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= 33 | github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= 34 | github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= 35 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 36 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 37 | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 38 | github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= 39 | github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 40 | github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= 41 | github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= 42 | github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= 43 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 44 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 45 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 46 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 47 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 48 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 49 | github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= 50 | github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= 51 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 52 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 53 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 54 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 55 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 56 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 57 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 58 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 59 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 60 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 61 | github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 62 | github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= 63 | github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 64 | github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= 65 | github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= 66 | github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= 67 | github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= 68 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 69 | go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= 70 | go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= 71 | go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 72 | go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= 73 | go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= 74 | golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= 75 | golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= 76 | golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= 77 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 78 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 79 | golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= 80 | golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= 81 | golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= 82 | golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= 83 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 84 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 85 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 86 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 87 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 88 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 89 | golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= 90 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 91 | golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= 92 | golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= 93 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 94 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 95 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 96 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 97 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 98 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 99 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 100 | golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 101 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 102 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 103 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 104 | golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= 105 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 106 | golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= 107 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 108 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 109 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 110 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 111 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 112 | golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= 113 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 114 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 115 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 116 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 117 | golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= 118 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 119 | golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= 120 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 121 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 122 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 123 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 124 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 125 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 126 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 127 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 128 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 129 | google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= 130 | google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 131 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 132 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 133 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 134 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 135 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 136 | rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= 137 | -------------------------------------------------------------------------------- /hexagonal-news-api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/adapter/input/routes" 5 | "github.com/HunCoding/golang-architecture/hexagonal-news-api/configuration/logger" 6 | "github.com/gin-gonic/gin" 7 | "github.com/joho/godotenv" 8 | ) 9 | 10 | func main() { 11 | godotenv.Load() 12 | logger.Info("About to start application") 13 | router := gin.Default() 14 | 15 | routes.InitRoutes(router) 16 | 17 | if err := router.Run(":8080"); err != nil { 18 | logger.Error("Error trying to init application on port 8080", err) 19 | return 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /hexagonal/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | .idea 12 | .env 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Dependency directories (remove the comment below to include it) 18 | # vendor/ -------------------------------------------------------------------------------- /hexagonal/adapter/input/controller/create_user_controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "hexagonal/adapter/input/converter" 5 | "hexagonal/adapter/input/model/request" 6 | "hexagonal/application/domain" 7 | "hexagonal/application/port/input" 8 | "hexagonal/configuration/logger" 9 | "hexagonal/configuration/validation" 10 | "net/http" 11 | 12 | "github.com/gin-gonic/gin" 13 | "go.uber.org/zap" 14 | ) 15 | 16 | func NewUserControllerInterface( 17 | serviceInterface input.UserDomainService, 18 | ) UserControllerInterface { 19 | return &userControllerInterface{ 20 | service: serviceInterface, 21 | } 22 | } 23 | 24 | type UserControllerInterface interface { 25 | FindUserByID(c *gin.Context) 26 | FindUserByEmail(c *gin.Context) 27 | 28 | CreateUser(c *gin.Context) 29 | } 30 | 31 | type userControllerInterface struct { 32 | service input.UserDomainService 33 | } 34 | 35 | func (uc *userControllerInterface) CreateUser(c *gin.Context) { 36 | logger.Info("Init CreateUser controller", 37 | zap.String("journey", "createUser"), 38 | ) 39 | var userRequest request.UserRequest 40 | 41 | if err := c.ShouldBindJSON(&userRequest); err != nil { 42 | logger.Error("Error trying to validate user info", err, 43 | zap.String("journey", "createUser")) 44 | errRest := validation.ValidateUserError(err) 45 | 46 | c.JSON(errRest.Code, errRest) 47 | return 48 | } 49 | 50 | userDomain := domain.UserDomain{ 51 | Email: userRequest.Email, 52 | Password: userRequest.Password, 53 | Name: userRequest.Name, 54 | Age: userRequest.Age, 55 | } 56 | domainResult, err := uc.service.CreateUserServices(userDomain) 57 | if err != nil { 58 | logger.Error( 59 | "Error trying to call CreateUser service", 60 | err, 61 | zap.String("journey", "createUser")) 62 | c.JSON(err.Code, err) 63 | return 64 | } 65 | 66 | logger.Info( 67 | "CreateUser controller executed successfully", 68 | zap.String("userId", domainResult.Id), 69 | zap.String("journey", "createUser")) 70 | 71 | c.JSON(http.StatusOK, converter.ConvertDomainToResponse( 72 | domainResult, 73 | )) 74 | } 75 | -------------------------------------------------------------------------------- /hexagonal/adapter/input/controller/find_user_controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "go.mongodb.org/mongo-driver/bson/primitive" 6 | "go.uber.org/zap" 7 | "hexagonal/adapter/input/converter" 8 | "hexagonal/configuration/logger" 9 | "hexagonal/configuration/rest_errors" 10 | "net/http" 11 | "net/mail" 12 | ) 13 | 14 | func (uc *userControllerInterface) FindUserByID(c *gin.Context) { 15 | logger.Info("Init findUserByID controller", 16 | zap.String("journey", "findUserByID"), 17 | ) 18 | 19 | userId := c.Param("userId") 20 | 21 | if _, err := primitive.ObjectIDFromHex(userId); err != nil { 22 | logger.Error("Error trying to validate userId", 23 | err, 24 | zap.String("journey", "findUserByID"), 25 | ) 26 | errorMessage := rest_errors.NewBadRequestError( 27 | "UserID is not a valid id", 28 | ) 29 | 30 | c.JSON(errorMessage.Code, errorMessage) 31 | return 32 | } 33 | 34 | userDomain, err := uc.service.FindUserByIDServices(userId) 35 | if err != nil { 36 | logger.Error("Error trying to call findUserByID services", 37 | err, 38 | zap.String("journey", "findUserByID"), 39 | ) 40 | c.JSON(err.Code, err) 41 | return 42 | } 43 | 44 | logger.Info("FindUserByID controller executed successfully", 45 | zap.String("journey", "findUserByID"), 46 | ) 47 | c.JSON(http.StatusOK, converter.ConvertDomainToResponse( 48 | userDomain, 49 | )) 50 | } 51 | 52 | func (uc *userControllerInterface) FindUserByEmail(c *gin.Context) { 53 | logger.Info("Init findUserByEmail controller", 54 | zap.String("journey", "findUserByEmail"), 55 | ) 56 | 57 | userEmail := c.Param("userEmail") 58 | 59 | if _, err := mail.ParseAddress(userEmail); err != nil { 60 | logger.Error("Error trying to validate userEmail", 61 | err, 62 | zap.String("journey", "findUserByEmail"), 63 | ) 64 | errorMessage := rest_errors.NewBadRequestError( 65 | "UserEmail is not a valid email", 66 | ) 67 | 68 | c.JSON(errorMessage.Code, errorMessage) 69 | return 70 | } 71 | 72 | userDomain, err := uc.service.FindUserByEmailServices(userEmail) 73 | if err != nil { 74 | logger.Error("Error trying to call findUserByEmail services", 75 | err, 76 | zap.String("journey", "findUserByEmail"), 77 | ) 78 | c.JSON(err.Code, err) 79 | return 80 | } 81 | 82 | logger.Info("findUserByEmail controller executed successfully", 83 | zap.String("journey", "findUserByEmail"), 84 | ) 85 | c.JSON(http.StatusOK, converter.ConvertDomainToResponse( 86 | userDomain, 87 | )) 88 | } 89 | -------------------------------------------------------------------------------- /hexagonal/adapter/input/controller/middlewares/jwt_middleware.go: -------------------------------------------------------------------------------- 1 | package middlewares 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gin-gonic/gin" 6 | "github.com/golang-jwt/jwt" 7 | "hexagonal/application/constants" 8 | "hexagonal/application/domain" 9 | "hexagonal/configuration/logger" 10 | "hexagonal/configuration/rest_errors" 11 | "os" 12 | "strings" 13 | ) 14 | 15 | func VerifyTokenMiddleware(c *gin.Context) { 16 | secret := os.Getenv(constants.JWT_SECRET_KEY) 17 | tokenValue := RemoveBearerPrefix(c.Request.Header.Get("Authorization")) 18 | 19 | token, err := jwt.Parse(tokenValue, func(token *jwt.Token) (interface{}, error) { 20 | if _, ok := token.Method.(*jwt.SigningMethodHMAC); ok { 21 | return []byte(secret), nil 22 | } 23 | 24 | return nil, rest_errors.NewBadRequestError("invalid token") 25 | }) 26 | if err != nil { 27 | errRest := rest_errors.NewUnauthorizedRequestError("invalid token") 28 | c.JSON(errRest.Code, errRest) 29 | c.Abort() 30 | return 31 | } 32 | 33 | claims, ok := token.Claims.(jwt.MapClaims) 34 | if !ok || !token.Valid { 35 | errRest := rest_errors.NewUnauthorizedRequestError("invalid token") 36 | c.JSON(errRest.Code, errRest) 37 | c.Abort() 38 | return 39 | } 40 | 41 | userDomain := domain.UserDomain{ 42 | Id: claims["id"].(string), 43 | Email: claims["email"].(string), 44 | Name: claims["name"].(string), 45 | Age: int8(claims["age"].(float64)), 46 | } 47 | logger.Info(fmt.Sprintf("User authenticated: %#v", userDomain)) 48 | } 49 | 50 | func RemoveBearerPrefix(token string) string { 51 | if strings.HasPrefix(token, "Bearer ") { 52 | token = strings.TrimPrefix("Bearer ", token) 53 | } 54 | 55 | return token 56 | } 57 | -------------------------------------------------------------------------------- /hexagonal/adapter/input/controller/routes/routes.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "hexagonal/adapter/input/controller" 6 | "hexagonal/adapter/input/controller/middlewares" 7 | ) 8 | 9 | func InitRoutes( 10 | r *gin.RouterGroup, 11 | userController controller.UserControllerInterface) { 12 | 13 | r.GET("/getUserById/:userId", middlewares.VerifyTokenMiddleware, userController.FindUserByID) 14 | r.GET("/getUserByEmail/:userEmail", middlewares.VerifyTokenMiddleware, userController.FindUserByEmail) 15 | r.POST("/createUser", userController.CreateUser) 16 | } 17 | -------------------------------------------------------------------------------- /hexagonal/adapter/input/converter/convert_domain_to_response.go: -------------------------------------------------------------------------------- 1 | package converter 2 | 3 | import ( 4 | "hexagonal/adapter/input/model/response" 5 | "hexagonal/application/domain" 6 | ) 7 | 8 | func ConvertDomainToResponse( 9 | userDomain *domain.UserDomain, 10 | ) response.UserResponse { 11 | return response.UserResponse{ 12 | ID: userDomain.Id, 13 | Email: userDomain.Email, 14 | Name: userDomain.Name, 15 | Age: userDomain.Age, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /hexagonal/adapter/input/model/request/user_request.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | type UserRequest struct { 4 | Email string `json:"email" binding:"required,email"` 5 | Password string `json:"password" binding:"required,min=6,containsany=!@#$%*"` 6 | Name string `json:"name" binding:"required,min=4,max=100"` 7 | Age int8 `json:"age" binding:"required,min=1,max=140"` 8 | } 9 | 10 | type UserUpdateRequest struct { 11 | Name string `json:"name" binding:"omitempty,min=4,max=100"` 12 | Age int8 `json:"age" binding:"omitempty,min=1,max=140"` 13 | } 14 | -------------------------------------------------------------------------------- /hexagonal/adapter/input/model/response/user_response.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | type UserResponse struct { 4 | ID string `json:"id"` 5 | Email string `json:"email"` 6 | Name string `json:"name"` 7 | Age int8 `json:"age"` 8 | } 9 | -------------------------------------------------------------------------------- /hexagonal/adapter/output/converter/convert_domain_to_entity.go: -------------------------------------------------------------------------------- 1 | package converter 2 | 3 | import ( 4 | "hexagonal/adapter/output/model/entity" 5 | "hexagonal/application/domain" 6 | ) 7 | 8 | func ConvertDomainToEntity( 9 | domain domain.UserDomain, 10 | ) *entity.UserEntity { 11 | return &entity.UserEntity{ 12 | Email: domain.Email, 13 | Password: domain.Password, 14 | Name: domain.Name, 15 | Age: domain.Age, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /hexagonal/adapter/output/converter/convert_entity_to_domain.go: -------------------------------------------------------------------------------- 1 | package converter 2 | 3 | import ( 4 | "hexagonal/adapter/output/model/entity" 5 | "hexagonal/application/domain" 6 | ) 7 | 8 | func ConvertEntityToDomain( 9 | entity entity.UserEntity, 10 | ) *domain.UserDomain { 11 | domainConverted := &domain.UserDomain{ 12 | Email: entity.Email, 13 | Password: entity.Password, 14 | Name: entity.Name, 15 | Age: entity.Age, 16 | } 17 | 18 | domainConverted.Id = entity.ID.Hex() 19 | return domainConverted 20 | } 21 | -------------------------------------------------------------------------------- /hexagonal/adapter/output/model/entity/user_entity.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "go.mongodb.org/mongo-driver/bson/primitive" 4 | 5 | type UserEntity struct { 6 | ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` 7 | Email string `bson:"email,omitempty"` 8 | Password string `bson:"password,omitempty"` 9 | Name string `bson:"name,omitempty"` 10 | Age int8 `bson:"age,omitempty"` 11 | } 12 | -------------------------------------------------------------------------------- /hexagonal/adapter/output/repository/create_user_repository.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "context" 5 | "go.mongodb.org/mongo-driver/mongo" 6 | "hexagonal/adapter/output/converter" 7 | "hexagonal/application/domain" 8 | "hexagonal/application/port/output" 9 | "hexagonal/configuration/logger" 10 | "hexagonal/configuration/rest_errors" 11 | "os" 12 | 13 | "go.mongodb.org/mongo-driver/bson/primitive" 14 | "go.uber.org/zap" 15 | ) 16 | 17 | const ( 18 | MONGODB_USER_DB = "MONGODB_USER_DB" 19 | ) 20 | 21 | func NewUserRepository( 22 | database *mongo.Database, 23 | ) output.UserPort { 24 | return &userRepository{ 25 | database, 26 | } 27 | } 28 | 29 | type userRepository struct { 30 | databaseConnection *mongo.Database 31 | } 32 | 33 | func (ur *userRepository) CreateUser( 34 | userDomain domain.UserDomain, 35 | ) (*domain.UserDomain, *rest_errors.RestErr) { 36 | logger.Info("Init createUser repository", 37 | zap.String("journey", "createUser")) 38 | 39 | collection_name := os.Getenv(MONGODB_USER_DB) 40 | 41 | collection := ur.databaseConnection.Collection(collection_name) 42 | 43 | value := converter.ConvertDomainToEntity(userDomain) 44 | 45 | result, err := collection.InsertOne(context.Background(), value) 46 | if err != nil { 47 | logger.Error("Error trying to create user", 48 | err, 49 | zap.String("journey", "createUser")) 50 | return nil, rest_errors.NewInternalServerError(err.Error()) 51 | } 52 | 53 | value.ID = result.InsertedID.(primitive.ObjectID) 54 | 55 | logger.Info( 56 | "CreateUser repository executed successfully", 57 | zap.String("userId", value.ID.Hex()), 58 | zap.String("journey", "createUser")) 59 | 60 | return converter.ConvertEntityToDomain(*value), nil 61 | } 62 | -------------------------------------------------------------------------------- /hexagonal/adapter/output/repository/find_user_repository.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "hexagonal/adapter/output/converter" 7 | "hexagonal/adapter/output/model/entity" 8 | "hexagonal/application/domain" 9 | "hexagonal/configuration/logger" 10 | "hexagonal/configuration/rest_errors" 11 | "os" 12 | 13 | "go.mongodb.org/mongo-driver/bson" 14 | "go.mongodb.org/mongo-driver/bson/primitive" 15 | "go.mongodb.org/mongo-driver/mongo" 16 | "go.uber.org/zap" 17 | ) 18 | 19 | func (ur *userRepository) FindUserByEmail( 20 | email string, 21 | ) (*domain.UserDomain, *rest_errors.RestErr) { 22 | logger.Info("Init findUserByEmail repository", 23 | zap.String("journey", "findUserByEmail")) 24 | 25 | collection_name := os.Getenv(MONGODB_USER_DB) 26 | collection := ur.databaseConnection.Collection(collection_name) 27 | 28 | userEntity := &entity.UserEntity{} 29 | 30 | filter := bson.D{{Key: "email", Value: email}} 31 | err := collection.FindOne( 32 | context.Background(), 33 | filter, 34 | ).Decode(userEntity) 35 | 36 | if err != nil { 37 | if err == mongo.ErrNoDocuments { 38 | errorMessage := fmt.Sprintf( 39 | "User not found with this email: %s", email) 40 | logger.Error(errorMessage, 41 | err, 42 | zap.String("journey", "findUserByEmail")) 43 | 44 | return nil, rest_errors.NewNotFoundError(errorMessage) 45 | } 46 | errorMessage := "Error trying to find user by email" 47 | logger.Error(errorMessage, 48 | err, 49 | zap.String("journey", "findUserByEmail")) 50 | 51 | return nil, rest_errors.NewInternalServerError(errorMessage) 52 | } 53 | 54 | logger.Info("FindUserByEmail repository executed successfully", 55 | zap.String("journey", "findUserByEmail"), 56 | zap.String("email", email), 57 | zap.String("userId", userEntity.ID.Hex())) 58 | return converter.ConvertEntityToDomain(*userEntity), nil 59 | } 60 | 61 | func (ur *userRepository) FindUserByID( 62 | id string, 63 | ) (*domain.UserDomain, *rest_errors.RestErr) { 64 | logger.Info("Init findUserByID repository", 65 | zap.String("journey", "findUserByID")) 66 | 67 | collection_name := os.Getenv(MONGODB_USER_DB) 68 | collection := ur.databaseConnection.Collection(collection_name) 69 | 70 | userEntity := &entity.UserEntity{} 71 | 72 | objectId, _ := primitive.ObjectIDFromHex(id) 73 | filter := bson.D{{Key: "_id", Value: objectId}} 74 | err := collection.FindOne( 75 | context.Background(), 76 | filter, 77 | ).Decode(userEntity) 78 | 79 | if err != nil { 80 | if err == mongo.ErrNoDocuments { 81 | errorMessage := fmt.Sprintf( 82 | "User not found with this ID: %s", id) 83 | logger.Error(errorMessage, 84 | err, 85 | zap.String("journey", "findUserByID")) 86 | 87 | return nil, rest_errors.NewNotFoundError(errorMessage) 88 | } 89 | errorMessage := "Error trying to find user by ID" 90 | logger.Error(errorMessage, 91 | err, 92 | zap.String("journey", "findUserByID")) 93 | 94 | return nil, rest_errors.NewInternalServerError(errorMessage) 95 | } 96 | 97 | logger.Info("FindUserByID repository executed successfully", 98 | zap.String("journey", "findUserByID"), 99 | zap.String("userId", userEntity.ID.Hex())) 100 | return converter.ConvertEntityToDomain(*userEntity), nil 101 | } 102 | -------------------------------------------------------------------------------- /hexagonal/application/constants/token.go: -------------------------------------------------------------------------------- 1 | package constants 2 | 3 | var ( 4 | JWT_SECRET_KEY = "JWT_SECRET_KEY" 5 | ) 6 | -------------------------------------------------------------------------------- /hexagonal/application/domain/user_domain.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "crypto/md5" 5 | "encoding/hex" 6 | ) 7 | 8 | type UserDomain struct { 9 | Id string 10 | Email string 11 | Password string 12 | Name string 13 | Age int8 14 | } 15 | 16 | func (ud *UserDomain) EncryptPassword() { 17 | hash := md5.New() 18 | defer hash.Reset() 19 | hash.Write([]byte(ud.Password)) 20 | ud.Password = hex.EncodeToString(hash.Sum(nil)) 21 | } 22 | -------------------------------------------------------------------------------- /hexagonal/application/domain/user_token_domain.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "fmt" 5 | "github.com/golang-jwt/jwt" 6 | "hexagonal/application/constants" 7 | "hexagonal/configuration/rest_errors" 8 | "os" 9 | "time" 10 | ) 11 | 12 | func (ud *UserDomain) GenerateToken() (string, *rest_errors.RestErr) { 13 | secret := os.Getenv(constants.JWT_SECRET_KEY) 14 | 15 | claims := jwt.MapClaims{ 16 | "id": ud.Id, 17 | "email": ud.Email, 18 | "name": ud.Name, 19 | "age": ud.Age, 20 | "exp": time.Now().Add(time.Hour * 24).Unix(), 21 | } 22 | 23 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 24 | 25 | tokenString, err := token.SignedString([]byte(secret)) 26 | if err != nil { 27 | return "", rest_errors.NewInternalServerError( 28 | fmt.Sprintf("error trying to generate jwt token, err=%s", err.Error())) 29 | } 30 | 31 | return tokenString, nil 32 | } 33 | -------------------------------------------------------------------------------- /hexagonal/application/port/input/users_use_case.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import ( 4 | "hexagonal/application/domain" 5 | "hexagonal/configuration/rest_errors" 6 | ) 7 | 8 | type UserDomainService interface { 9 | CreateUserServices(domain.UserDomain) ( 10 | *domain.UserDomain, *rest_errors.RestErr) 11 | FindUserByIDServices( 12 | id string, 13 | ) (*domain.UserDomain, *rest_errors.RestErr) 14 | FindUserByEmailServices( 15 | email string, 16 | ) (*domain.UserDomain, *rest_errors.RestErr) 17 | } 18 | -------------------------------------------------------------------------------- /hexagonal/application/port/output/user_port.go: -------------------------------------------------------------------------------- 1 | package output 2 | 3 | import ( 4 | "hexagonal/application/domain" 5 | "hexagonal/configuration/rest_errors" 6 | ) 7 | 8 | type UserPort interface { 9 | CreateUser( 10 | userDomain domain.UserDomain, 11 | ) (*domain.UserDomain, *rest_errors.RestErr) 12 | 13 | FindUserByEmail( 14 | email string, 15 | ) (*domain.UserDomain, *rest_errors.RestErr) 16 | FindUserByID( 17 | id string, 18 | ) (*domain.UserDomain, *rest_errors.RestErr) 19 | } 20 | -------------------------------------------------------------------------------- /hexagonal/application/services/create_user.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "go.uber.org/zap" 5 | "hexagonal/application/domain" 6 | "hexagonal/application/port/input" 7 | "hexagonal/application/port/output" 8 | "hexagonal/configuration/logger" 9 | "hexagonal/configuration/rest_errors" 10 | ) 11 | 12 | func NewUserDomainService( 13 | userRepository output.UserPort) input.UserDomainService { 14 | return &userDomainService{ 15 | userRepository, 16 | } 17 | } 18 | 19 | type userDomainService struct { 20 | repository output.UserPort 21 | } 22 | 23 | func (ud *userDomainService) CreateUserServices( 24 | userDomain domain.UserDomain, 25 | ) (*domain.UserDomain, *rest_errors.RestErr) { 26 | 27 | logger.Info("Init createUser model.", 28 | zap.String("journey", "createUser")) 29 | 30 | user, _ := ud.FindUserByEmailServices(userDomain.Email) 31 | if user != nil { 32 | return nil, rest_errors.NewBadRequestError("Email is already registered in another account") 33 | } 34 | 35 | userDomain.EncryptPassword() 36 | userDomainRepository, err := ud.repository.CreateUser(userDomain) 37 | if err != nil { 38 | logger.Error("Error trying to call repository", 39 | err, 40 | zap.String("journey", "createUser")) 41 | return nil, err 42 | } 43 | 44 | logger.Info( 45 | "CreateUser service executed successfully", 46 | zap.String("userId", userDomainRepository.Id), 47 | zap.String("journey", "createUser")) 48 | return userDomainRepository, nil 49 | } 50 | -------------------------------------------------------------------------------- /hexagonal/application/services/find_user.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "go.uber.org/zap" 5 | "hexagonal/application/domain" 6 | "hexagonal/configuration/logger" 7 | "hexagonal/configuration/rest_errors" 8 | ) 9 | 10 | func (ud *userDomainService) FindUserByIDServices( 11 | id string, 12 | ) (*domain.UserDomain, *rest_errors.RestErr) { 13 | logger.Info("Init findUserByID services.", 14 | zap.String("journey", "findUserById")) 15 | 16 | return ud.repository.FindUserByID(id) 17 | } 18 | 19 | func (ud *userDomainService) FindUserByEmailServices( 20 | email string, 21 | ) (*domain.UserDomain, *rest_errors.RestErr) { 22 | logger.Info("Init findUserByEmail services.", 23 | zap.String("journey", "findUserById")) 24 | 25 | return ud.repository.FindUserByEmail(email) 26 | } 27 | -------------------------------------------------------------------------------- /hexagonal/configuration/database/mongodb/mongodb_connection.go: -------------------------------------------------------------------------------- 1 | package mongodb 2 | 3 | import ( 4 | "context" 5 | "os" 6 | 7 | "go.mongodb.org/mongo-driver/mongo" 8 | "go.mongodb.org/mongo-driver/mongo/options" 9 | ) 10 | 11 | var ( 12 | MONGODB_URL = "MONGODB_URL" 13 | MONGODB_USER_DB = "MONGODB_USER_DB" 14 | ) 15 | 16 | func NewMongoDBConnection( 17 | ctx context.Context, 18 | ) (*mongo.Database, error) { 19 | mongodb_uri := os.Getenv(MONGODB_URL) 20 | mongodb_database := os.Getenv(MONGODB_USER_DB) 21 | 22 | client, err := mongo.Connect( 23 | ctx, 24 | options.Client().ApplyURI(mongodb_uri)) 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | if err := client.Ping(ctx, nil); err != nil { 30 | return nil, err 31 | } 32 | 33 | return client.Database(mongodb_database), nil 34 | } 35 | -------------------------------------------------------------------------------- /hexagonal/configuration/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "os" 5 | "strings" 6 | 7 | "go.uber.org/zap" 8 | "go.uber.org/zap/zapcore" 9 | ) 10 | 11 | var ( 12 | log *zap.Logger 13 | 14 | LOG_OUTPUT = "LOG_OUTPUT" 15 | LOG_LEVEL = "LOG_LEVEL" 16 | ) 17 | 18 | func init() { 19 | logConfig := zap.Config{ 20 | OutputPaths: []string{getOutputLogs()}, 21 | Level: zap.NewAtomicLevelAt(getLevelLogs()), 22 | Encoding: "json", 23 | EncoderConfig: zapcore.EncoderConfig{ 24 | LevelKey: "level", 25 | TimeKey: "time", 26 | MessageKey: "message", 27 | EncodeTime: zapcore.ISO8601TimeEncoder, 28 | EncodeLevel: zapcore.LowercaseLevelEncoder, 29 | EncodeCaller: zapcore.ShortCallerEncoder, 30 | }, 31 | } 32 | 33 | log, _ = logConfig.Build() 34 | } 35 | 36 | func Info(message string, tags ...zap.Field) { 37 | log.Info(message, tags...) 38 | errSync := log.Sync() 39 | if errSync != nil { 40 | return 41 | } 42 | } 43 | 44 | func Error(message string, err error, tags ...zap.Field) { 45 | tags = append(tags, zap.NamedError("error", err)) 46 | log.Info(message, tags...) 47 | errSync := log.Sync() 48 | if errSync != nil { 49 | return 50 | } 51 | } 52 | 53 | func getOutputLogs() string { 54 | output := strings.ToLower(strings.TrimSpace(os.Getenv(LOG_OUTPUT))) 55 | if output == "" { 56 | return "stdout" 57 | } 58 | 59 | return output 60 | } 61 | 62 | func getLevelLogs() zapcore.Level { 63 | switch strings.ToLower(strings.TrimSpace(os.Getenv(LOG_LEVEL))) { 64 | case "info": 65 | return zapcore.InfoLevel 66 | case "error": 67 | return zapcore.ErrorLevel 68 | case "debug": 69 | return zapcore.DebugLevel 70 | default: 71 | return zapcore.InfoLevel 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /hexagonal/configuration/rest_errors/rest_errors.go: -------------------------------------------------------------------------------- 1 | package rest_errors 2 | 3 | import "net/http" 4 | 5 | type RestErr struct { 6 | Message string `json:"message"` 7 | Err string `json:"error"` 8 | Code int `json:"code"` 9 | Causes []Causes `json:"causes"` 10 | } 11 | 12 | type Causes struct { 13 | Field string `json:"field"` 14 | Message string `json:"message"` 15 | } 16 | 17 | func (r *RestErr) Error() string { 18 | return r.Message 19 | } 20 | 21 | func NewBadRequestError(message string) *RestErr { 22 | return &RestErr{ 23 | Message: message, 24 | Err: "bad_request", 25 | Code: http.StatusBadRequest, 26 | } 27 | } 28 | 29 | func NewUnauthorizedRequestError(message string) *RestErr { 30 | return &RestErr{ 31 | Message: message, 32 | Err: "unauthorized", 33 | Code: http.StatusUnauthorized, 34 | } 35 | } 36 | 37 | func NewBadRequestValidationError(message string, causes []Causes) *RestErr { 38 | return &RestErr{ 39 | Message: message, 40 | Err: "bad_request", 41 | Code: http.StatusBadRequest, 42 | Causes: causes, 43 | } 44 | } 45 | 46 | func NewInternalServerError(message string) *RestErr { 47 | return &RestErr{ 48 | Message: message, 49 | Err: "internal_server_error", 50 | Code: http.StatusInternalServerError, 51 | } 52 | } 53 | 54 | func NewNotFoundError(message string) *RestErr { 55 | return &RestErr{ 56 | Message: message, 57 | Err: "not_found", 58 | Code: http.StatusNotFound, 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /hexagonal/configuration/validation/validate.go: -------------------------------------------------------------------------------- 1 | package validation 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "hexagonal/configuration/rest_errors" 7 | 8 | "github.com/gin-gonic/gin/binding" 9 | "github.com/go-playground/locales/en" 10 | ut "github.com/go-playground/universal-translator" 11 | "github.com/go-playground/validator/v10" 12 | 13 | en_translation "github.com/go-playground/validator/v10/translations/en" 14 | ) 15 | 16 | var ( 17 | transl ut.Translator 18 | ) 19 | 20 | func init() { 21 | if val, ok := binding.Validator.Engine().(*validator.Validate); ok { 22 | enTranslator := en.New() 23 | unt := ut.New(enTranslator, enTranslator) 24 | transl, _ = unt.GetTranslator("en") 25 | err := en_translation.RegisterDefaultTranslations(val, transl) 26 | if err != nil { 27 | return 28 | } 29 | } 30 | } 31 | 32 | func ValidateUserError( 33 | validation_err error, 34 | ) *rest_errors.RestErr { 35 | 36 | var jsonErr *json.UnmarshalTypeError 37 | var jsonValidationError validator.ValidationErrors 38 | 39 | if errors.As(validation_err, &jsonErr) { 40 | return rest_errors.NewBadRequestError("Invalid field type") 41 | } else if errors.As(validation_err, &jsonValidationError) { 42 | errorsCauses := []rest_errors.Causes{} 43 | 44 | for _, e := range validation_err.(validator.ValidationErrors) { 45 | cause := rest_errors.Causes{ 46 | Message: e.Translate(transl), 47 | Field: e.Field(), 48 | } 49 | 50 | errorsCauses = append(errorsCauses, cause) 51 | } 52 | 53 | return rest_errors.NewBadRequestValidationError("Some fields are invalid", errorsCauses) 54 | } else { 55 | return rest_errors.NewBadRequestError("Error trying to convert fields") 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /hexagonal/crud_users.http: -------------------------------------------------------------------------------- 1 | // Buscar usuário no banco de dados por email 2 | GET http://localhost:8080/getUserByEmail/huncoding@gmail.com 3 | Accept: application/json 4 | Authorization: 5 | ### 6 | 7 | // Buscar usuário no banco de dados por email 8 | GET http://localhost:8080/getUserById/647b3fc9c5be50a5f2e48008 9 | Accept: application/json 10 | Authorization: 11 | ### 12 | 13 | // Criar um usuario dentro do banco de dados 14 | POST http://localhost:8080/createUser 15 | Content-Type: application/json 16 | 17 | { 18 | "email": "huncoding@gmail.com", 19 | "age": 20, 20 | "password": "huncoding#!@!dwdw", 21 | "name": "Huncoding" 22 | } 23 | ### 24 | 25 | // Atualiza um usuario já criado dentro do banco de dados 26 | PUT http://localhost:8080/updateUser/6423852a15cd25e0b80f8535 27 | Content-Type: application/json 28 | 29 | { 30 | "email": "otavio20313131@test.com", 31 | "age": 90 32 | } 33 | ### 34 | 35 | // Apaga um usuário do banco de dados dado um userId 36 | DELETE http://localhost:8080/deleteUser/6423852a15cd25e0b80f8535 37 | Accept: application/json 38 | ### 39 | 40 | // Realiza o login do usuário com email e senha 41 | POST http://localhost:8080/login 42 | Content-Type: application/json 43 | 44 | { 45 | "email": "huncoding@gmail.com", 46 | "password": "huncoding#!@!dwdw" 47 | } 48 | ### -------------------------------------------------------------------------------- /hexagonal/go.mod: -------------------------------------------------------------------------------- 1 | module hexagonal 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.9.1 7 | github.com/go-playground/locales v0.14.1 8 | github.com/go-playground/universal-translator v0.18.1 9 | github.com/go-playground/validator/v10 v10.14.0 10 | github.com/golang-jwt/jwt v3.2.2+incompatible 11 | github.com/joho/godotenv v1.5.1 12 | go.mongodb.org/mongo-driver v1.11.7 13 | go.uber.org/zap v1.24.0 14 | ) 15 | 16 | require ( 17 | github.com/bytedance/sonic v1.9.1 // indirect 18 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect 19 | github.com/gabriel-vasile/mimetype v1.4.2 // indirect 20 | github.com/gin-contrib/sse v0.1.0 // indirect 21 | github.com/goccy/go-json v0.10.2 // indirect 22 | github.com/golang/snappy v0.0.1 // indirect 23 | github.com/json-iterator/go v1.1.12 // indirect 24 | github.com/klauspost/compress v1.13.6 // indirect 25 | github.com/klauspost/cpuid/v2 v2.2.4 // indirect 26 | github.com/leodido/go-urn v1.2.4 // indirect 27 | github.com/mattn/go-isatty v0.0.19 // indirect 28 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 29 | github.com/modern-go/reflect2 v1.0.2 // indirect 30 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect 31 | github.com/pelletier/go-toml/v2 v2.0.8 // indirect 32 | github.com/pkg/errors v0.9.1 // indirect 33 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 34 | github.com/ugorji/go/codec v1.2.11 // indirect 35 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect 36 | github.com/xdg-go/scram v1.1.1 // indirect 37 | github.com/xdg-go/stringprep v1.0.3 // indirect 38 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect 39 | go.uber.org/atomic v1.7.0 // indirect 40 | go.uber.org/multierr v1.6.0 // indirect 41 | golang.org/x/arch v0.3.0 // indirect 42 | golang.org/x/crypto v0.9.0 // indirect 43 | golang.org/x/net v0.10.0 // indirect 44 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect 45 | golang.org/x/sys v0.8.0 // indirect 46 | golang.org/x/text v0.9.0 // indirect 47 | google.golang.org/protobuf v1.30.0 // indirect 48 | gopkg.in/yaml.v3 v3.0.1 // indirect 49 | ) 50 | -------------------------------------------------------------------------------- /hexagonal/go.sum: -------------------------------------------------------------------------------- 1 | github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= 2 | github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= 3 | github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= 4 | github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= 5 | github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= 6 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= 7 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= 8 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 10 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= 12 | github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= 13 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 14 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 15 | github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= 16 | github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= 17 | github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= 18 | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= 19 | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 20 | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= 21 | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= 22 | github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= 23 | github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= 24 | github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= 25 | github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 26 | github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= 27 | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 28 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 29 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= 30 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 31 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 32 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 33 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 34 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 35 | github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= 36 | github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= 37 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 38 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 39 | github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= 40 | github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 41 | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 42 | github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= 43 | github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 44 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 45 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 46 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 47 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 48 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 49 | github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= 50 | github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= 51 | github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= 52 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 53 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 54 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 55 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 56 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 57 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 58 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= 59 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= 60 | github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= 61 | github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= 62 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 63 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 64 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 65 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 66 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 67 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 68 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 69 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 70 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 71 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 72 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 73 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 74 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 75 | github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 76 | github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= 77 | github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 78 | github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= 79 | github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= 80 | github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= 81 | github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= 82 | github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= 83 | github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= 84 | github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= 85 | github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= 86 | github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E= 87 | github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= 88 | github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs= 89 | github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= 90 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= 91 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= 92 | go.mongodb.org/mongo-driver v1.11.7 h1:LIwYxASDLGUg/8wOhgOOZhX8tQa/9tgZPgzZoVqJvcs= 93 | go.mongodb.org/mongo-driver v1.11.7/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY= 94 | go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= 95 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 96 | go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= 97 | go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= 98 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 99 | go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= 100 | go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 101 | golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= 102 | golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= 103 | golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= 104 | golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 105 | golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= 106 | golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= 107 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 108 | golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= 109 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 110 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 111 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 112 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 113 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 114 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 115 | golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 116 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 117 | golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= 118 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 119 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 120 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 121 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 122 | golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= 123 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 124 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 125 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 126 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 127 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 128 | google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= 129 | google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 130 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 131 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 132 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 133 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 134 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 135 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 136 | rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= 137 | -------------------------------------------------------------------------------- /hexagonal/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "github.com/gin-gonic/gin" 6 | "github.com/joho/godotenv" 7 | "go.mongodb.org/mongo-driver/mongo" 8 | "hexagonal/adapter/input/controller" 9 | "hexagonal/adapter/input/controller/routes" 10 | "hexagonal/adapter/output/repository" 11 | service "hexagonal/application/services" 12 | "hexagonal/configuration/database/mongodb" 13 | "hexagonal/configuration/logger" 14 | "log" 15 | ) 16 | 17 | func main() { 18 | logger.Info("About to start user application") 19 | 20 | err := godotenv.Load() 21 | if err != nil { 22 | log.Fatal("Error loading .env file") 23 | return 24 | } 25 | 26 | database, err := mongodb.NewMongoDBConnection(context.Background()) 27 | if err != nil { 28 | log.Fatalf( 29 | "Error trying to connect to database, error=%s \n", 30 | err.Error()) 31 | return 32 | } 33 | 34 | userController := initDependencies(database) 35 | 36 | router := gin.Default() 37 | routes.InitRoutes(&router.RouterGroup, userController) 38 | 39 | if err := router.Run(":8080"); err != nil { 40 | log.Fatal(err) 41 | } 42 | } 43 | 44 | func initDependencies( 45 | database *mongo.Database, 46 | ) controller.UserControllerInterface { 47 | userRepo := repository.NewUserRepository(database) 48 | userService := service.NewUserDomainService(userRepo) 49 | return controller.NewUserControllerInterface(userService) 50 | } 51 | -------------------------------------------------------------------------------- /mvc/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/HunCoding/golang-architecture/mvc 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.8.1 7 | go.mongodb.org/mongo-driver v1.10.1 8 | ) 9 | 10 | require ( 11 | github.com/gin-contrib/sse v0.1.0 // indirect 12 | github.com/go-playground/locales v0.14.0 // indirect 13 | github.com/go-playground/universal-translator v0.18.0 // indirect 14 | github.com/go-playground/validator/v10 v10.10.0 // indirect 15 | github.com/goccy/go-json v0.9.7 // indirect 16 | github.com/golang/snappy v0.0.1 // indirect 17 | github.com/json-iterator/go v1.1.12 // indirect 18 | github.com/klauspost/compress v1.13.6 // indirect 19 | github.com/leodido/go-urn v1.2.1 // indirect 20 | github.com/mattn/go-isatty v0.0.14 // indirect 21 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 22 | github.com/modern-go/reflect2 v1.0.2 // indirect 23 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect 24 | github.com/pelletier/go-toml/v2 v2.0.1 // indirect 25 | github.com/pkg/errors v0.9.1 // indirect 26 | github.com/ugorji/go/codec v1.2.7 // indirect 27 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect 28 | github.com/xdg-go/scram v1.1.1 // indirect 29 | github.com/xdg-go/stringprep v1.0.3 // indirect 30 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect 31 | golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect 32 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect 33 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect 34 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect 35 | golang.org/x/text v0.3.7 // indirect 36 | google.golang.org/protobuf v1.28.0 // indirect 37 | gopkg.in/yaml.v2 v2.4.0 // indirect 38 | ) 39 | -------------------------------------------------------------------------------- /mvc/go.sum: -------------------------------------------------------------------------------- 1 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 4 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 6 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 7 | github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= 8 | github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= 9 | github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= 10 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 11 | github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= 12 | github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= 13 | github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= 14 | github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= 15 | github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0= 16 | github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= 17 | github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= 18 | github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 19 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 20 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= 21 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 22 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 23 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 24 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 25 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 26 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 27 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 28 | github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= 29 | github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 30 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 31 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 32 | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 33 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 34 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 35 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 36 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 37 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 38 | github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= 39 | github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= 40 | github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= 41 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 42 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 43 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 44 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 45 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 46 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= 47 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= 48 | github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= 49 | github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= 50 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 51 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 52 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 53 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 54 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 55 | github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 56 | github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= 57 | github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= 58 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 59 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 60 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 61 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 62 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= 63 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 64 | github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= 65 | github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= 66 | github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= 67 | github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= 68 | github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= 69 | github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= 70 | github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= 71 | github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E= 72 | github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= 73 | github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs= 74 | github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= 75 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= 76 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= 77 | go.mongodb.org/mongo-driver v1.10.1 h1:NujsPveKwHaWuKUer/ceo9DzEe7HIj1SlJ6uvXZG0S4= 78 | go.mongodb.org/mongo-driver v1.10.1/go.mod h1:z4XpeoU6w+9Vht+jAFyLgVrD+jGSQQe0+CBWFHNiHt8= 79 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 80 | golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= 81 | golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 82 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 83 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= 84 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 85 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 86 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 87 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 88 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 89 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 90 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 91 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU= 92 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 93 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 94 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 95 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 96 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 97 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 98 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 99 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 100 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 101 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 102 | google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= 103 | google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 104 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 105 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 106 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 107 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 108 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 109 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 110 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 111 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 112 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 113 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 114 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 115 | -------------------------------------------------------------------------------- /mvc/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/HunCoding/golang-architecture/mvc/src/controller" 5 | "github.com/HunCoding/golang-architecture/mvc/src/controller/repository" 6 | "github.com/gin-gonic/gin" 7 | "go.mongodb.org/mongo-driver/mongo" 8 | ) 9 | 10 | func main() { 11 | client, _ := mongo.NewClient() 12 | repo := repository.NewUserRepository(client) 13 | control := controller.NewUserController(repo) 14 | 15 | router := gin.Default() 16 | 17 | router.POST("/user", control.CreateUser) 18 | 19 | router.Run(":9090") 20 | } 21 | -------------------------------------------------------------------------------- /mvc/src/controller/user-form.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import "github.com/HunCoding/golang-architecture/mvc/src/models" 4 | 5 | type UserForm struct { 6 | Email string `json:"email" binding:"required"` 7 | Name string `json:"name" binding:"required"` 8 | Age int `json:"age" binding:"required"` 9 | Password string `json:"password" binding:"required"` 10 | } 11 | 12 | func (uf *UserForm) ConvertInputUserToUserEntity() *models.User { 13 | return &models.User{ 14 | Email: uf.Email, 15 | Name: uf.Name, 16 | Age: uf.Age, 17 | Password: uf.Password, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /mvc/src/controller/user.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/HunCoding/golang-architecture/mvc/src/models/repository" 8 | "github.com/HunCoding/golang-architecture/mvc/src/views" 9 | "github.com/gin-gonic/gin" 10 | ) 11 | 12 | func NewUserController( 13 | userRepository repository.UserRepository, 14 | ) UserControllerInterface { 15 | return &userController{userRepository} 16 | } 17 | 18 | type UserControllerInterface interface { 19 | CreateUser(c *gin.Context) 20 | } 21 | 22 | type userController struct { 23 | userRepository repository.UserRepository 24 | } 25 | 26 | func (uc *userController) CreateUser(c *gin.Context) { 27 | user := UserForm{} 28 | 29 | if err := c.ShouldBindJSON(&user); err != nil { 30 | errPerso := views.ParseError( 31 | fmt.Sprintf("Error trying to parse user, error=%s", err), 32 | http.StatusBadRequest, 33 | ) 34 | 35 | c.JSON(errPerso.ErrorCode, errPerso) 36 | } 37 | 38 | userModel := user.ConvertInputUserToUserEntity() 39 | createdUser, err := uc.userRepository.CreateUser(userModel) 40 | if err != nil { 41 | errPerso := views.ParseError( 42 | fmt.Sprintf("Error trying to create user, error=%s", err), 43 | http.StatusInternalServerError, 44 | ) 45 | 46 | c.JSON(errPerso.ErrorCode, errPerso) 47 | } 48 | 49 | c.JSON(http.StatusOK, views.ConvertUserIntoView(createdUser)) 50 | } 51 | -------------------------------------------------------------------------------- /mvc/src/models/repository/user.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "github.com/HunCoding/golang-architecture/mvc/src/models" 5 | "go.mongodb.org/mongo-driver/mongo" 6 | ) 7 | 8 | func NewUserRepository( 9 | mongodbClient *mongo.Client, 10 | ) UserRepository { 11 | return &userRepository{mongodbClient} 12 | } 13 | 14 | type UserRepository interface { 15 | CreateUser(user *models.User) (*models.User, error) 16 | } 17 | 18 | type userRepository struct { 19 | mongodbClient *mongo.Client 20 | } 21 | 22 | func (ur *userRepository) CreateUser(user *models.User) (*models.User, error) { 23 | //TODO: Implement mongodb user insert 24 | return nil, nil 25 | } 26 | -------------------------------------------------------------------------------- /mvc/src/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type User struct { 4 | Email string `bson:"email"` 5 | Name string `bson:"name"` 6 | Age int `bson:"age"` 7 | Password string `bson:"password"` 8 | } 9 | 10 | func (u *User) VerifyEmail() { 11 | // TODO: Enviar email para o usuario verificando o email dele 12 | } 13 | 14 | func (u *User) CheckDuplicateEmail() { 15 | // TODO: Verificar se o email ja nao existe no banco de dados 16 | } 17 | -------------------------------------------------------------------------------- /mvc/src/views/errors.go: -------------------------------------------------------------------------------- 1 | package views 2 | 3 | type ErrorView struct { 4 | Message string `json:"message"` 5 | ErrorCode int `json:"errorCode"` 6 | } 7 | 8 | func ParseError( 9 | message string, 10 | errorCode int, 11 | ) *ErrorView { 12 | return &ErrorView{ 13 | message, errorCode, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /mvc/src/views/user.go: -------------------------------------------------------------------------------- 1 | package views 2 | 3 | import "github.com/HunCoding/golang-architecture/mvc/src/models" 4 | 5 | type User struct { 6 | Email string `json:"email"` 7 | Name string `json:"name"` 8 | Age int `json:"age"` 9 | } 10 | 11 | func ConvertUserIntoView(user *models.User) *User { 12 | return &User{ 13 | Email: user.Email, 14 | Name: user.Name, 15 | Age: user.Age, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /singleton/.env: -------------------------------------------------------------------------------- 1 | CAPITALS=TESTE1,TESTE2,TESTE3 -------------------------------------------------------------------------------- /singleton/go.mod: -------------------------------------------------------------------------------- 1 | module singleton 2 | 3 | go 1.19 4 | 5 | require github.com/joho/godotenv v1.5.1 // indirect 6 | -------------------------------------------------------------------------------- /singleton/go.sum: -------------------------------------------------------------------------------- 1 | github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= 2 | github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= 3 | -------------------------------------------------------------------------------- /singleton/singleton.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/joho/godotenv" 6 | "os" 7 | "strings" 8 | "sync" 9 | ) 10 | 11 | type singletonDatabase struct { 12 | capital []string 13 | } 14 | 15 | func (sd *singletonDatabase) GetCapitals() []string { 16 | return sd.capital 17 | } 18 | 19 | var once sync.Once 20 | var instance *singletonDatabase 21 | 22 | func NewSingletonDatabase() *singletonDatabase { 23 | godotenv.Load(".env") 24 | capitals := strings.Split(os.Getenv("CAPITALS"), ",") 25 | once.Do(func() { 26 | db := singletonDatabase{capitals} 27 | fmt.Println("Iniciou a variavel") 28 | instance = &db 29 | }) 30 | fmt.Println(&instance) 31 | return instance 32 | } 33 | 34 | func main() { 35 | fmt.Println(NewSingletonDatabase(), NewSingletonDatabase()) 36 | } 37 | -------------------------------------------------------------------------------- /solid/dependency-inversion-principle/dip.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "strconv" 7 | ) 8 | 9 | type UserRepository interface { 10 | InsertUser(user_id string, name string) *User 11 | GetUserByID(user_id string) *User 12 | } 13 | 14 | type mysqlRepository struct{} 15 | type mongodbRepository struct{} 16 | 17 | func (m *mongodbRepository) InsertUser(user_id string, name string) *User { 18 | panic("not implemented") // TODO: Implement 19 | } 20 | 21 | func (m *mongodbRepository) GetUserByID(user_id string) *User { 22 | panic("not implemented") // TODO: Implement 23 | } 24 | 25 | type userServices struct { 26 | repo UserRepository 27 | } 28 | 29 | func (m *mysqlRepository) InsertUser(user_id string, name string) *User { 30 | user := User{user_id, name} 31 | inMemoUsers[user_id] = user 32 | return &user 33 | } 34 | 35 | func (m *mysqlRepository) GetUserByID(user_id string) *User { 36 | user, ok := inMemoUsers[user_id] 37 | if !ok { 38 | return nil 39 | } 40 | 41 | return &user 42 | } 43 | 44 | var ( 45 | inMemoUsers map[string]User 46 | ) 47 | 48 | func init() { 49 | inMemoUsers = make(map[string]User) 50 | } 51 | 52 | type User struct { 53 | id string 54 | name string 55 | } 56 | 57 | func main() { 58 | mongodbRepo := &mongodbRepository{} 59 | 60 | services := &userServices{mongodbRepo} 61 | 62 | name := "HunCoding" 63 | user_inserted := services.InsertUserServices(name) 64 | fmt.Printf("User inserted: %#v \n", user_inserted) 65 | 66 | user_returned := services.GetUserByIDServices(user_inserted.id) 67 | fmt.Printf("User returned from get: %#v \n", user_returned) 68 | } 69 | 70 | // Alto nivel 71 | func (s *userServices) GetUserByIDServices(user_id string) *User { 72 | return s.repo.GetUserByID(user_id) 73 | } 74 | 75 | // Alto nivel 76 | func (s *userServices) InsertUserServices(name string) *User { 77 | user_id := strconv.Itoa(rand.Intn(100000)) 78 | 79 | return s.repo.InsertUser(user_id, name) 80 | } 81 | -------------------------------------------------------------------------------- /solid/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/HunCoding/golang-architecture/solid 2 | 3 | go 1.18 4 | -------------------------------------------------------------------------------- /solid/interface-segregration-principle/main.go: -------------------------------------------------------------------------------- 1 | package interfacesegregrationprinciple 2 | 3 | type Trabalho interface { 4 | Entrar() 5 | 6 | ComecarATrabalhar() 7 | 8 | ContinuarATrabalhar() 9 | 10 | Sair() 11 | } 12 | 13 | type HumanoTasks interface { 14 | Trabalho 15 | 16 | PausaProCafe() 17 | 18 | Almocar() 19 | } 20 | 21 | type RoboTasks interface { 22 | Trabalho 23 | 24 | VerificarOleo() 25 | 26 | CarregarBateria() 27 | } 28 | 29 | type Robo struct{} 30 | 31 | type Humano struct{} 32 | -------------------------------------------------------------------------------- /solid/liskov-substitution-principle/main.go: -------------------------------------------------------------------------------- 1 | package liskovsubstitutionprinciple 2 | 3 | type Area interface { 4 | GetArea() float64 5 | } 6 | 7 | type RetanguloType interface { 8 | Area 9 | 10 | GetWidth() float64 11 | GetHeight() float64 12 | 13 | SetWidth(width float64) 14 | SetHeight(height float64) 15 | } 16 | 17 | type QuadradoType interface { 18 | Area 19 | 20 | SetSize(size float64) 21 | GetSize() float64 22 | } 23 | 24 | func (r *Quadrado) GetArea() float64 { 25 | return r.size * r.size 26 | } 27 | 28 | func (r *Quadrado) SetSize(size float64) { 29 | r.size = size 30 | } 31 | 32 | func (r *Quadrado) GetSize() float64 { 33 | return r.size 34 | } 35 | 36 | type Quadrado struct { 37 | size float64 38 | } 39 | 40 | type Retangulo struct { 41 | width, height float64 42 | } 43 | 44 | func (r *Retangulo) GetArea() float64 { 45 | return r.width * r.height 46 | } 47 | 48 | func (r *Retangulo) GetWidth() float64 { 49 | return r.width 50 | } 51 | 52 | func (r *Retangulo) GetHeight() float64 { 53 | panic("not implemented") // TODO: Implement 54 | } 55 | 56 | func (r *Retangulo) SetWidth(width float64) { 57 | panic("not implemented") // TODO: Implement 58 | } 59 | 60 | func (r *Retangulo) SetHeight(height float64) { 61 | panic("not implemented") // TODO: Implement 62 | } 63 | -------------------------------------------------------------------------------- /solid/open-closed-principle/right_way.go: -------------------------------------------------------------------------------- 1 | package singleresponsibility 2 | 3 | type FuncPJ struct{} 4 | type FuncCLT struct{} 5 | type FuncEstagiario struct{} 6 | 7 | type Funcionario interface { 8 | CalcularSalario() float64 9 | } 10 | 11 | func main() { 12 | funcionario := &FuncPJ{} 13 | funcionario.CalcularSalario() 14 | 15 | stag := &FuncEstagiario{} 16 | stag.CalcularSalario() 17 | 18 | FolhaDePagamento(stag) 19 | } 20 | 21 | func (f *FuncPJ) CalcularSalario() float64 { 22 | //Calcular salario 23 | return 0.0 24 | } 25 | 26 | func (f *FuncCLT) CalcularSalario() float64 { 27 | //Calcular salario + beneficios 28 | return 0.0 29 | } 30 | 31 | func (f *FuncEstagiario) CalcularSalario() float64 { 32 | //Calcular bolsa auxilio 33 | return 0.0 34 | } 35 | 36 | func FolhaDePagamento(funcionario Funcionario) float64 { 37 | return funcionario.CalcularSalario() 38 | } 39 | -------------------------------------------------------------------------------- /solid/open-closed-principle/wrong_way.go: -------------------------------------------------------------------------------- 1 | package singleresponsibility 2 | 3 | import "reflect" 4 | 5 | type FuncionarioCLT struct{} 6 | type FuncionarioPJ struct{} 7 | type Estagiario struct{} 8 | 9 | func FolhaDePag[TipoFuncionario FuncionarioCLT | Estagiario | FuncionarioPJ](funcionario TipoFuncionario) float64 { 10 | 11 | if reflect.TypeOf(FuncionarioCLT{}) == reflect.TypeOf(funcionario) { 12 | 13 | //Calcular salario + beneficios 14 | return 0.0 15 | 16 | } else if reflect.TypeOf(FuncionarioPJ{}) == reflect.TypeOf(funcionario) { 17 | 18 | // Calcular salario do PJ 19 | return 0.0 20 | 21 | } else { 22 | 23 | //Calcular bolsa auxilio do estagiario 24 | return 0.0 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /solid/single-responsibility-principle/god_object.go: -------------------------------------------------------------------------------- 1 | package singleresponsibilityprinciple 2 | 3 | import ( 4 | "io/ioutil" 5 | "net/url" 6 | "strings" 7 | ) 8 | 9 | type Journal struct { 10 | News []string 11 | } 12 | 13 | func (j *Journal) String() string { 14 | return strings.Join(j.News, "\n") 15 | } 16 | 17 | func (j *Journal) AddNews(news string) { 18 | //... 19 | } 20 | 21 | func (j *Journal) RemoveNews(news string) { 22 | //... 23 | } 24 | 25 | func (j *Journal) UpdateNews(news string) { 26 | //... 27 | } 28 | 29 | func (j *Journal) DeleteNews(news string) { 30 | //... 31 | } 32 | 33 | func (j *Journal) PrintNews(filename string, news string) { 34 | _ = ioutil.WriteFile(filename, []byte(j.String()), 0644) 35 | } 36 | 37 | func (j *Journal) LoadNewsFromFile(filename string) { 38 | //... 39 | } 40 | 41 | func (j *Journal) LoadNewsFromWeb(website *url.URL) { 42 | //... 43 | } 44 | -------------------------------------------------------------------------------- /solid/single-responsibility-principle/journal.go: -------------------------------------------------------------------------------- 1 | package singleresponsibilityprinciple 2 | 3 | import "strings" 4 | 5 | type JournalClassic struct { 6 | News []string 7 | } 8 | 9 | func (j *JournalClassic) String() string { 10 | return strings.Join(j.News, "\n") 11 | } 12 | 13 | func (j *JournalClassic) AddNews(news string) { 14 | //... 15 | } 16 | 17 | func (j *JournalClassic) RemoveNews(news string) { 18 | //... 19 | } 20 | 21 | func (j *JournalClassic) UpdateNews(news string) { 22 | //... 23 | } 24 | 25 | func (j *JournalClassic) DeleteNews(news string) { 26 | //... 27 | } 28 | -------------------------------------------------------------------------------- /solid/single-responsibility-principle/load_news.go: -------------------------------------------------------------------------------- 1 | package singleresponsibilityprinciple 2 | 3 | import "net/url" 4 | 5 | func LoadNewsFromFile(filename string) { 6 | //... 7 | } 8 | 9 | func LoadNewsFromWeb(website *url.URL) { 10 | //... 11 | } 12 | -------------------------------------------------------------------------------- /solid/single-responsibility-principle/printer.go: -------------------------------------------------------------------------------- 1 | package singleresponsibilityprinciple 2 | 3 | import ( 4 | "io/ioutil" 5 | ) 6 | 7 | func PrintNews(filename string, journal JournalClassic) { 8 | _ = ioutil.WriteFile(filename, []byte(journal.String()), 0644) 9 | } 10 | --------------------------------------------------------------------------------