├── .gitignore ├── README.md ├── project ├── bank │ ├── config.yaml │ ├── errs │ │ └── errs.go │ ├── go.mod │ ├── go.sum │ ├── handler │ │ ├── account.go │ │ ├── customer.go │ │ └── handler.go │ ├── logs │ │ └── logs.go │ ├── main.go │ ├── mock │ │ ├── mock_repository │ │ │ ├── mock_account_repository.go │ │ │ └── mock_customer_repository.go │ │ └── mock_service │ │ │ ├── mock_account_service.go │ │ │ └── mock_customer_service.go │ ├── repository │ │ ├── account.go │ │ ├── account_db.go │ │ ├── customer.go │ │ ├── customer_db.go │ │ └── customer_mock.go │ └── service │ │ ├── account.go │ │ ├── account_service.go │ │ ├── customer.go │ │ ├── customer_service.go │ │ └── customer_test.go ├── gitobject │ └── main.go ├── gobreaker │ ├── client │ │ ├── docker-compose.yml │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go │ └── server │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go ├── gofiber │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── wwwroot │ │ └── index.html ├── gogrpc │ ├── client │ │ ├── go.mod │ │ ├── go.sum │ │ ├── main.go │ │ └── services │ │ │ ├── calculator.pb.go │ │ │ ├── calculator_grpc.pb.go │ │ │ ├── calculator_service.go │ │ │ └── gender.pb.go │ ├── gogrpc.code-workspace │ ├── proto │ │ ├── calculator.proto │ │ ├── gen.sh │ │ └── gender.proto │ ├── server │ │ ├── go.mod │ │ ├── go.sum │ │ ├── main.go │ │ └── services │ │ │ ├── calculator.pb.go │ │ │ ├── calculator_grpc.pb.go │ │ │ ├── calculator_server.go │ │ │ └── gender.pb.go │ └── tls │ │ ├── gen.sh │ │ └── ssl.cnf ├── gokafka │ ├── consumer │ │ ├── config.yaml │ │ ├── go.mod │ │ ├── go.sum │ │ ├── main.go │ │ ├── repositories │ │ │ └── account.go │ │ └── services │ │ │ ├── account.go │ │ │ └── consumer.go │ ├── events │ │ ├── event.go │ │ └── go.mod │ ├── gokafka.code-workspace │ ├── producer │ │ ├── commands │ │ │ └── command.go │ │ ├── config.yaml │ │ ├── controllers │ │ │ └── account.go │ │ ├── go.mod │ │ ├── go.sum │ │ ├── main.go │ │ └── services │ │ │ ├── account.go │ │ │ └── producer.go │ └── server │ │ └── docker-compose.yml ├── goredis │ ├── config │ │ └── redis.conf │ ├── docker-compose.yml │ ├── go.mod │ ├── go.sum │ ├── handlers │ │ ├── catalog.go │ │ ├── catalog.handler.go │ │ └── catalog_redis.go │ ├── main.go │ ├── repositories │ │ ├── product.go │ │ ├── product_db.go │ │ └── product_redis.go │ ├── scripts │ │ └── test.js │ └── services │ │ ├── catalog.go │ │ ├── catalog_redis.go │ │ └── catalog_service.go ├── gotest │ ├── go.mod │ ├── go.sum │ ├── handlers │ │ ├── promotion.go │ │ ├── promotion_integration_test.go │ │ └── promotion_test.go │ ├── main.go │ ├── repositories │ │ ├── promotion.go │ │ └── promotion_mock.go │ └── services │ │ ├── errs.go │ │ ├── grade.go │ │ ├── grade_test.go │ │ ├── promotion.go │ │ ├── promotion_mock.go │ │ └── promotion_test.go └── orm │ ├── go.mod │ ├── go.sum │ └── main.go └── resource ├── banking.sql ├── tasks.json └── tls ├── gen.sh └── ssl.cnf /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | .DS_Store 8 | data/ 9 | 10 | # Test binary, built with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Dependency directories (remove the comment below to include it) 17 | # vendor/ 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go Programming Language 2 | Go Programming Playlist https://youtube.com/playlist?list=PLyZTXfAT27ib7T9Eg3qhvDE5rgvjQk4OL 3 | 4 | ### Website 5 | * Golang https://go.dev 6 | * Package https://pkg.go.dev 7 | * Go standard library https://pkg.go.dev/std 8 | * Language Specification https://go.dev/ref/spec 9 | * Awesome Go https://github.com/avelino/awesome-go 10 | * Uber Style Guide https://github.com/uber-go/guide 11 | * Go modules cheat sheet https://encore.dev/guide/go.mod 12 | * VSCode Settings https://github.com/golang/vscode-go/blob/master/docs/settings.md 13 | * SQL database drivers https://github.com/golang/go/wiki/SQLDrivers 14 | * Redis https://redis.io 15 | * K6 https://k6.io 16 | * Influx https://influxdata.com 17 | * Grafana https://grafana.com 18 | * Learn Go with Tests https://quii.gitbook.io 19 | * Kafka https://kafka.apache.org 20 | * gRPC https://grpc.io 21 | * Protocol Buffers Release https://github.com/protocolbuffers/protobuf/releases 22 | * Protocol Buffers Doctument https://developers.google.com/protocol-buffers/docs/proto3 23 | * evans gRPC Client https://github.com/ktr0731/evans 24 | * Protocol Buffer Library https://github.com/protocolbuffers/protobuf/tree/main/src/google/protobuf 25 | 26 | ### Go on macOS 27 | ```sh 28 | curl -OL https://golang.org/dl/go1.17.darwin-amd64.tar.gz 29 | tar xfz go1.17.darwin-amd64.tar.gz 30 | sudo mv go /usr/local 31 | sudo ln /usr/local/go/bin/go /usr/local/bin/go 32 | ``` 33 | 34 | ### Go on Windows with Windows Package Manager 35 | * [Windows Terminal](https://www.microsoft.com/store/productId/9N0DX20HK701) 36 | * [Windows Package Manager Insiders Program](https://forms.microsoft.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR-NSOqDz219PqoOqk5qxQEZUMVVCT1IwVEpLSklZS0dDRFZEUjZUOU9ZWi4u) 37 | * [App Installer (winget)](https://www.microsoft.com/store/productId/9NBLGGH4NNS1) 38 | 39 | ### Visual Studio Code and Extension 40 | * VSCode https://code.visualstudio.com 41 | * Go https://marketplace.visualstudio.com/items?itemName=golang.Go 42 | * Error Lens https://marketplace.visualstudio.com/items?itemName=usernamehw.errorlens 43 | * Docker https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker 44 | * MySQL https://marketplace.visualstudio.com/items?itemName=formulahendry.vscode-mysql 45 | * K6 snippets https://marketplace.visualstudio.com/items?itemName=mJacobson.snippets-for-k6 46 | * vscode-proto3 https://marketplace.visualstudio.com/items?itemName=zxh404.vscode-proto3 47 | 48 | ### Go Package 49 | * database/sql https://pkg.go.dev/database/sql 50 | * jmoiron/sqlx https://pkg.go.dev/github.com/jmoiron/sqlx 51 | * denisenkom/go-mssqldb https://pkg.go.dev/github.com/denisenkom/go-mssqldb 52 | * go-sql-driver/mysql https://pkg.go.dev/github.com/go-sql-driver/mysql 53 | * gorilla/mux https://pkg.go.dev/github.com/gorilla/mux 54 | * go.uber.org/zap https://pkg.go.dev/go.uber.org/zap 55 | * spf13/viper https://pkg.go.dev/github.com/spf13/viper 56 | * gofiber/fiber/v2 https://pkg.go.dev/github.com/gofiber/fiber/v2 57 | * gofiber/jwt/v2 https://pkg.go.dev/github.com/gofiber/jwt/v2 58 | * gofiber/adaptor/v2 https://pkg.go.dev/github.com/gofiber/adaptor/v2 59 | * mock/gomock https://pkg.go.dev/github.com/golang/mock/gomock 60 | * net/http https://pkg.go.dev/net/http 61 | * net/http/httptest https://pkg.go.dev/net/http/httptest 62 | * crypto/bcrypt https://pkg.go.dev/golang.org/x/crypto/bcrypt 63 | * dgrijalva/jwt-go https://pkg.go.dev/github.com/dgrijalva/jwt-go 64 | * gorm.io/gorm https://pkg.go.dev/gorm.io/gorm 65 | * gorm.io/driver/mysql https://pkg.go.dev/gorm.io/driver/mysql 66 | * go-redis/redis/v8 https://pkg.go.dev/github.com/go-redis/redis/v8 67 | * afex/hystrix-go/hystrix https://pkg.go.dev/github.com/afex/hystrix-go/hystrix 68 | * stretchr/testify https://pkg.go.dev/github.com/stretchr/testify 69 | * godoc https://pkg.go.dev/golang.org/x/tools/cmd/godoc 70 | * Shopify/sarama https://pkg.go.dev/github.com/Shopify/sarama 71 | * google/uuid https://pkg.go.dev/github.com/google/uuid 72 | * grpc https://pkg.go.dev/google.golang.org/grpc 73 | * protobuf https://pkg.go.dev/google.golang.org/protobuf 74 | * protoc-gen-go https://pkg.go.dev/google.golang.org/protobuf/cmd/protoc-gen-go 75 | * protoc-gen-go-grpc https://pkg.go.dev/google.golang.org/grpc/cmd/protoc-gen-go-grpc 76 | 77 | #### Docker Image 78 | * redis https://hub.docker.com/_/redis 79 | * loadimpact/k6 https://hub.docker.com/r/loadimpact/k6 80 | * influxdb https://hub.docker.com/_/influxdb 81 | * mariadb https://hub.docker.com/_/mariadb 82 | * grafana/grafana https://hub.docker.com/r/grafana/grafana 83 | * mlabouardy/hystrix-dashboard https://hub.docker.com/r/mlabouardy/hystrix-dashboard 84 | * zookeeper https://hub.docker.com/_/zookeeper 85 | * kafka https://hub.docker.com/r/bitnami/kafka 86 | * vscode-proto3 https://marketplace.visualstudio.com/items?itemName=zxh404.vscode-proto3 87 | 88 | #### Redis Configuration 89 | ``` 90 | bind 0.0.0.0 91 | appendonly yes 92 | SAVE "" 93 | ``` 94 | 95 | #### Unit Test VS Code Configuration 96 | ```json 97 | "go.coverOnSave": true, 98 | "go.coverOnSingleTest": true, 99 | "go.coverageDecorator": { 100 | "type": "gutter", 101 | "coveredHighlightColor": "rgba(64,128,128,0.5)", 102 | "uncoveredHighlightColor": "rgba(128,64,64,0.25)", 103 | "coveredGutterStyle": "blockgreen", 104 | "uncoveredGutterStyle": "blockred" 105 | } 106 | ``` 107 | 108 | ### Go gRPC for macOS 109 | 1) Install Protobuf on macOS 110 | ``` 111 | brew install protobuf 112 | ``` 113 | 2) Install Evans gRPC client for macOS 114 | ``` 115 | brew tap ktr0731/evans 116 | brew install evans 117 | ``` 118 | 3) Install vscode-proto3 for VSCode https://marketplace.visualstudio.com/items?itemName=zxh404.vscode-proto3 119 | 120 | 4) Go get package in project 121 | ``` 122 | go get google.golang.org/protobuf/cmd/protoc-gen-go 123 | go get google.golang.org/grpc/cmd/protoc-gen-go-grpc 124 | ``` 125 | 5) Install gRPC tool in project 126 | ``` 127 | go install google.golang.org/protobuf/cmd/protoc-gen-go 128 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc 129 | ``` 130 | 131 | 132 | ### Follow me 133 | * **Page:** [https://fb.com/CodeBangkok​](https://fb.com/CodeBangkok​) 134 | * **Group:** [https://fb.com/groups/msdevth​](https://fb.com/groups/msdevth​) 135 | * **Blog:** [https://dev.to/codebangkok](https://dev.to/codebangkok) 136 | * **YouTube:** [https://youtube.com/CodeBangkok](https://youtube.com/CodeBangkok) -------------------------------------------------------------------------------- /project/bank/config.yaml: -------------------------------------------------------------------------------- 1 | app: 2 | port: 8000 3 | 4 | db: 5 | driver: "mysql" 6 | host: "13.76.163.73" 7 | port: 3306 8 | username: root 9 | password: P@ssw0rd 10 | database: banking -------------------------------------------------------------------------------- /project/bank/errs/errs.go: -------------------------------------------------------------------------------- 1 | package errs 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type AppError struct { 8 | Code int 9 | Message string 10 | } 11 | 12 | func (e AppError) Error() string { 13 | return e.Message 14 | } 15 | 16 | func NewNotFoundError(message string) error { 17 | return AppError{ 18 | Code: http.StatusNotFound, 19 | Message: message, 20 | } 21 | } 22 | 23 | func NewUnexpectedError() error { 24 | return AppError{ 25 | Code: http.StatusInternalServerError, 26 | Message: "unexpected error", 27 | } 28 | } 29 | 30 | func NewValidationError(message string) error { 31 | return AppError{ 32 | Code: http.StatusUnprocessableEntity, 33 | Message: message, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /project/bank/go.mod: -------------------------------------------------------------------------------- 1 | module bank 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/go-sql-driver/mysql v1.6.0 7 | github.com/golang/mock v1.6.0 // indirect 8 | github.com/gorilla/mux v1.8.0 9 | github.com/jmoiron/sqlx v1.3.4 10 | github.com/spf13/viper v1.7.1 11 | go.uber.org/atomic v1.8.0 // indirect 12 | go.uber.org/multierr v1.7.0 // indirect 13 | go.uber.org/zap v1.17.0 14 | ) 15 | -------------------------------------------------------------------------------- /project/bank/handler/account.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "bank/errs" 5 | "bank/service" 6 | "encoding/json" 7 | "net/http" 8 | "strconv" 9 | 10 | "github.com/gorilla/mux" 11 | ) 12 | 13 | type accountHandler struct { 14 | accSrv service.AccountService 15 | } 16 | 17 | func NewAccountHandler(accSrv service.AccountService) accountHandler { 18 | return accountHandler{accSrv: accSrv} 19 | } 20 | 21 | func (h accountHandler) NewAccount(w http.ResponseWriter, r *http.Request) { 22 | customerID, _ := strconv.Atoi(mux.Vars(r)["customerID"]) 23 | 24 | if r.Header.Get("content-type") != "application/json" { 25 | handleError(w, errs.NewValidationError("request body incorrect format")) 26 | return 27 | } 28 | 29 | request := service.NewAccountRequest{} 30 | err := json.NewDecoder(r.Body).Decode(&request) 31 | if err != nil { 32 | handleError(w, errs.NewValidationError("request body incorrect format")) 33 | return 34 | } 35 | 36 | response, err := h.accSrv.NewAccount(customerID, request) 37 | if err != nil { 38 | handleError(w, err) 39 | return 40 | } 41 | 42 | w.WriteHeader(http.StatusCreated) 43 | w.Header().Set("content-type", "applicaiton/json") 44 | json.NewEncoder(w).Encode(response) 45 | } 46 | 47 | func (h accountHandler) GetAccounts(w http.ResponseWriter, r *http.Request) { 48 | customerID, _ := strconv.Atoi(mux.Vars(r)["customerID"]) 49 | 50 | responses, err := h.accSrv.GetAccounts(customerID) 51 | if err != nil { 52 | handleError(w, err) 53 | return 54 | } 55 | 56 | w.Header().Set("content-type", "application/json") 57 | json.NewEncoder(w).Encode(responses) 58 | } 59 | -------------------------------------------------------------------------------- /project/bank/handler/customer.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "bank/service" 5 | "encoding/json" 6 | "net/http" 7 | "strconv" 8 | 9 | "github.com/gorilla/mux" 10 | ) 11 | 12 | type customerHandler struct { 13 | custSrv service.CustomerService 14 | } 15 | 16 | func NewCustomerHandler(custSrv service.CustomerService) customerHandler { 17 | return customerHandler{custSrv: custSrv} 18 | } 19 | 20 | func (h customerHandler) GetCustomers(w http.ResponseWriter, r *http.Request) { 21 | customers, err := h.custSrv.GetCustomers() 22 | if err != nil { 23 | handleError(w, err) 24 | return 25 | } 26 | 27 | w.Header().Set("content-type", "application/json") 28 | json.NewEncoder(w).Encode(customers) 29 | } 30 | 31 | func (h customerHandler) GetCustomer(w http.ResponseWriter, r *http.Request) { 32 | customerID, _ := strconv.Atoi(mux.Vars(r)["customerID"]) 33 | 34 | customer, err := h.custSrv.GetCustomer(customerID) 35 | if err != nil { 36 | handleError(w, err) 37 | return 38 | } 39 | 40 | w.Header().Set("content-type", "application/json") 41 | json.NewEncoder(w).Encode(customer) 42 | } 43 | -------------------------------------------------------------------------------- /project/bank/handler/handler.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "bank/errs" 5 | "fmt" 6 | "net/http" 7 | ) 8 | 9 | func handleError(w http.ResponseWriter, err error) { 10 | switch e := err.(type) { 11 | case errs.AppError: 12 | w.WriteHeader(e.Code) 13 | fmt.Fprintln(w, e) 14 | case error: 15 | w.WriteHeader(http.StatusInternalServerError) 16 | fmt.Fprintln(w, e) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /project/bank/logs/logs.go: -------------------------------------------------------------------------------- 1 | package logs 2 | 3 | import ( 4 | "go.uber.org/zap" 5 | "go.uber.org/zap/zapcore" 6 | ) 7 | 8 | var log *zap.Logger 9 | 10 | func init() { 11 | config := zap.NewProductionConfig() 12 | config.EncoderConfig.TimeKey = "timestamp" 13 | config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder 14 | config.EncoderConfig.StacktraceKey = "" 15 | 16 | var err error 17 | log, err = config.Build(zap.AddCallerSkip(1)) 18 | if err != nil { 19 | panic(err) 20 | } 21 | } 22 | 23 | func Info(message string, fields ...zap.Field) { 24 | log.Info(message, fields...) 25 | } 26 | 27 | func Debug(message string, fields ...zap.Field) { 28 | log.Debug(message, fields...) 29 | } 30 | 31 | func Error(message interface{}, fields ...zap.Field) { 32 | switch v := message.(type) { 33 | case error: 34 | log.Error(v.Error(), fields...) 35 | case string: 36 | log.Error(v, fields...) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /project/bank/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bank/handler" 5 | "bank/logs" 6 | "bank/repository" 7 | "bank/service" 8 | "fmt" 9 | "net/http" 10 | "strings" 11 | "time" 12 | 13 | _ "github.com/go-sql-driver/mysql" 14 | "github.com/gorilla/mux" 15 | "github.com/jmoiron/sqlx" 16 | "github.com/spf13/viper" 17 | ) 18 | 19 | func main() { 20 | initTimeZone() 21 | initConfig() 22 | db := initDatabase() 23 | 24 | customerRepositoryDB := repository.NewCustomerRepositoryDB(db) 25 | customerService := service.NewCustomerService(customerRepositoryDB) 26 | customerHandler := handler.NewCustomerHandler(customerService) 27 | 28 | accountRepositoryDB := repository.NewAccountRepositoryDB(db) 29 | accountService := service.NewAccountService(accountRepositoryDB) 30 | accountHandler := handler.NewAccountHandler(accountService) 31 | 32 | router := mux.NewRouter() 33 | 34 | router.HandleFunc("/customers", customerHandler.GetCustomers).Methods(http.MethodGet) 35 | router.HandleFunc("/customers/{customerID:[0-9]+}", customerHandler.GetCustomer).Methods(http.MethodGet) 36 | 37 | router.HandleFunc("/customers/{customerID:[0-9]+}/accounts", accountHandler.GetAccounts).Methods(http.MethodGet) 38 | router.HandleFunc("/customers/{customerID:[0-9]+}/accounts", accountHandler.NewAccount).Methods(http.MethodPost) 39 | 40 | logs.Info("Banking service started at port " + viper.GetString("app.port")) 41 | http.ListenAndServe(fmt.Sprintf(":%v", viper.GetInt("app.port")), router) 42 | } 43 | 44 | func initConfig() { 45 | viper.SetConfigName("config") 46 | viper.SetConfigType("yaml") 47 | viper.AddConfigPath(".") 48 | viper.AutomaticEnv() 49 | viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) 50 | 51 | err := viper.ReadInConfig() 52 | if err != nil { 53 | panic(err) 54 | } 55 | 56 | } 57 | 58 | func initTimeZone() { 59 | ict, err := time.LoadLocation("Asia/Bangkok") 60 | if err != nil { 61 | panic(err) 62 | } 63 | 64 | time.Local = ict 65 | } 66 | 67 | func initDatabase() *sqlx.DB { 68 | dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?parseTime=true", 69 | viper.GetString("db.username"), 70 | viper.GetString("db.password"), 71 | viper.GetString("db.host"), 72 | viper.GetInt("db.port"), 73 | viper.GetString("db.database"), 74 | ) 75 | 76 | db, err := sqlx.Open(viper.GetString("db.driver"), dsn) 77 | if err != nil { 78 | panic(err) 79 | } 80 | 81 | db.SetConnMaxLifetime(3 * time.Minute) 82 | db.SetMaxOpenConns(10) 83 | db.SetMaxIdleConns(10) 84 | 85 | return db 86 | } 87 | -------------------------------------------------------------------------------- /project/bank/mock/mock_repository/mock_account_repository.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: bank/repository (interfaces: AccountRepository) 3 | 4 | // Package mock_repository is a generated GoMock package. 5 | package mock_repository 6 | 7 | import ( 8 | repository "bank/repository" 9 | reflect "reflect" 10 | 11 | gomock "github.com/golang/mock/gomock" 12 | ) 13 | 14 | // MockAccountRepository is a mock of AccountRepository interface. 15 | type MockAccountRepository struct { 16 | ctrl *gomock.Controller 17 | recorder *MockAccountRepositoryMockRecorder 18 | } 19 | 20 | // MockAccountRepositoryMockRecorder is the mock recorder for MockAccountRepository. 21 | type MockAccountRepositoryMockRecorder struct { 22 | mock *MockAccountRepository 23 | } 24 | 25 | // NewMockAccountRepository creates a new mock instance. 26 | func NewMockAccountRepository(ctrl *gomock.Controller) *MockAccountRepository { 27 | mock := &MockAccountRepository{ctrl: ctrl} 28 | mock.recorder = &MockAccountRepositoryMockRecorder{mock} 29 | return mock 30 | } 31 | 32 | // EXPECT returns an object that allows the caller to indicate expected use. 33 | func (m *MockAccountRepository) EXPECT() *MockAccountRepositoryMockRecorder { 34 | return m.recorder 35 | } 36 | 37 | // Create mocks base method. 38 | func (m *MockAccountRepository) Create(arg0 repository.Account) (*repository.Account, error) { 39 | m.ctrl.T.Helper() 40 | ret := m.ctrl.Call(m, "Create", arg0) 41 | ret0, _ := ret[0].(*repository.Account) 42 | ret1, _ := ret[1].(error) 43 | return ret0, ret1 44 | } 45 | 46 | // Create indicates an expected call of Create. 47 | func (mr *MockAccountRepositoryMockRecorder) Create(arg0 interface{}) *gomock.Call { 48 | mr.mock.ctrl.T.Helper() 49 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockAccountRepository)(nil).Create), arg0) 50 | } 51 | 52 | // GetAll mocks base method. 53 | func (m *MockAccountRepository) GetAll(arg0 int) ([]repository.Account, error) { 54 | m.ctrl.T.Helper() 55 | ret := m.ctrl.Call(m, "GetAll", arg0) 56 | ret0, _ := ret[0].([]repository.Account) 57 | ret1, _ := ret[1].(error) 58 | return ret0, ret1 59 | } 60 | 61 | // GetAll indicates an expected call of GetAll. 62 | func (mr *MockAccountRepositoryMockRecorder) GetAll(arg0 interface{}) *gomock.Call { 63 | mr.mock.ctrl.T.Helper() 64 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockAccountRepository)(nil).GetAll), arg0) 65 | } 66 | -------------------------------------------------------------------------------- /project/bank/mock/mock_repository/mock_customer_repository.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: bank/repository (interfaces: CustomerRepository) 3 | 4 | // Package mock_repository is a generated GoMock package. 5 | package mock_repository 6 | 7 | import ( 8 | repository "bank/repository" 9 | reflect "reflect" 10 | 11 | gomock "github.com/golang/mock/gomock" 12 | ) 13 | 14 | // MockCustomerRepository is a mock of CustomerRepository interface. 15 | type MockCustomerRepository struct { 16 | ctrl *gomock.Controller 17 | recorder *MockCustomerRepositoryMockRecorder 18 | } 19 | 20 | // MockCustomerRepositoryMockRecorder is the mock recorder for MockCustomerRepository. 21 | type MockCustomerRepositoryMockRecorder struct { 22 | mock *MockCustomerRepository 23 | } 24 | 25 | // NewMockCustomerRepository creates a new mock instance. 26 | func NewMockCustomerRepository(ctrl *gomock.Controller) *MockCustomerRepository { 27 | mock := &MockCustomerRepository{ctrl: ctrl} 28 | mock.recorder = &MockCustomerRepositoryMockRecorder{mock} 29 | return mock 30 | } 31 | 32 | // EXPECT returns an object that allows the caller to indicate expected use. 33 | func (m *MockCustomerRepository) EXPECT() *MockCustomerRepositoryMockRecorder { 34 | return m.recorder 35 | } 36 | 37 | // GetAll mocks base method. 38 | func (m *MockCustomerRepository) GetAll() ([]repository.Customer, error) { 39 | m.ctrl.T.Helper() 40 | ret := m.ctrl.Call(m, "GetAll") 41 | ret0, _ := ret[0].([]repository.Customer) 42 | ret1, _ := ret[1].(error) 43 | return ret0, ret1 44 | } 45 | 46 | // GetAll indicates an expected call of GetAll. 47 | func (mr *MockCustomerRepositoryMockRecorder) GetAll() *gomock.Call { 48 | mr.mock.ctrl.T.Helper() 49 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockCustomerRepository)(nil).GetAll)) 50 | } 51 | 52 | // GetById mocks base method. 53 | func (m *MockCustomerRepository) GetById(arg0 int) (*repository.Customer, error) { 54 | m.ctrl.T.Helper() 55 | ret := m.ctrl.Call(m, "GetById", arg0) 56 | ret0, _ := ret[0].(*repository.Customer) 57 | ret1, _ := ret[1].(error) 58 | return ret0, ret1 59 | } 60 | 61 | // GetById indicates an expected call of GetById. 62 | func (mr *MockCustomerRepositoryMockRecorder) GetById(arg0 interface{}) *gomock.Call { 63 | mr.mock.ctrl.T.Helper() 64 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetById", reflect.TypeOf((*MockCustomerRepository)(nil).GetById), arg0) 65 | } 66 | -------------------------------------------------------------------------------- /project/bank/mock/mock_service/mock_account_service.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: bank/service (interfaces: AccountService) 3 | 4 | // Package mock_service is a generated GoMock package. 5 | package mock_service 6 | 7 | import ( 8 | service "bank/service" 9 | reflect "reflect" 10 | 11 | gomock "github.com/golang/mock/gomock" 12 | ) 13 | 14 | // MockAccountService is a mock of AccountService interface. 15 | type MockAccountService struct { 16 | ctrl *gomock.Controller 17 | recorder *MockAccountServiceMockRecorder 18 | } 19 | 20 | // MockAccountServiceMockRecorder is the mock recorder for MockAccountService. 21 | type MockAccountServiceMockRecorder struct { 22 | mock *MockAccountService 23 | } 24 | 25 | // NewMockAccountService creates a new mock instance. 26 | func NewMockAccountService(ctrl *gomock.Controller) *MockAccountService { 27 | mock := &MockAccountService{ctrl: ctrl} 28 | mock.recorder = &MockAccountServiceMockRecorder{mock} 29 | return mock 30 | } 31 | 32 | // EXPECT returns an object that allows the caller to indicate expected use. 33 | func (m *MockAccountService) EXPECT() *MockAccountServiceMockRecorder { 34 | return m.recorder 35 | } 36 | 37 | // GetAccounts mocks base method. 38 | func (m *MockAccountService) GetAccounts(arg0 int) ([]service.AccountResponse, error) { 39 | m.ctrl.T.Helper() 40 | ret := m.ctrl.Call(m, "GetAccounts", arg0) 41 | ret0, _ := ret[0].([]service.AccountResponse) 42 | ret1, _ := ret[1].(error) 43 | return ret0, ret1 44 | } 45 | 46 | // GetAccounts indicates an expected call of GetAccounts. 47 | func (mr *MockAccountServiceMockRecorder) GetAccounts(arg0 interface{}) *gomock.Call { 48 | mr.mock.ctrl.T.Helper() 49 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccounts", reflect.TypeOf((*MockAccountService)(nil).GetAccounts), arg0) 50 | } 51 | 52 | // NewAccount mocks base method. 53 | func (m *MockAccountService) NewAccount(arg0 int, arg1 service.NewAccountRequest) (*service.AccountResponse, error) { 54 | m.ctrl.T.Helper() 55 | ret := m.ctrl.Call(m, "NewAccount", arg0, arg1) 56 | ret0, _ := ret[0].(*service.AccountResponse) 57 | ret1, _ := ret[1].(error) 58 | return ret0, ret1 59 | } 60 | 61 | // NewAccount indicates an expected call of NewAccount. 62 | func (mr *MockAccountServiceMockRecorder) NewAccount(arg0, arg1 interface{}) *gomock.Call { 63 | mr.mock.ctrl.T.Helper() 64 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAccount", reflect.TypeOf((*MockAccountService)(nil).NewAccount), arg0, arg1) 65 | } 66 | -------------------------------------------------------------------------------- /project/bank/mock/mock_service/mock_customer_service.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: bank/service (interfaces: CustomerService) 3 | 4 | // Package mock_service is a generated GoMock package. 5 | package mock_service 6 | 7 | import ( 8 | service "bank/service" 9 | reflect "reflect" 10 | 11 | gomock "github.com/golang/mock/gomock" 12 | ) 13 | 14 | // MockCustomerService is a mock of CustomerService interface. 15 | type MockCustomerService struct { 16 | ctrl *gomock.Controller 17 | recorder *MockCustomerServiceMockRecorder 18 | } 19 | 20 | // MockCustomerServiceMockRecorder is the mock recorder for MockCustomerService. 21 | type MockCustomerServiceMockRecorder struct { 22 | mock *MockCustomerService 23 | } 24 | 25 | // NewMockCustomerService creates a new mock instance. 26 | func NewMockCustomerService(ctrl *gomock.Controller) *MockCustomerService { 27 | mock := &MockCustomerService{ctrl: ctrl} 28 | mock.recorder = &MockCustomerServiceMockRecorder{mock} 29 | return mock 30 | } 31 | 32 | // EXPECT returns an object that allows the caller to indicate expected use. 33 | func (m *MockCustomerService) EXPECT() *MockCustomerServiceMockRecorder { 34 | return m.recorder 35 | } 36 | 37 | // GetCustomer mocks base method. 38 | func (m *MockCustomerService) GetCustomer(arg0 int) (*service.CustomerResponse, error) { 39 | m.ctrl.T.Helper() 40 | ret := m.ctrl.Call(m, "GetCustomer", arg0) 41 | ret0, _ := ret[0].(*service.CustomerResponse) 42 | ret1, _ := ret[1].(error) 43 | return ret0, ret1 44 | } 45 | 46 | // GetCustomer indicates an expected call of GetCustomer. 47 | func (mr *MockCustomerServiceMockRecorder) GetCustomer(arg0 interface{}) *gomock.Call { 48 | mr.mock.ctrl.T.Helper() 49 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCustomer", reflect.TypeOf((*MockCustomerService)(nil).GetCustomer), arg0) 50 | } 51 | 52 | // GetCustomers mocks base method. 53 | func (m *MockCustomerService) GetCustomers() ([]service.CustomerResponse, error) { 54 | m.ctrl.T.Helper() 55 | ret := m.ctrl.Call(m, "GetCustomers") 56 | ret0, _ := ret[0].([]service.CustomerResponse) 57 | ret1, _ := ret[1].(error) 58 | return ret0, ret1 59 | } 60 | 61 | // GetCustomers indicates an expected call of GetCustomers. 62 | func (mr *MockCustomerServiceMockRecorder) GetCustomers() *gomock.Call { 63 | mr.mock.ctrl.T.Helper() 64 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCustomers", reflect.TypeOf((*MockCustomerService)(nil).GetCustomers)) 65 | } 66 | -------------------------------------------------------------------------------- /project/bank/repository/account.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | type Account struct { 4 | AccountID int `db:"account_id"` 5 | CustomerID int `db:"customer_id"` 6 | OpeningDate string `db:"opening_date"` 7 | AccountType string `db:"account_type"` 8 | Amount float64 `db:"amount"` 9 | Status int `db:"status"` 10 | } 11 | 12 | //go:generate mockgen -destination=../mock/mock_repository/mock_account_repository.go bank/repository AccountRepository 13 | type AccountRepository interface { 14 | Create(Account) (*Account, error) 15 | GetAll(int) ([]Account, error) 16 | } 17 | -------------------------------------------------------------------------------- /project/bank/repository/account_db.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import "github.com/jmoiron/sqlx" 4 | 5 | type accountRepositoryDB struct { 6 | db *sqlx.DB 7 | } 8 | 9 | func NewAccountRepositoryDB(db *sqlx.DB) AccountRepository { 10 | return accountRepositoryDB{db: db} 11 | } 12 | 13 | func (r accountRepositoryDB) Create(acc Account) (*Account, error) { 14 | query := "insert into accounts (customer_id, opening_date, account_type, amount, status) values (?, ?, ?, ?, ?)" 15 | result, err := r.db.Exec( 16 | query, 17 | acc.CustomerID, 18 | acc.OpeningDate, 19 | acc.AccountType, 20 | acc.Amount, 21 | acc.Status, 22 | ) 23 | 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | id, err := result.LastInsertId() 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | acc.AccountID = int(id) 34 | 35 | return &acc, nil 36 | } 37 | 38 | func (r accountRepositoryDB) GetAll(customerID int) ([]Account, error) { 39 | query := "select account_id, customer_id, opening_date, account_type, amount, status from accounts where customer_id=?" 40 | accounts := []Account{} 41 | err := r.db.Select(&accounts, query, customerID) 42 | if err != nil { 43 | return nil, err 44 | } 45 | return accounts, nil 46 | } 47 | -------------------------------------------------------------------------------- /project/bank/repository/customer.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | type Customer struct { 4 | CustomerID int `db:"customer_id"` 5 | Name string `db:"name"` 6 | DateOfBirth string `db:"date_of_birth"` 7 | City string `db:"city"` 8 | ZipCode string `db:"zipcode"` 9 | Status int `db:"status"` 10 | } 11 | 12 | //go:generate mockgen -destination=../mock/mock_repository/mock_customer_repository.go bank/repository CustomerRepository 13 | type CustomerRepository interface { 14 | GetAll() ([]Customer, error) 15 | GetById(int) (*Customer, error) 16 | } 17 | -------------------------------------------------------------------------------- /project/bank/repository/customer_db.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import "github.com/jmoiron/sqlx" 4 | 5 | type customerRepositoryDB struct { 6 | db *sqlx.DB 7 | } 8 | 9 | func NewCustomerRepositoryDB(db *sqlx.DB) CustomerRepository { 10 | return customerRepositoryDB{db: db} 11 | } 12 | 13 | func (r customerRepositoryDB) GetAll() ([]Customer, error) { 14 | customers := []Customer{} 15 | query := "select customer_id, name, date_of_birth, city, zipcode, status from customers" 16 | err := r.db.Select(&customers, query) 17 | if err != nil { 18 | return nil, err 19 | } 20 | return customers, nil 21 | } 22 | 23 | func (r customerRepositoryDB) GetById(id int) (*Customer, error) { 24 | customer := Customer{} 25 | query := "select customer_id, name, date_of_birth, city, zipcode, status from customers where customer_id=?" 26 | err := r.db.Get(&customer, query, id) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return &customer, nil 31 | } 32 | -------------------------------------------------------------------------------- /project/bank/repository/customer_mock.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import "errors" 4 | 5 | type customerRepositoryMock struct { 6 | customers []Customer 7 | } 8 | 9 | func NewCustomerRepositoryMock() CustomerRepository { 10 | customers := []Customer{ 11 | {CustomerID: 1001, Name: "Ashish", City: "New Delhi", ZipCode: "110011", DateOfBirth: "2000-01-01", Status: 1}, 12 | {CustomerID: 1002, Name: "Rob", City: "New Delhi", ZipCode: "110011", DateOfBirth: "2000-01-01", Status: 0}, 13 | } 14 | 15 | return customerRepositoryMock{customers: customers} 16 | } 17 | 18 | func (r customerRepositoryMock) GetAll() ([]Customer, error) { 19 | return r.customers, nil 20 | } 21 | 22 | func (r customerRepositoryMock) GetById(id int) (*Customer, error) { 23 | for _, customer := range r.customers { 24 | if customer.CustomerID == id { 25 | return &customer, nil 26 | } 27 | } 28 | 29 | return nil, errors.New("customer not found") 30 | } 31 | -------------------------------------------------------------------------------- /project/bank/service/account.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | type NewAccountRequest struct { 4 | AccountType string `json:"account_type"` 5 | Amount float64 `json:"amount"` 6 | } 7 | 8 | type AccountResponse struct { 9 | AccountID int `json:"account_id"` 10 | OpeningDate string `json:"opening_date"` 11 | AccountType string `json:"account_type"` 12 | Amount float64 `json:"amount"` 13 | Status int `json:"status"` 14 | } 15 | 16 | //go:generate mockgen -destination=../mock/mock_service/mock_account_service.go bank/service AccountService 17 | type AccountService interface { 18 | NewAccount(int, NewAccountRequest) (*AccountResponse, error) 19 | GetAccounts(int) ([]AccountResponse, error) 20 | } 21 | -------------------------------------------------------------------------------- /project/bank/service/account_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "bank/errs" 5 | "bank/logs" 6 | "bank/repository" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | type accountService struct { 12 | accRepo repository.AccountRepository 13 | } 14 | 15 | func NewAccountService(accRepo repository.AccountRepository) AccountService { 16 | return accountService{accRepo: accRepo} 17 | } 18 | 19 | func (s accountService) NewAccount(customerID int, request NewAccountRequest) (*AccountResponse, error) { 20 | //Validate 21 | if request.Amount < 5000 { 22 | return nil, errs.NewValidationError("amount at least 5,000") 23 | } 24 | if strings.ToLower(request.AccountType) != "saving" && strings.ToLower(request.AccountType) != "checking" { 25 | return nil, errs.NewValidationError("account type should be saving or checking") 26 | } 27 | 28 | account := repository.Account{ 29 | CustomerID: customerID, 30 | OpeningDate: time.Now().Format("2006-1-2 15:04:05"), 31 | AccountType: request.AccountType, 32 | Amount: request.Amount, 33 | Status: 1, 34 | } 35 | 36 | newAcc, err := s.accRepo.Create(account) 37 | if err != nil { 38 | logs.Error(err) 39 | return nil, errs.NewUnexpectedError() 40 | } 41 | 42 | response := AccountResponse{ 43 | AccountID: newAcc.AccountID, 44 | OpeningDate: newAcc.OpeningDate, 45 | AccountType: newAcc.AccountType, 46 | Amount: newAcc.Amount, 47 | Status: newAcc.Status, 48 | } 49 | 50 | return &response, nil 51 | } 52 | 53 | func (s accountService) GetAccounts(customerID int) ([]AccountResponse, error) { 54 | accounts, err := s.accRepo.GetAll(customerID) 55 | if err != nil { 56 | logs.Error(err) 57 | return nil, errs.NewUnexpectedError() 58 | } 59 | 60 | responses := []AccountResponse{} 61 | for _, account := range accounts { 62 | responses = append(responses, AccountResponse{ 63 | AccountID: account.AccountID, 64 | OpeningDate: account.OpeningDate, 65 | AccountType: account.AccountType, 66 | Amount: account.Amount, 67 | Status: account.Status, 68 | }) 69 | } 70 | return responses, nil 71 | } 72 | -------------------------------------------------------------------------------- /project/bank/service/customer.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | type CustomerResponse struct { 4 | CustomerID int `json:"customer_id"` 5 | Name string `json:"name"` 6 | Status int `json:"status"` 7 | } 8 | 9 | //go:generate mockgen -destination=../mock/mock_service/mock_customer_service.go bank/service CustomerService 10 | type CustomerService interface { 11 | GetCustomers() ([]CustomerResponse, error) 12 | GetCustomer(int) (*CustomerResponse, error) 13 | } 14 | -------------------------------------------------------------------------------- /project/bank/service/customer_service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "bank/errs" 5 | "bank/logs" 6 | "bank/repository" 7 | "database/sql" 8 | ) 9 | 10 | type customerService struct { 11 | custRepo repository.CustomerRepository 12 | } 13 | 14 | func NewCustomerService(custRepo repository.CustomerRepository) CustomerService { 15 | return customerService{custRepo: custRepo} 16 | } 17 | 18 | func (s customerService) GetCustomers() ([]CustomerResponse, error) { 19 | 20 | customers, err := s.custRepo.GetAll() 21 | if err != nil { 22 | logs.Error(err) 23 | return nil, errs.NewUnexpectedError() 24 | } 25 | 26 | custResponses := []CustomerResponse{} 27 | for _, customer := range customers { 28 | custResponse := CustomerResponse{ 29 | CustomerID: customer.CustomerID, 30 | Name: customer.Name, 31 | Status: customer.Status, 32 | } 33 | custResponses = append(custResponses, custResponse) 34 | } 35 | 36 | return custResponses, nil 37 | } 38 | 39 | func (s customerService) GetCustomer(id int) (*CustomerResponse, error) { 40 | customer, err := s.custRepo.GetById(id) 41 | if err != nil { 42 | 43 | if err == sql.ErrNoRows { 44 | return nil, errs.NewNotFoundError("customer not found") 45 | } 46 | 47 | logs.Error(err) 48 | return nil, errs.NewUnexpectedError() 49 | } 50 | 51 | custResponse := CustomerResponse{ 52 | CustomerID: customer.CustomerID, 53 | Name: customer.Name, 54 | Status: customer.Status, 55 | } 56 | 57 | return &custResponse, nil 58 | } 59 | -------------------------------------------------------------------------------- /project/bank/service/customer_test.go: -------------------------------------------------------------------------------- 1 | package service_test 2 | 3 | import ( 4 | "bank/errs" 5 | "bank/mock/mock_repository" 6 | "bank/service" 7 | "database/sql" 8 | "net/http" 9 | "testing" 10 | 11 | "github.com/golang/mock/gomock" 12 | ) 13 | 14 | func TestGetCustomerNotFound(t *testing.T) { 15 | //Arrage 16 | ctrl := gomock.NewController(t) 17 | defer ctrl.Finish() 18 | 19 | mockRepo := mock_repository.NewMockCustomerRepository(ctrl) 20 | 21 | customerID := 1 22 | 23 | mockRepo.EXPECT().GetById(customerID).Return(nil, sql.ErrNoRows) 24 | customerService := service.NewCustomerService(mockRepo) 25 | 26 | //Act 27 | _, err := customerService.GetCustomer(customerID) 28 | 29 | //Assert 30 | if err == nil { 31 | t.Error("should be error") 32 | return 33 | } 34 | 35 | appErr, ok := err.(errs.AppError) 36 | if !ok { 37 | t.Error("should return AppError") 38 | return 39 | } 40 | 41 | if appErr.Code != http.StatusNotFound { 42 | t.Error("invalid error code") 43 | } 44 | 45 | if appErr.Message != "customer not found" { 46 | t.Error("invalid error message") 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /project/gitobject/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "compress/zlib" 5 | "io" 6 | "log" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | f, err := os.Open("blob") 12 | if err != nil { 13 | log.Fatal(err) 14 | } 15 | r, err := zlib.NewReader(f) 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | io.Copy(os.Stdout, r) 20 | r.Close() 21 | } 22 | -------------------------------------------------------------------------------- /project/gobreaker/client/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | services: 3 | hystrix: 4 | image: mlabouardy/hystrix-dashboard 5 | container_name: hystrix 6 | ports: 7 | - 9002:9002 -------------------------------------------------------------------------------- /project/gobreaker/client/go.mod: -------------------------------------------------------------------------------- 1 | module client 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 // indirect 7 | github.com/andybalholm/brotli v1.0.2 // indirect 8 | github.com/gofiber/fiber/v2 v2.21.0 // indirect 9 | github.com/klauspost/compress v1.13.4 // indirect 10 | github.com/valyala/bytebufferpool v1.0.0 // indirect 11 | github.com/valyala/fasthttp v1.31.0 // indirect 12 | github.com/valyala/tcplisten v1.0.0 // indirect 13 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /project/gobreaker/client/go.sum: -------------------------------------------------------------------------------- 1 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw= 2 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= 3 | github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E= 4 | github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 5 | github.com/gofiber/fiber/v2 v2.21.0 h1:tdRNrgqWqcHWBwE3o51oAleEVsil4Ro02zd2vMEuP4Q= 6 | github.com/gofiber/fiber/v2 v2.21.0/go.mod h1:MR1usVH3JHYRyQwMe2eZXRSZHRX38fkV+A7CPB+DlDQ= 7 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 8 | github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= 9 | github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 10 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 11 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 12 | github.com/valyala/fasthttp v1.31.0 h1:lrauRLII19afgCs2fnWRJ4M5IkV0lo2FqA61uGkNBfE= 13 | github.com/valyala/fasthttp v1.31.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= 14 | github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= 15 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 16 | golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 17 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 18 | golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 19 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 20 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 21 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= 22 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 23 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 24 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 25 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 26 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 27 | -------------------------------------------------------------------------------- /project/gobreaker/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "net/http" 7 | 8 | "github.com/afex/hystrix-go/hystrix" 9 | "github.com/gofiber/fiber/v2" 10 | ) 11 | 12 | func main() { 13 | 14 | app := fiber.New() 15 | 16 | app.Get("/api", api) 17 | app.Get("/api2", api2) 18 | 19 | app.Listen(":8001") 20 | } 21 | 22 | func init() { 23 | 24 | hystrix.ConfigureCommand("api", hystrix.CommandConfig{ 25 | Timeout: 500, 26 | RequestVolumeThreshold: 4, 27 | ErrorPercentThreshold: 50, 28 | SleepWindow: 15000, 29 | }) 30 | 31 | hystrix.ConfigureCommand("api2", hystrix.CommandConfig{ 32 | Timeout: 500, 33 | RequestVolumeThreshold: 4, 34 | ErrorPercentThreshold: 50, 35 | SleepWindow: 15000, 36 | }) 37 | 38 | hystrixStreamHandler := hystrix.NewStreamHandler() 39 | hystrixStreamHandler.Start() 40 | go http.ListenAndServe(":8002", hystrixStreamHandler) 41 | 42 | } 43 | 44 | func api(c *fiber.Ctx) error { 45 | 46 | output := make(chan string, 1) 47 | hystrix.Go("api", func() error { 48 | 49 | res, err := http.Get("http://localhost:8000/api") 50 | if err != nil { 51 | return err 52 | } 53 | defer res.Body.Close() 54 | 55 | data, err := io.ReadAll(res.Body) 56 | if err != nil { 57 | return err 58 | } 59 | 60 | msg := string(data) 61 | fmt.Println(msg) 62 | 63 | output <- msg 64 | 65 | return nil 66 | }, func(err error) error { 67 | fmt.Println(err) 68 | 69 | return err 70 | }) 71 | 72 | out := <-output 73 | 74 | return c.SendString(out) 75 | } 76 | 77 | func api2(c *fiber.Ctx) error { 78 | 79 | output := make(chan string, 1) 80 | hystrix.Go("api2", func() error { 81 | 82 | res, err := http.Get("http://localhost:8000/api") 83 | if err != nil { 84 | return err 85 | } 86 | defer res.Body.Close() 87 | 88 | data, err := io.ReadAll(res.Body) 89 | if err != nil { 90 | return err 91 | } 92 | 93 | msg := string(data) 94 | fmt.Println(msg) 95 | 96 | output <- msg 97 | 98 | return nil 99 | }, func(err error) error { 100 | fmt.Println(err) 101 | 102 | return nil 103 | }) 104 | 105 | out := <-output 106 | 107 | return c.SendString(out) 108 | } 109 | -------------------------------------------------------------------------------- /project/gobreaker/server/go.mod: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | go 1.17 4 | 5 | require github.com/gofiber/fiber/v2 v2.21.0 6 | 7 | require ( 8 | github.com/andybalholm/brotli v1.0.2 // indirect 9 | github.com/klauspost/compress v1.13.4 // indirect 10 | github.com/valyala/bytebufferpool v1.0.0 // indirect 11 | github.com/valyala/fasthttp v1.31.0 // indirect 12 | github.com/valyala/tcplisten v1.0.0 // indirect 13 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /project/gobreaker/server/go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E= 2 | github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 3 | github.com/gofiber/fiber/v2 v2.21.0 h1:tdRNrgqWqcHWBwE3o51oAleEVsil4Ro02zd2vMEuP4Q= 4 | github.com/gofiber/fiber/v2 v2.21.0/go.mod h1:MR1usVH3JHYRyQwMe2eZXRSZHRX38fkV+A7CPB+DlDQ= 5 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 6 | github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= 7 | github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 8 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 9 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 10 | github.com/valyala/fasthttp v1.31.0 h1:lrauRLII19afgCs2fnWRJ4M5IkV0lo2FqA61uGkNBfE= 11 | github.com/valyala/fasthttp v1.31.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= 12 | github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= 13 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 14 | golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 15 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 16 | golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 17 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 18 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 19 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= 20 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 21 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 22 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 23 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 24 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 25 | -------------------------------------------------------------------------------- /project/gobreaker/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/gofiber/fiber/v2" 8 | ) 9 | 10 | func main() { 11 | app := fiber.New() 12 | 13 | counter := 0 14 | 15 | app.Get("/api", func(c *fiber.Ctx) error { 16 | counter++ 17 | 18 | if counter >= 5 && counter <= 10 { 19 | time.Sleep(time.Millisecond * 1000) 20 | } 21 | 22 | msg := fmt.Sprintf("Hello %v", counter) 23 | fmt.Println(msg) 24 | 25 | return c.SendString(msg) 26 | }) 27 | 28 | app.Listen(":8000") 29 | } 30 | -------------------------------------------------------------------------------- /project/gofiber/go.mod: -------------------------------------------------------------------------------- 1 | module gofiber 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect 7 | github.com/go-sql-driver/mysql v1.6.0 8 | github.com/gofiber/fiber/v2 v2.13.0 9 | github.com/gofiber/jwt/v2 v2.2.3 // indirect 10 | github.com/gorilla/mux v1.8.0 // indirect 11 | github.com/jmoiron/sqlx v1.3.4 12 | golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e 13 | ) 14 | -------------------------------------------------------------------------------- /project/gofiber/go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E= 2 | github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 3 | github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= 4 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 5 | github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= 6 | github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= 7 | github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 8 | github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= 9 | github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 10 | github.com/gofiber/fiber/v2 v2.13.0 h1:jJBCPwq+hlsfHRDVsmfu6pbgW85Y8jL9dE+VmTzfE6I= 11 | github.com/gofiber/fiber/v2 v2.13.0/go.mod h1:oZTLWqYnqpMMuF922SjGbsYZsdpE1MCfh416HNdweIM= 12 | github.com/gofiber/jwt/v2 v2.2.3 h1:8KciFlwiqjohPCHrwseq1b7oqDWGXsV12l67gi8kMBk= 13 | github.com/gofiber/jwt/v2 v2.2.3/go.mod h1:s9m7LZucTciuzNGNWhn8EFRmfc/1iIyakb29wQUxsFs= 14 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 15 | github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= 16 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 17 | github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= 18 | github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= 19 | github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8= 20 | github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 21 | github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 22 | github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= 23 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 24 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 25 | github.com/valyala/fasthttp v1.26.0 h1:k5Tooi31zPG/g8yS6o2RffRO2C9B9Kah9SY8j/S7058= 26 | github.com/valyala/fasthttp v1.26.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA= 27 | github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= 28 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 29 | golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 30 | golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= 31 | golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 32 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 33 | golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 34 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 35 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 36 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= 37 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 38 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= 39 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 40 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 41 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 42 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 43 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 44 | -------------------------------------------------------------------------------- /project/gofiber/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "time" 7 | 8 | "github.com/dgrijalva/jwt-go" 9 | "github.com/gofiber/fiber/v2" 10 | "github.com/gofiber/fiber/v2/middleware/cors" 11 | "github.com/gofiber/fiber/v2/middleware/requestid" 12 | "github.com/jmoiron/sqlx" 13 | "golang.org/x/crypto/bcrypt" 14 | 15 | _ "github.com/go-sql-driver/mysql" 16 | 17 | jwtware "github.com/gofiber/jwt/v2" 18 | ) 19 | 20 | var db *sqlx.DB 21 | 22 | const jwtSecret = "infinitas" 23 | 24 | func main() { 25 | 26 | var err error 27 | db, err = sqlx.Open("mysql", "root:P@ssw0rd@tcp(13.76.163.73:3306)/techcoach") 28 | if err != nil { 29 | panic(err) 30 | } 31 | 32 | app := fiber.New() 33 | 34 | app.Use("/hello", jwtware.New(jwtware.Config{ 35 | SigningMethod: "HS256", 36 | SigningKey: []byte(jwtSecret), 37 | SuccessHandler: func(c *fiber.Ctx) error { 38 | return c.Next() 39 | }, 40 | ErrorHandler: func(c *fiber.Ctx, e error) error { 41 | return fiber.ErrUnauthorized 42 | }, 43 | })) 44 | 45 | app.Post("/signup", Signup) 46 | app.Post("/login", Login) 47 | app.Get("/hello", Hello) 48 | 49 | app.Listen(":8000") 50 | } 51 | 52 | func Signup(c *fiber.Ctx) error { 53 | 54 | request := SignupRequest{} 55 | err := c.BodyParser(&request) 56 | if err != nil { 57 | return err 58 | } 59 | 60 | if request.Username == "" || request.Password == "" { 61 | return fiber.ErrUnprocessableEntity 62 | } 63 | 64 | password, err := bcrypt.GenerateFromPassword([]byte(request.Password), 10) 65 | if err != nil { 66 | return fiber.NewError(fiber.StatusUnprocessableEntity, err.Error()) 67 | } 68 | 69 | query := "insert user (username, password) values (?, ?)" 70 | result, err := db.Exec(query, request.Username, string(password)) 71 | if err != nil { 72 | return fiber.NewError(fiber.StatusUnprocessableEntity, err.Error()) 73 | } 74 | 75 | id, err := result.LastInsertId() 76 | if err != nil { 77 | return fiber.NewError(fiber.StatusUnprocessableEntity, err.Error()) 78 | } 79 | 80 | user := User{ 81 | Id: int(id), 82 | Username: request.Username, 83 | Password: string(password), 84 | } 85 | 86 | return c.Status(fiber.StatusCreated).JSON(user) 87 | } 88 | 89 | func Login(c *fiber.Ctx) error { 90 | 91 | request := LoginRequest{} 92 | err := c.BodyParser(&request) 93 | if err != nil { 94 | return err 95 | } 96 | 97 | if request.Username == "" || request.Password == "" { 98 | return fiber.ErrUnprocessableEntity 99 | } 100 | 101 | user := User{} 102 | query := "select id, username, password from user where username=?" 103 | err = db.Get(&user, query, request.Username) 104 | if err != nil { 105 | return fiber.NewError(fiber.StatusNotFound, "Incorrect username or password") 106 | } 107 | 108 | err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(request.Password)) 109 | if err != nil { 110 | return fiber.NewError(fiber.StatusNotFound, "Incorrect username or password") 111 | } 112 | 113 | cliams := jwt.StandardClaims{ 114 | Issuer: strconv.Itoa(user.Id), 115 | ExpiresAt: time.Now().Add(time.Hour * 24).Unix(), 116 | } 117 | 118 | jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, cliams) 119 | token, err := jwtToken.SignedString([]byte(jwtSecret)) 120 | if err != nil { 121 | return fiber.ErrInternalServerError 122 | } 123 | 124 | return c.JSON(fiber.Map{ 125 | "jwtToken": token, 126 | }) 127 | } 128 | 129 | func Hello(c *fiber.Ctx) error { 130 | return c.SendString("Hello World") 131 | } 132 | 133 | type User struct { 134 | Id int `db:"id" json:"id"` 135 | Username string `db:"username" json:"username"` 136 | Password string `db:"password" json:"password"` 137 | } 138 | 139 | type SignupRequest struct { 140 | Username string `json:"username"` 141 | Password string `json:"password"` 142 | } 143 | 144 | type LoginRequest struct { 145 | Username string `json:"username"` 146 | Password string `json:"password"` 147 | } 148 | 149 | func Fiber() { 150 | app := fiber.New(fiber.Config{ 151 | Prefork: false, 152 | }) 153 | 154 | //Middleware 155 | app.Use("/hello", func(c *fiber.Ctx) error { 156 | c.Locals("name", "bond") 157 | fmt.Println("before") 158 | err := c.Next() 159 | fmt.Println("after") 160 | return err 161 | }) 162 | 163 | app.Use(requestid.New()) 164 | 165 | app.Use(cors.New(cors.Config{ 166 | AllowOrigins: "*", 167 | AllowMethods: "*", 168 | AllowHeaders: "*", 169 | })) 170 | 171 | // app.Use(logger.New(logger.Config{ 172 | // TimeZone: "Asia/Bangkok", 173 | // })) 174 | 175 | //GET 176 | app.Get("/hello", func(c *fiber.Ctx) error { 177 | name := c.Locals("name") 178 | fmt.Printf("IsChild: %v\n", fiber.IsChild()) 179 | return c.SendString(fmt.Sprintf("GET: Hello %v", name)) 180 | }) 181 | 182 | //POST 183 | app.Post("/hello", func(c *fiber.Ctx) error { 184 | return c.SendString("POST: Hello World") 185 | }) 186 | 187 | //Parameters Optional 188 | app.Get("/hello/:name/:surname", func(c *fiber.Ctx) error { 189 | name := c.Params("name") 190 | surname := c.Params("surname") 191 | return c.SendString("name: " + name + ", surname: " + surname) 192 | }) 193 | 194 | //ParamsInt 195 | app.Get("/hello/:id", func(c *fiber.Ctx) error { 196 | id, err := c.ParamsInt("id") 197 | if err != nil { 198 | return fiber.ErrBadRequest 199 | } 200 | return c.SendString(fmt.Sprintf("ID = %v", id)) 201 | }) 202 | 203 | //Query 204 | app.Get("/query", func(c *fiber.Ctx) error { 205 | name := c.Query("name") 206 | surname := c.Query("surname") 207 | return c.SendString("name: " + name + " surname: " + surname) 208 | }) 209 | 210 | //Query 211 | app.Get("/query2", func(c *fiber.Ctx) error { 212 | person := Person{} 213 | c.QueryParser(&person) 214 | return c.JSON(person) 215 | }) 216 | 217 | //Wildcards 218 | app.Get("/wildcards/*", func(c *fiber.Ctx) error { 219 | wildcard := c.Params("*") 220 | return c.SendString(wildcard) 221 | }) 222 | 223 | //Static file 224 | app.Static("/", "./wwwroot", fiber.Static{ 225 | Index: "index.html", 226 | CacheDuration: time.Second * 10, 227 | }) 228 | 229 | //NewError 230 | app.Get("/error", func(c *fiber.Ctx) error { 231 | fmt.Println("error") 232 | return fiber.NewError(fiber.StatusNotFound, "content not found") 233 | }) 234 | 235 | //Group 236 | v1 := app.Group("/v1", func(c *fiber.Ctx) error { 237 | c.Set("Version", "v1") 238 | return c.Next() 239 | }) 240 | v1.Get("/hello", func(c *fiber.Ctx) error { 241 | return c.SendString("Hello v1") 242 | }) 243 | 244 | v2 := app.Group("/v2", func(c *fiber.Ctx) error { 245 | c.Set("Version", "v2") 246 | 247 | return c.Next() 248 | }) 249 | v2.Get("/hello", func(c *fiber.Ctx) error { 250 | return c.SendString("Hello v2") 251 | }) 252 | 253 | //Mount 254 | userApp := fiber.New() 255 | userApp.Get("/login", func(c *fiber.Ctx) error { 256 | return c.SendString("Login") 257 | }) 258 | 259 | app.Mount("/user", userApp) 260 | 261 | //Server 262 | app.Server().MaxConnsPerIP = 1 263 | app.Get("/server", func(c *fiber.Ctx) error { 264 | time.Sleep(time.Second * 30) 265 | return c.SendString("server") 266 | }) 267 | 268 | //Environment 269 | app.Get("/env", func(c *fiber.Ctx) error { 270 | return c.JSON(fiber.Map{ 271 | "BaseURL": c.BaseURL(), 272 | "Hostname": c.Hostname(), 273 | "IP": c.IP(), 274 | "IPs": c.IPs(), 275 | "OriginalURL": c.OriginalURL(), 276 | "Path": c.Path(), 277 | "Protocol": c.Protocol(), 278 | "Subdomains": c.Subdomains(), 279 | }) 280 | }) 281 | 282 | //Body 283 | app.Post("/body", func(c *fiber.Ctx) error { 284 | fmt.Printf("IsJson: %v\n", c.Is("json")) 285 | // fmt.Println(string(c.Body())) 286 | 287 | person := Person{} 288 | err := c.BodyParser(&person) 289 | if err != nil { 290 | return err 291 | } 292 | 293 | fmt.Println(person) 294 | return nil 295 | }) 296 | 297 | //Body 298 | app.Post("/body2", func(c *fiber.Ctx) error { 299 | fmt.Printf("IsJson: %v\n", c.Is("json")) 300 | // fmt.Println(string(c.Body())) 301 | 302 | data := map[string]interface{}{} 303 | err := c.BodyParser(&data) 304 | if err != nil { 305 | return err 306 | } 307 | 308 | fmt.Println(data) 309 | return nil 310 | }) 311 | 312 | app.Listen(":8000") 313 | } 314 | 315 | type Person struct { 316 | Id int `json:"id"` 317 | Name string `json:"name"` 318 | } 319 | -------------------------------------------------------------------------------- /project/gofiber/wwwroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | Hello HTML 11 | 12 | -------------------------------------------------------------------------------- /project/gogrpc/client/go.mod: -------------------------------------------------------------------------------- 1 | module client 2 | 3 | go 1.18 4 | 5 | require ( 6 | google.golang.org/grpc v1.45.0 7 | google.golang.org/protobuf v1.26.0 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.2 // indirect 12 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 13 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 14 | golang.org/x/text v0.3.0 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /project/gogrpc/client/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 5 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 6 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 7 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 8 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 9 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 10 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 11 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 12 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 13 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 14 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 15 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 16 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 17 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 18 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 19 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 20 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 21 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 22 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 23 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 24 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 25 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 26 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 27 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 28 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 29 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 30 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 31 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 32 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 33 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 34 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 35 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 36 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 37 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 38 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 39 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 40 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 41 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 42 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 43 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 44 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 45 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 46 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 47 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 48 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 49 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 50 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 51 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 52 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 53 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 54 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 55 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 56 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 57 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 58 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 59 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 60 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 61 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 62 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 63 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 64 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 65 | golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= 66 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 67 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 68 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 69 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 70 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 71 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 72 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 73 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 74 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 75 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 76 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= 77 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 78 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 79 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 80 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 81 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 82 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 83 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 84 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 85 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 86 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 87 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 88 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 89 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 90 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 91 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= 92 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 93 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 94 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 95 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 96 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 97 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 98 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 99 | google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= 100 | google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= 101 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 102 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 103 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 104 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 105 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 106 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 107 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 108 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 109 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 110 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 111 | google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= 112 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 113 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 114 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 115 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 116 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 117 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 118 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 119 | -------------------------------------------------------------------------------- /project/gogrpc/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "client/services" 5 | "flag" 6 | "log" 7 | 8 | "google.golang.org/grpc" 9 | "google.golang.org/grpc/credentials" 10 | "google.golang.org/grpc/credentials/insecure" 11 | "google.golang.org/grpc/status" 12 | ) 13 | 14 | func main() { 15 | 16 | var cc *grpc.ClientConn 17 | var err error 18 | var creds credentials.TransportCredentials 19 | 20 | host := flag.String("host", "localhost:50051", "gRPC server host") 21 | tls := flag.Bool("tls", false, "use a secure TLS connection") 22 | flag.Parse() 23 | 24 | if *tls { 25 | certFile := "../tls/ca.crt" 26 | creds, err = credentials.NewClientTLSFromFile(certFile, "") 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | } else { 31 | creds = insecure.NewCredentials() 32 | } 33 | 34 | cc, err = grpc.Dial(*host, grpc.WithTransportCredentials(creds)) 35 | if err != nil { 36 | log.Fatal(err) 37 | } 38 | defer cc.Close() 39 | 40 | calculatorClient := services.NewCalculatorClient(cc) 41 | calculatorService := services.NewCalculatorService(calculatorClient) 42 | 43 | err = calculatorService.Hello("Bond") 44 | // err = calculatorService.Fibonacci(6) 45 | // err = calculatorService.Average(1, 2, 3, 4, 5) 46 | // err = calculatorService.Sum(1, 2, 3, 4, 5) 47 | 48 | if err != nil { 49 | if grpcErr, ok := status.FromError(err); ok { 50 | log.Printf("[%v] %v", grpcErr.Code(), grpcErr.Message()) 51 | } else { 52 | log.Fatal(err) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /project/gogrpc/client/services/calculator_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.19.4 5 | // source: calculator.proto 6 | 7 | package services 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // CalculatorClient is the client API for Calculator service. 22 | // 23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 24 | type CalculatorClient interface { 25 | Hello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) 26 | Fibonacci(ctx context.Context, in *FibonacciRequest, opts ...grpc.CallOption) (Calculator_FibonacciClient, error) 27 | Average(ctx context.Context, opts ...grpc.CallOption) (Calculator_AverageClient, error) 28 | Sum(ctx context.Context, opts ...grpc.CallOption) (Calculator_SumClient, error) 29 | } 30 | 31 | type calculatorClient struct { 32 | cc grpc.ClientConnInterface 33 | } 34 | 35 | func NewCalculatorClient(cc grpc.ClientConnInterface) CalculatorClient { 36 | return &calculatorClient{cc} 37 | } 38 | 39 | func (c *calculatorClient) Hello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) { 40 | out := new(HelloResponse) 41 | err := c.cc.Invoke(ctx, "/services.Calculator/Hello", in, out, opts...) 42 | if err != nil { 43 | return nil, err 44 | } 45 | return out, nil 46 | } 47 | 48 | func (c *calculatorClient) Fibonacci(ctx context.Context, in *FibonacciRequest, opts ...grpc.CallOption) (Calculator_FibonacciClient, error) { 49 | stream, err := c.cc.NewStream(ctx, &Calculator_ServiceDesc.Streams[0], "/services.Calculator/Fibonacci", opts...) 50 | if err != nil { 51 | return nil, err 52 | } 53 | x := &calculatorFibonacciClient{stream} 54 | if err := x.ClientStream.SendMsg(in); err != nil { 55 | return nil, err 56 | } 57 | if err := x.ClientStream.CloseSend(); err != nil { 58 | return nil, err 59 | } 60 | return x, nil 61 | } 62 | 63 | type Calculator_FibonacciClient interface { 64 | Recv() (*FibonacciResponse, error) 65 | grpc.ClientStream 66 | } 67 | 68 | type calculatorFibonacciClient struct { 69 | grpc.ClientStream 70 | } 71 | 72 | func (x *calculatorFibonacciClient) Recv() (*FibonacciResponse, error) { 73 | m := new(FibonacciResponse) 74 | if err := x.ClientStream.RecvMsg(m); err != nil { 75 | return nil, err 76 | } 77 | return m, nil 78 | } 79 | 80 | func (c *calculatorClient) Average(ctx context.Context, opts ...grpc.CallOption) (Calculator_AverageClient, error) { 81 | stream, err := c.cc.NewStream(ctx, &Calculator_ServiceDesc.Streams[1], "/services.Calculator/Average", opts...) 82 | if err != nil { 83 | return nil, err 84 | } 85 | x := &calculatorAverageClient{stream} 86 | return x, nil 87 | } 88 | 89 | type Calculator_AverageClient interface { 90 | Send(*AverageRequest) error 91 | CloseAndRecv() (*AverageResponse, error) 92 | grpc.ClientStream 93 | } 94 | 95 | type calculatorAverageClient struct { 96 | grpc.ClientStream 97 | } 98 | 99 | func (x *calculatorAverageClient) Send(m *AverageRequest) error { 100 | return x.ClientStream.SendMsg(m) 101 | } 102 | 103 | func (x *calculatorAverageClient) CloseAndRecv() (*AverageResponse, error) { 104 | if err := x.ClientStream.CloseSend(); err != nil { 105 | return nil, err 106 | } 107 | m := new(AverageResponse) 108 | if err := x.ClientStream.RecvMsg(m); err != nil { 109 | return nil, err 110 | } 111 | return m, nil 112 | } 113 | 114 | func (c *calculatorClient) Sum(ctx context.Context, opts ...grpc.CallOption) (Calculator_SumClient, error) { 115 | stream, err := c.cc.NewStream(ctx, &Calculator_ServiceDesc.Streams[2], "/services.Calculator/Sum", opts...) 116 | if err != nil { 117 | return nil, err 118 | } 119 | x := &calculatorSumClient{stream} 120 | return x, nil 121 | } 122 | 123 | type Calculator_SumClient interface { 124 | Send(*SumRequest) error 125 | Recv() (*SumResponse, error) 126 | grpc.ClientStream 127 | } 128 | 129 | type calculatorSumClient struct { 130 | grpc.ClientStream 131 | } 132 | 133 | func (x *calculatorSumClient) Send(m *SumRequest) error { 134 | return x.ClientStream.SendMsg(m) 135 | } 136 | 137 | func (x *calculatorSumClient) Recv() (*SumResponse, error) { 138 | m := new(SumResponse) 139 | if err := x.ClientStream.RecvMsg(m); err != nil { 140 | return nil, err 141 | } 142 | return m, nil 143 | } 144 | 145 | // CalculatorServer is the server API for Calculator service. 146 | // All implementations must embed UnimplementedCalculatorServer 147 | // for forward compatibility 148 | type CalculatorServer interface { 149 | Hello(context.Context, *HelloRequest) (*HelloResponse, error) 150 | Fibonacci(*FibonacciRequest, Calculator_FibonacciServer) error 151 | Average(Calculator_AverageServer) error 152 | Sum(Calculator_SumServer) error 153 | mustEmbedUnimplementedCalculatorServer() 154 | } 155 | 156 | // UnimplementedCalculatorServer must be embedded to have forward compatible implementations. 157 | type UnimplementedCalculatorServer struct { 158 | } 159 | 160 | func (UnimplementedCalculatorServer) Hello(context.Context, *HelloRequest) (*HelloResponse, error) { 161 | return nil, status.Errorf(codes.Unimplemented, "method Hello not implemented") 162 | } 163 | func (UnimplementedCalculatorServer) Fibonacci(*FibonacciRequest, Calculator_FibonacciServer) error { 164 | return status.Errorf(codes.Unimplemented, "method Fibonacci not implemented") 165 | } 166 | func (UnimplementedCalculatorServer) Average(Calculator_AverageServer) error { 167 | return status.Errorf(codes.Unimplemented, "method Average not implemented") 168 | } 169 | func (UnimplementedCalculatorServer) Sum(Calculator_SumServer) error { 170 | return status.Errorf(codes.Unimplemented, "method Sum not implemented") 171 | } 172 | func (UnimplementedCalculatorServer) mustEmbedUnimplementedCalculatorServer() {} 173 | 174 | // UnsafeCalculatorServer may be embedded to opt out of forward compatibility for this service. 175 | // Use of this interface is not recommended, as added methods to CalculatorServer will 176 | // result in compilation errors. 177 | type UnsafeCalculatorServer interface { 178 | mustEmbedUnimplementedCalculatorServer() 179 | } 180 | 181 | func RegisterCalculatorServer(s grpc.ServiceRegistrar, srv CalculatorServer) { 182 | s.RegisterService(&Calculator_ServiceDesc, srv) 183 | } 184 | 185 | func _Calculator_Hello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 186 | in := new(HelloRequest) 187 | if err := dec(in); err != nil { 188 | return nil, err 189 | } 190 | if interceptor == nil { 191 | return srv.(CalculatorServer).Hello(ctx, in) 192 | } 193 | info := &grpc.UnaryServerInfo{ 194 | Server: srv, 195 | FullMethod: "/services.Calculator/Hello", 196 | } 197 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 198 | return srv.(CalculatorServer).Hello(ctx, req.(*HelloRequest)) 199 | } 200 | return interceptor(ctx, in, info, handler) 201 | } 202 | 203 | func _Calculator_Fibonacci_Handler(srv interface{}, stream grpc.ServerStream) error { 204 | m := new(FibonacciRequest) 205 | if err := stream.RecvMsg(m); err != nil { 206 | return err 207 | } 208 | return srv.(CalculatorServer).Fibonacci(m, &calculatorFibonacciServer{stream}) 209 | } 210 | 211 | type Calculator_FibonacciServer interface { 212 | Send(*FibonacciResponse) error 213 | grpc.ServerStream 214 | } 215 | 216 | type calculatorFibonacciServer struct { 217 | grpc.ServerStream 218 | } 219 | 220 | func (x *calculatorFibonacciServer) Send(m *FibonacciResponse) error { 221 | return x.ServerStream.SendMsg(m) 222 | } 223 | 224 | func _Calculator_Average_Handler(srv interface{}, stream grpc.ServerStream) error { 225 | return srv.(CalculatorServer).Average(&calculatorAverageServer{stream}) 226 | } 227 | 228 | type Calculator_AverageServer interface { 229 | SendAndClose(*AverageResponse) error 230 | Recv() (*AverageRequest, error) 231 | grpc.ServerStream 232 | } 233 | 234 | type calculatorAverageServer struct { 235 | grpc.ServerStream 236 | } 237 | 238 | func (x *calculatorAverageServer) SendAndClose(m *AverageResponse) error { 239 | return x.ServerStream.SendMsg(m) 240 | } 241 | 242 | func (x *calculatorAverageServer) Recv() (*AverageRequest, error) { 243 | m := new(AverageRequest) 244 | if err := x.ServerStream.RecvMsg(m); err != nil { 245 | return nil, err 246 | } 247 | return m, nil 248 | } 249 | 250 | func _Calculator_Sum_Handler(srv interface{}, stream grpc.ServerStream) error { 251 | return srv.(CalculatorServer).Sum(&calculatorSumServer{stream}) 252 | } 253 | 254 | type Calculator_SumServer interface { 255 | Send(*SumResponse) error 256 | Recv() (*SumRequest, error) 257 | grpc.ServerStream 258 | } 259 | 260 | type calculatorSumServer struct { 261 | grpc.ServerStream 262 | } 263 | 264 | func (x *calculatorSumServer) Send(m *SumResponse) error { 265 | return x.ServerStream.SendMsg(m) 266 | } 267 | 268 | func (x *calculatorSumServer) Recv() (*SumRequest, error) { 269 | m := new(SumRequest) 270 | if err := x.ServerStream.RecvMsg(m); err != nil { 271 | return nil, err 272 | } 273 | return m, nil 274 | } 275 | 276 | // Calculator_ServiceDesc is the grpc.ServiceDesc for Calculator service. 277 | // It's only intended for direct use with grpc.RegisterService, 278 | // and not to be introspected or modified (even as a copy) 279 | var Calculator_ServiceDesc = grpc.ServiceDesc{ 280 | ServiceName: "services.Calculator", 281 | HandlerType: (*CalculatorServer)(nil), 282 | Methods: []grpc.MethodDesc{ 283 | { 284 | MethodName: "Hello", 285 | Handler: _Calculator_Hello_Handler, 286 | }, 287 | }, 288 | Streams: []grpc.StreamDesc{ 289 | { 290 | StreamName: "Fibonacci", 291 | Handler: _Calculator_Fibonacci_Handler, 292 | ServerStreams: true, 293 | }, 294 | { 295 | StreamName: "Average", 296 | Handler: _Calculator_Average_Handler, 297 | ClientStreams: true, 298 | }, 299 | { 300 | StreamName: "Sum", 301 | Handler: _Calculator_Sum_Handler, 302 | ServerStreams: true, 303 | ClientStreams: true, 304 | }, 305 | }, 306 | Metadata: "calculator.proto", 307 | } 308 | -------------------------------------------------------------------------------- /project/gogrpc/client/services/calculator_service.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "time" 8 | 9 | "google.golang.org/protobuf/types/known/timestamppb" 10 | ) 11 | 12 | type CalculatorService interface { 13 | Hello(name string) error 14 | Fibonacci(n uint32) error 15 | Average(numbers ...float64) error 16 | Sum(numbers ...int32) error 17 | } 18 | 19 | type calculatorService struct { 20 | calculatorClient CalculatorClient 21 | } 22 | 23 | func NewCalculatorService(calculatorClient CalculatorClient) CalculatorService { 24 | return calculatorService{calculatorClient} 25 | } 26 | 27 | func (base calculatorService) Hello(name string) error { 28 | req := HelloRequest{ 29 | Name: name, 30 | CreatedDate: timestamppb.Now(), 31 | } 32 | 33 | res, err := base.calculatorClient.Hello(context.Background(), &req) 34 | if err != nil { 35 | return err 36 | } 37 | 38 | fmt.Printf("Service : Hello\n") 39 | fmt.Printf("Request : %v\n", req.Name) 40 | fmt.Printf("Response: %v\n", res.Result) 41 | return nil 42 | } 43 | 44 | func (base calculatorService) Fibonacci(n uint32) error { 45 | req := FibonacciRequest{ 46 | N: n, 47 | } 48 | 49 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 50 | defer cancel() 51 | 52 | stream, err := base.calculatorClient.Fibonacci(ctx, &req) 53 | if err != nil { 54 | return err 55 | } 56 | 57 | fmt.Printf("Service : Fibonacci\n") 58 | fmt.Printf("Request : %v\n", req.N) 59 | for { 60 | res, err := stream.Recv() 61 | if err == io.EOF { 62 | break 63 | } 64 | if err != nil { 65 | return err 66 | } 67 | fmt.Printf("Response: %v\n", res.Result) 68 | } 69 | return nil 70 | } 71 | 72 | func (base calculatorService) Average(numbers ...float64) error { 73 | 74 | stream, err := base.calculatorClient.Average(context.Background()) 75 | if err != nil { 76 | return err 77 | } 78 | 79 | fmt.Printf("Service : Average\n") 80 | for _, number := range numbers { 81 | req := AverageRequest{ 82 | Number: number, 83 | } 84 | stream.Send(&req) 85 | fmt.Printf("Request : %v\n", req.Number) 86 | time.Sleep(time.Second) 87 | } 88 | 89 | res, err := stream.CloseAndRecv() 90 | if err != nil { 91 | return err 92 | } 93 | fmt.Printf("Response: %v\n", res.Result) 94 | return nil 95 | } 96 | 97 | func (base calculatorService) Sum(numbers ...int32) error { 98 | stream, err := base.calculatorClient.Sum(context.Background()) 99 | if err != nil { 100 | return err 101 | } 102 | 103 | fmt.Printf("Service : Sum\n") 104 | go func() { 105 | for _, number := range numbers { 106 | req := SumRequest{ 107 | Number: number, 108 | } 109 | stream.Send(&req) 110 | fmt.Printf("Request : %v\n", req.Number) 111 | time.Sleep(time.Second * 2) 112 | } 113 | stream.CloseSend() 114 | }() 115 | 116 | done := make(chan bool) 117 | errs := make(chan error) 118 | go func() { 119 | for { 120 | res, err := stream.Recv() 121 | if err == io.EOF { 122 | break 123 | } 124 | if err != nil { 125 | errs <- err 126 | } 127 | fmt.Printf("Response: %v\n", res.Result) 128 | } 129 | done <- true 130 | }() 131 | 132 | select { 133 | case <-done: 134 | return nil 135 | case err := <-errs: 136 | return err 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /project/gogrpc/client/services/gender.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.0 4 | // protoc v3.19.4 5 | // source: gender.proto 6 | 7 | package services 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | reflect "reflect" 13 | sync "sync" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | type Gender int32 24 | 25 | const ( 26 | Gender_UNKNOWN Gender = 0 27 | Gender_MALE Gender = 1 28 | Gender_FEMALE Gender = 2 29 | ) 30 | 31 | // Enum value maps for Gender. 32 | var ( 33 | Gender_name = map[int32]string{ 34 | 0: "UNKNOWN", 35 | 1: "MALE", 36 | 2: "FEMALE", 37 | } 38 | Gender_value = map[string]int32{ 39 | "UNKNOWN": 0, 40 | "MALE": 1, 41 | "FEMALE": 2, 42 | } 43 | ) 44 | 45 | func (x Gender) Enum() *Gender { 46 | p := new(Gender) 47 | *p = x 48 | return p 49 | } 50 | 51 | func (x Gender) String() string { 52 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 53 | } 54 | 55 | func (Gender) Descriptor() protoreflect.EnumDescriptor { 56 | return file_gender_proto_enumTypes[0].Descriptor() 57 | } 58 | 59 | func (Gender) Type() protoreflect.EnumType { 60 | return &file_gender_proto_enumTypes[0] 61 | } 62 | 63 | func (x Gender) Number() protoreflect.EnumNumber { 64 | return protoreflect.EnumNumber(x) 65 | } 66 | 67 | // Deprecated: Use Gender.Descriptor instead. 68 | func (Gender) EnumDescriptor() ([]byte, []int) { 69 | return file_gender_proto_rawDescGZIP(), []int{0} 70 | } 71 | 72 | var File_gender_proto protoreflect.FileDescriptor 73 | 74 | var file_gender_proto_rawDesc = []byte{ 75 | 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 76 | 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2a, 0x2b, 0x0a, 0x06, 0x47, 0x65, 0x6e, 0x64, 77 | 0x65, 0x72, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 78 | 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x45, 0x4d, 79 | 0x41, 0x4c, 0x45, 0x10, 0x02, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 80 | 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 81 | } 82 | 83 | var ( 84 | file_gender_proto_rawDescOnce sync.Once 85 | file_gender_proto_rawDescData = file_gender_proto_rawDesc 86 | ) 87 | 88 | func file_gender_proto_rawDescGZIP() []byte { 89 | file_gender_proto_rawDescOnce.Do(func() { 90 | file_gender_proto_rawDescData = protoimpl.X.CompressGZIP(file_gender_proto_rawDescData) 91 | }) 92 | return file_gender_proto_rawDescData 93 | } 94 | 95 | var file_gender_proto_enumTypes = make([]protoimpl.EnumInfo, 1) 96 | var file_gender_proto_goTypes = []interface{}{ 97 | (Gender)(0), // 0: services.Gender 98 | } 99 | var file_gender_proto_depIdxs = []int32{ 100 | 0, // [0:0] is the sub-list for method output_type 101 | 0, // [0:0] is the sub-list for method input_type 102 | 0, // [0:0] is the sub-list for extension type_name 103 | 0, // [0:0] is the sub-list for extension extendee 104 | 0, // [0:0] is the sub-list for field type_name 105 | } 106 | 107 | func init() { file_gender_proto_init() } 108 | func file_gender_proto_init() { 109 | if File_gender_proto != nil { 110 | return 111 | } 112 | type x struct{} 113 | out := protoimpl.TypeBuilder{ 114 | File: protoimpl.DescBuilder{ 115 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 116 | RawDescriptor: file_gender_proto_rawDesc, 117 | NumEnums: 1, 118 | NumMessages: 0, 119 | NumExtensions: 0, 120 | NumServices: 0, 121 | }, 122 | GoTypes: file_gender_proto_goTypes, 123 | DependencyIndexes: file_gender_proto_depIdxs, 124 | EnumInfos: file_gender_proto_enumTypes, 125 | }.Build() 126 | File_gender_proto = out.File 127 | file_gender_proto_rawDesc = nil 128 | file_gender_proto_goTypes = nil 129 | file_gender_proto_depIdxs = nil 130 | } 131 | -------------------------------------------------------------------------------- /project/gogrpc/gogrpc.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "proto" 5 | }, 6 | { 7 | "path": "server" 8 | }, 9 | { 10 | "path": "client" 11 | }, 12 | { 13 | "path": "tls" 14 | } 15 | ], 16 | "settings": {} 17 | } -------------------------------------------------------------------------------- /project/gogrpc/proto/calculator.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gender.proto"; 4 | import "google/protobuf/timestamp.proto"; 5 | 6 | package services; 7 | option go_package="./services"; 8 | 9 | service Calculator { 10 | rpc Hello(HelloRequest) returns(HelloResponse); 11 | rpc Fibonacci(FibonacciRequest) returns(stream FibonacciResponse); 12 | rpc Average(stream AverageRequest) returns(AverageResponse); 13 | rpc Sum(stream SumRequest) returns(stream SumResponse); 14 | } 15 | 16 | message HelloRequest { 17 | string name = 1; 18 | google.protobuf.Timestamp created_date = 2; 19 | } 20 | 21 | message HelloResponse { 22 | string result = 1; 23 | } 24 | 25 | message Person { 26 | string name = 1; 27 | int32 age = 2; 28 | float weight = 3; 29 | double height = 4; 30 | bool active = 5; 31 | repeated string phone_number = 6; 32 | Gender gender = 7; 33 | map contries = 8; 34 | google.protobuf.Timestamp created_date = 9; 35 | } 36 | 37 | message FibonacciRequest { 38 | uint32 n = 1; 39 | } 40 | 41 | message FibonacciResponse { 42 | uint32 result = 1; 43 | } 44 | 45 | message AverageRequest { 46 | double number = 1; 47 | } 48 | 49 | message AverageResponse { 50 | double result = 1; 51 | } 52 | 53 | message SumRequest { 54 | int32 number = 1; 55 | } 56 | 57 | message SumResponse { 58 | int32 result = 1; 59 | } -------------------------------------------------------------------------------- /project/gogrpc/proto/gen.sh: -------------------------------------------------------------------------------- 1 | protoc *.proto --go_out=../server --go-grpc_out=../server 2 | protoc *.proto --go_out=../client --go-grpc_out=../client -------------------------------------------------------------------------------- /project/gogrpc/proto/gender.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package services; 4 | option go_package="./services"; 5 | 6 | enum Gender { 7 | UNKNOWN = 0; 8 | MALE = 1; 9 | FEMALE = 2; 10 | } -------------------------------------------------------------------------------- /project/gogrpc/server/go.mod: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | go 1.18 4 | 5 | require ( 6 | google.golang.org/grpc v1.45.0 7 | google.golang.org/protobuf v1.28.0 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.2 // indirect 12 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 13 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 14 | golang.org/x/text v0.3.0 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /project/gogrpc/server/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 5 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 6 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 7 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 8 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 9 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 10 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 11 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 12 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 13 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 14 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 15 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 16 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 17 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 18 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 19 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 20 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 21 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 22 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 23 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 24 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 25 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 26 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 27 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 28 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 29 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 30 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 31 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 32 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 33 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 34 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 35 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 36 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 37 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 38 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 39 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 40 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 41 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 42 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 43 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 44 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 45 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 46 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 47 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 48 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 49 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 50 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 51 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 52 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 53 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 54 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 55 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 56 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 57 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 58 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 59 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 60 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 61 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 62 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 63 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 64 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 65 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 66 | golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= 67 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 68 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 69 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 70 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 71 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 72 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 73 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 74 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 75 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 76 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 77 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= 78 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 79 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 80 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 81 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 82 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 83 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 84 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 85 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 86 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 87 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 88 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 89 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 90 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 91 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 92 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 93 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= 94 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 95 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 96 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 97 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 98 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 99 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 100 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 101 | google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= 102 | google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= 103 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 104 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 105 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 106 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 107 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 108 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 109 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 110 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 111 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 112 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 113 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 114 | google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= 115 | google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 116 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 117 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 118 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 119 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 120 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 121 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 122 | -------------------------------------------------------------------------------- /project/gogrpc/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "net" 8 | "server/services" 9 | 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/credentials" 12 | "google.golang.org/grpc/reflection" 13 | ) 14 | 15 | func main() { 16 | 17 | var s *grpc.Server 18 | 19 | tls := flag.Bool("tls", false, "use a secure TLS connection") 20 | flag.Parse() 21 | 22 | if *tls { 23 | certFile := "../tls/server.crt" 24 | keyFile := "../tls/server.pem" 25 | creds, err := credentials.NewServerTLSFromFile(certFile, keyFile) 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | s = grpc.NewServer(grpc.Creds(creds)) 30 | } else { 31 | s = grpc.NewServer() 32 | } 33 | 34 | listener, err := net.Listen("tcp", ":50051") 35 | if err != nil { 36 | log.Fatal(err) 37 | } 38 | 39 | services.RegisterCalculatorServer(s, services.NewCalculatorServer()) 40 | reflection.Register(s) 41 | 42 | fmt.Print("gRPC server listening on port 50051") 43 | if *tls { 44 | fmt.Println(" with TLS") 45 | } else { 46 | fmt.Println() 47 | } 48 | err = s.Serve(listener) 49 | if err != nil { 50 | log.Fatal(err) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /project/gogrpc/server/services/calculator_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.19.4 5 | // source: calculator.proto 6 | 7 | package services 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // CalculatorClient is the client API for Calculator service. 22 | // 23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 24 | type CalculatorClient interface { 25 | Hello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) 26 | Fibonacci(ctx context.Context, in *FibonacciRequest, opts ...grpc.CallOption) (Calculator_FibonacciClient, error) 27 | Average(ctx context.Context, opts ...grpc.CallOption) (Calculator_AverageClient, error) 28 | Sum(ctx context.Context, opts ...grpc.CallOption) (Calculator_SumClient, error) 29 | } 30 | 31 | type calculatorClient struct { 32 | cc grpc.ClientConnInterface 33 | } 34 | 35 | func NewCalculatorClient(cc grpc.ClientConnInterface) CalculatorClient { 36 | return &calculatorClient{cc} 37 | } 38 | 39 | func (c *calculatorClient) Hello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) { 40 | out := new(HelloResponse) 41 | err := c.cc.Invoke(ctx, "/services.Calculator/Hello", in, out, opts...) 42 | if err != nil { 43 | return nil, err 44 | } 45 | return out, nil 46 | } 47 | 48 | func (c *calculatorClient) Fibonacci(ctx context.Context, in *FibonacciRequest, opts ...grpc.CallOption) (Calculator_FibonacciClient, error) { 49 | stream, err := c.cc.NewStream(ctx, &Calculator_ServiceDesc.Streams[0], "/services.Calculator/Fibonacci", opts...) 50 | if err != nil { 51 | return nil, err 52 | } 53 | x := &calculatorFibonacciClient{stream} 54 | if err := x.ClientStream.SendMsg(in); err != nil { 55 | return nil, err 56 | } 57 | if err := x.ClientStream.CloseSend(); err != nil { 58 | return nil, err 59 | } 60 | return x, nil 61 | } 62 | 63 | type Calculator_FibonacciClient interface { 64 | Recv() (*FibonacciResponse, error) 65 | grpc.ClientStream 66 | } 67 | 68 | type calculatorFibonacciClient struct { 69 | grpc.ClientStream 70 | } 71 | 72 | func (x *calculatorFibonacciClient) Recv() (*FibonacciResponse, error) { 73 | m := new(FibonacciResponse) 74 | if err := x.ClientStream.RecvMsg(m); err != nil { 75 | return nil, err 76 | } 77 | return m, nil 78 | } 79 | 80 | func (c *calculatorClient) Average(ctx context.Context, opts ...grpc.CallOption) (Calculator_AverageClient, error) { 81 | stream, err := c.cc.NewStream(ctx, &Calculator_ServiceDesc.Streams[1], "/services.Calculator/Average", opts...) 82 | if err != nil { 83 | return nil, err 84 | } 85 | x := &calculatorAverageClient{stream} 86 | return x, nil 87 | } 88 | 89 | type Calculator_AverageClient interface { 90 | Send(*AverageRequest) error 91 | CloseAndRecv() (*AverageResponse, error) 92 | grpc.ClientStream 93 | } 94 | 95 | type calculatorAverageClient struct { 96 | grpc.ClientStream 97 | } 98 | 99 | func (x *calculatorAverageClient) Send(m *AverageRequest) error { 100 | return x.ClientStream.SendMsg(m) 101 | } 102 | 103 | func (x *calculatorAverageClient) CloseAndRecv() (*AverageResponse, error) { 104 | if err := x.ClientStream.CloseSend(); err != nil { 105 | return nil, err 106 | } 107 | m := new(AverageResponse) 108 | if err := x.ClientStream.RecvMsg(m); err != nil { 109 | return nil, err 110 | } 111 | return m, nil 112 | } 113 | 114 | func (c *calculatorClient) Sum(ctx context.Context, opts ...grpc.CallOption) (Calculator_SumClient, error) { 115 | stream, err := c.cc.NewStream(ctx, &Calculator_ServiceDesc.Streams[2], "/services.Calculator/Sum", opts...) 116 | if err != nil { 117 | return nil, err 118 | } 119 | x := &calculatorSumClient{stream} 120 | return x, nil 121 | } 122 | 123 | type Calculator_SumClient interface { 124 | Send(*SumRequest) error 125 | Recv() (*SumResponse, error) 126 | grpc.ClientStream 127 | } 128 | 129 | type calculatorSumClient struct { 130 | grpc.ClientStream 131 | } 132 | 133 | func (x *calculatorSumClient) Send(m *SumRequest) error { 134 | return x.ClientStream.SendMsg(m) 135 | } 136 | 137 | func (x *calculatorSumClient) Recv() (*SumResponse, error) { 138 | m := new(SumResponse) 139 | if err := x.ClientStream.RecvMsg(m); err != nil { 140 | return nil, err 141 | } 142 | return m, nil 143 | } 144 | 145 | // CalculatorServer is the server API for Calculator service. 146 | // All implementations must embed UnimplementedCalculatorServer 147 | // for forward compatibility 148 | type CalculatorServer interface { 149 | Hello(context.Context, *HelloRequest) (*HelloResponse, error) 150 | Fibonacci(*FibonacciRequest, Calculator_FibonacciServer) error 151 | Average(Calculator_AverageServer) error 152 | Sum(Calculator_SumServer) error 153 | mustEmbedUnimplementedCalculatorServer() 154 | } 155 | 156 | // UnimplementedCalculatorServer must be embedded to have forward compatible implementations. 157 | type UnimplementedCalculatorServer struct { 158 | } 159 | 160 | func (UnimplementedCalculatorServer) Hello(context.Context, *HelloRequest) (*HelloResponse, error) { 161 | return nil, status.Errorf(codes.Unimplemented, "method Hello not implemented") 162 | } 163 | func (UnimplementedCalculatorServer) Fibonacci(*FibonacciRequest, Calculator_FibonacciServer) error { 164 | return status.Errorf(codes.Unimplemented, "method Fibonacci not implemented") 165 | } 166 | func (UnimplementedCalculatorServer) Average(Calculator_AverageServer) error { 167 | return status.Errorf(codes.Unimplemented, "method Average not implemented") 168 | } 169 | func (UnimplementedCalculatorServer) Sum(Calculator_SumServer) error { 170 | return status.Errorf(codes.Unimplemented, "method Sum not implemented") 171 | } 172 | func (UnimplementedCalculatorServer) mustEmbedUnimplementedCalculatorServer() {} 173 | 174 | // UnsafeCalculatorServer may be embedded to opt out of forward compatibility for this service. 175 | // Use of this interface is not recommended, as added methods to CalculatorServer will 176 | // result in compilation errors. 177 | type UnsafeCalculatorServer interface { 178 | mustEmbedUnimplementedCalculatorServer() 179 | } 180 | 181 | func RegisterCalculatorServer(s grpc.ServiceRegistrar, srv CalculatorServer) { 182 | s.RegisterService(&Calculator_ServiceDesc, srv) 183 | } 184 | 185 | func _Calculator_Hello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 186 | in := new(HelloRequest) 187 | if err := dec(in); err != nil { 188 | return nil, err 189 | } 190 | if interceptor == nil { 191 | return srv.(CalculatorServer).Hello(ctx, in) 192 | } 193 | info := &grpc.UnaryServerInfo{ 194 | Server: srv, 195 | FullMethod: "/services.Calculator/Hello", 196 | } 197 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 198 | return srv.(CalculatorServer).Hello(ctx, req.(*HelloRequest)) 199 | } 200 | return interceptor(ctx, in, info, handler) 201 | } 202 | 203 | func _Calculator_Fibonacci_Handler(srv interface{}, stream grpc.ServerStream) error { 204 | m := new(FibonacciRequest) 205 | if err := stream.RecvMsg(m); err != nil { 206 | return err 207 | } 208 | return srv.(CalculatorServer).Fibonacci(m, &calculatorFibonacciServer{stream}) 209 | } 210 | 211 | type Calculator_FibonacciServer interface { 212 | Send(*FibonacciResponse) error 213 | grpc.ServerStream 214 | } 215 | 216 | type calculatorFibonacciServer struct { 217 | grpc.ServerStream 218 | } 219 | 220 | func (x *calculatorFibonacciServer) Send(m *FibonacciResponse) error { 221 | return x.ServerStream.SendMsg(m) 222 | } 223 | 224 | func _Calculator_Average_Handler(srv interface{}, stream grpc.ServerStream) error { 225 | return srv.(CalculatorServer).Average(&calculatorAverageServer{stream}) 226 | } 227 | 228 | type Calculator_AverageServer interface { 229 | SendAndClose(*AverageResponse) error 230 | Recv() (*AverageRequest, error) 231 | grpc.ServerStream 232 | } 233 | 234 | type calculatorAverageServer struct { 235 | grpc.ServerStream 236 | } 237 | 238 | func (x *calculatorAverageServer) SendAndClose(m *AverageResponse) error { 239 | return x.ServerStream.SendMsg(m) 240 | } 241 | 242 | func (x *calculatorAverageServer) Recv() (*AverageRequest, error) { 243 | m := new(AverageRequest) 244 | if err := x.ServerStream.RecvMsg(m); err != nil { 245 | return nil, err 246 | } 247 | return m, nil 248 | } 249 | 250 | func _Calculator_Sum_Handler(srv interface{}, stream grpc.ServerStream) error { 251 | return srv.(CalculatorServer).Sum(&calculatorSumServer{stream}) 252 | } 253 | 254 | type Calculator_SumServer interface { 255 | Send(*SumResponse) error 256 | Recv() (*SumRequest, error) 257 | grpc.ServerStream 258 | } 259 | 260 | type calculatorSumServer struct { 261 | grpc.ServerStream 262 | } 263 | 264 | func (x *calculatorSumServer) Send(m *SumResponse) error { 265 | return x.ServerStream.SendMsg(m) 266 | } 267 | 268 | func (x *calculatorSumServer) Recv() (*SumRequest, error) { 269 | m := new(SumRequest) 270 | if err := x.ServerStream.RecvMsg(m); err != nil { 271 | return nil, err 272 | } 273 | return m, nil 274 | } 275 | 276 | // Calculator_ServiceDesc is the grpc.ServiceDesc for Calculator service. 277 | // It's only intended for direct use with grpc.RegisterService, 278 | // and not to be introspected or modified (even as a copy) 279 | var Calculator_ServiceDesc = grpc.ServiceDesc{ 280 | ServiceName: "services.Calculator", 281 | HandlerType: (*CalculatorServer)(nil), 282 | Methods: []grpc.MethodDesc{ 283 | { 284 | MethodName: "Hello", 285 | Handler: _Calculator_Hello_Handler, 286 | }, 287 | }, 288 | Streams: []grpc.StreamDesc{ 289 | { 290 | StreamName: "Fibonacci", 291 | Handler: _Calculator_Fibonacci_Handler, 292 | ServerStreams: true, 293 | }, 294 | { 295 | StreamName: "Average", 296 | Handler: _Calculator_Average_Handler, 297 | ClientStreams: true, 298 | }, 299 | { 300 | StreamName: "Sum", 301 | Handler: _Calculator_Sum_Handler, 302 | ServerStreams: true, 303 | ClientStreams: true, 304 | }, 305 | }, 306 | Metadata: "calculator.proto", 307 | } 308 | -------------------------------------------------------------------------------- /project/gogrpc/server/services/calculator_server.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | context "context" 5 | "fmt" 6 | "io" 7 | "time" 8 | 9 | "google.golang.org/grpc/codes" 10 | "google.golang.org/grpc/status" 11 | ) 12 | 13 | type calculatorServer struct { 14 | } 15 | 16 | func NewCalculatorServer() CalculatorServer { 17 | return calculatorServer{} 18 | } 19 | 20 | func (calculatorServer) mustEmbedUnimplementedCalculatorServer() {} 21 | 22 | func (calculatorServer) Hello(ctx context.Context, req *HelloRequest) (*HelloResponse, error) { 23 | 24 | if req.Name == "" { 25 | return nil, status.Errorf( 26 | codes.InvalidArgument, 27 | "name is required", 28 | ) 29 | } 30 | 31 | result := fmt.Sprintf("Hello %v at %v", req.Name, req.CreatedDate.AsTime().Local()) 32 | 33 | res := HelloResponse{ 34 | Result: result, 35 | } 36 | return &res, nil 37 | } 38 | 39 | func (calculatorServer) Fibonacci(req *FibonacciRequest, stream Calculator_FibonacciServer) error { 40 | for n := uint32(0); n <= req.N; n++ { 41 | result := fib(n) 42 | res := FibonacciResponse{ 43 | Result: result, 44 | } 45 | stream.Send(&res) 46 | time.Sleep(time.Second) 47 | } 48 | return nil 49 | } 50 | 51 | func fib(n uint32) uint32 { 52 | switch n { 53 | case 0: 54 | return 0 55 | case 1: 56 | return 1 57 | default: 58 | return fib(n-1) + fib(n-2) 59 | } 60 | } 61 | 62 | func (calculatorServer) Average(stream Calculator_AverageServer) error { 63 | sum := 0.0 64 | count := 0.0 65 | for { 66 | req, err := stream.Recv() 67 | if err == io.EOF { 68 | break 69 | } 70 | if err != nil { 71 | return err 72 | } 73 | sum += req.Number 74 | count++ 75 | } 76 | res := AverageResponse{ 77 | Result: sum / count, 78 | } 79 | return stream.SendAndClose(&res) 80 | } 81 | 82 | func (calculatorServer) Sum(stream Calculator_SumServer) error { 83 | sum := int32(0) 84 | for { 85 | req, err := stream.Recv() 86 | if err == io.EOF { 87 | break 88 | } 89 | if err != nil { 90 | return err 91 | } 92 | sum += req.Number 93 | res := SumResponse{ 94 | Result: sum, 95 | } 96 | err = stream.Send(&res) 97 | if err != nil { 98 | return err 99 | } 100 | } 101 | return nil 102 | } 103 | -------------------------------------------------------------------------------- /project/gogrpc/server/services/gender.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.0 4 | // protoc v3.19.4 5 | // source: gender.proto 6 | 7 | package services 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | reflect "reflect" 13 | sync "sync" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | type Gender int32 24 | 25 | const ( 26 | Gender_UNKNOWN Gender = 0 27 | Gender_MALE Gender = 1 28 | Gender_FEMALE Gender = 2 29 | ) 30 | 31 | // Enum value maps for Gender. 32 | var ( 33 | Gender_name = map[int32]string{ 34 | 0: "UNKNOWN", 35 | 1: "MALE", 36 | 2: "FEMALE", 37 | } 38 | Gender_value = map[string]int32{ 39 | "UNKNOWN": 0, 40 | "MALE": 1, 41 | "FEMALE": 2, 42 | } 43 | ) 44 | 45 | func (x Gender) Enum() *Gender { 46 | p := new(Gender) 47 | *p = x 48 | return p 49 | } 50 | 51 | func (x Gender) String() string { 52 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 53 | } 54 | 55 | func (Gender) Descriptor() protoreflect.EnumDescriptor { 56 | return file_gender_proto_enumTypes[0].Descriptor() 57 | } 58 | 59 | func (Gender) Type() protoreflect.EnumType { 60 | return &file_gender_proto_enumTypes[0] 61 | } 62 | 63 | func (x Gender) Number() protoreflect.EnumNumber { 64 | return protoreflect.EnumNumber(x) 65 | } 66 | 67 | // Deprecated: Use Gender.Descriptor instead. 68 | func (Gender) EnumDescriptor() ([]byte, []int) { 69 | return file_gender_proto_rawDescGZIP(), []int{0} 70 | } 71 | 72 | var File_gender_proto protoreflect.FileDescriptor 73 | 74 | var file_gender_proto_rawDesc = []byte{ 75 | 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 76 | 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2a, 0x2b, 0x0a, 0x06, 0x47, 0x65, 0x6e, 0x64, 77 | 0x65, 0x72, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 78 | 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x45, 0x4d, 79 | 0x41, 0x4c, 0x45, 0x10, 0x02, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 80 | 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 81 | } 82 | 83 | var ( 84 | file_gender_proto_rawDescOnce sync.Once 85 | file_gender_proto_rawDescData = file_gender_proto_rawDesc 86 | ) 87 | 88 | func file_gender_proto_rawDescGZIP() []byte { 89 | file_gender_proto_rawDescOnce.Do(func() { 90 | file_gender_proto_rawDescData = protoimpl.X.CompressGZIP(file_gender_proto_rawDescData) 91 | }) 92 | return file_gender_proto_rawDescData 93 | } 94 | 95 | var file_gender_proto_enumTypes = make([]protoimpl.EnumInfo, 1) 96 | var file_gender_proto_goTypes = []interface{}{ 97 | (Gender)(0), // 0: services.Gender 98 | } 99 | var file_gender_proto_depIdxs = []int32{ 100 | 0, // [0:0] is the sub-list for method output_type 101 | 0, // [0:0] is the sub-list for method input_type 102 | 0, // [0:0] is the sub-list for extension type_name 103 | 0, // [0:0] is the sub-list for extension extendee 104 | 0, // [0:0] is the sub-list for field type_name 105 | } 106 | 107 | func init() { file_gender_proto_init() } 108 | func file_gender_proto_init() { 109 | if File_gender_proto != nil { 110 | return 111 | } 112 | type x struct{} 113 | out := protoimpl.TypeBuilder{ 114 | File: protoimpl.DescBuilder{ 115 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 116 | RawDescriptor: file_gender_proto_rawDesc, 117 | NumEnums: 1, 118 | NumMessages: 0, 119 | NumExtensions: 0, 120 | NumServices: 0, 121 | }, 122 | GoTypes: file_gender_proto_goTypes, 123 | DependencyIndexes: file_gender_proto_depIdxs, 124 | EnumInfos: file_gender_proto_enumTypes, 125 | }.Build() 126 | File_gender_proto = out.File 127 | file_gender_proto_rawDesc = nil 128 | file_gender_proto_goTypes = nil 129 | file_gender_proto_depIdxs = nil 130 | } 131 | -------------------------------------------------------------------------------- /project/gogrpc/tls/gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Inspired from: https://github.com/grpc/grpc-java/tree/master/examples#generating-self-signed-certificates-for-use-with-grpc 3 | 4 | # Output files 5 | # ca.key: Certificate Authority private key file (this shouldn't be shared in real-life) 6 | # ca.crt: Certificate Authority trust certificate (this should be shared with users in real-life) 7 | # server.key: Server private key, password protected (this shouldn't be shared) 8 | # server.pem: Conversion of server.key into a format gRPC likes (this shouldn't be shared) 9 | # server.csr: Server certificate signing request (this should be shared with the CA owner) 10 | # server.crt: Server certificate signed by the CA (this would be sent back by the CA owner) - keep on server 11 | 12 | # Summary 13 | # Private files: ca.key, server.key, server.pem, server.crt 14 | # "Share" files: ca.crt (needed by the client), server.csr (needed by the CA) 15 | 16 | # Changes these CN's to match your hosts in your environment if needed. 17 | SERVER_CN=localhost 18 | 19 | # Step 1: Generate Certificate Authority + Trust Certificate (ca.crt) 20 | openssl genrsa -passout pass:1111 -des3 -out ca.key 4096 21 | openssl req -passin pass:1111 -new -x509 -sha256 -days 365 -key ca.key -out ca.crt -subj "/CN=${SERVER_CN}" 22 | 23 | # Step 2: Generate the Server Private Key (server.key) 24 | openssl genrsa -passout pass:1111 -des3 -out server.key 4096 25 | 26 | # Step 3: Convert the server certificate to .pem format (server.pem) - usable by gRPC 27 | openssl pkcs8 -topk8 -nocrypt -passin pass:1111 -in server.key -out server.pem 28 | 29 | # Step 4: Get a certificate signing request from the CA (server.csr) 30 | openssl req -passin pass:1111 -new -sha256 -key server.key -out server.csr -subj "/CN=${SERVER_CN}" -config ssl.cnf 31 | 32 | # Step 5: Sign the certificate with the CA we created (it's called self signing) - server.crt 33 | openssl x509 -req -passin pass:1111 -sha256 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt -extensions req_ext -extfile ssl.cnf -------------------------------------------------------------------------------- /project/gogrpc/tls/ssl.cnf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 4096 3 | distinguished_name = dn 4 | req_extensions = req_ext 5 | prompt = no 6 | 7 | [ dn ] 8 | CN = localhost 9 | 10 | [ req_ext ] 11 | subjectAltName = @alt_names 12 | 13 | [alt_names] 14 | DNS.1 = localhost -------------------------------------------------------------------------------- /project/gokafka/consumer/config.yaml: -------------------------------------------------------------------------------- 1 | kafka: 2 | servers: 3 | - codebangkok.com:9092 4 | group: accountConsumer 5 | 6 | db: 7 | driver: mysql 8 | host: codebangkok.com 9 | port: 3306 10 | username: bond 11 | password: P@ssw0rd 12 | database: micro -------------------------------------------------------------------------------- /project/gokafka/consumer/go.mod: -------------------------------------------------------------------------------- 1 | module consumer 2 | 3 | go 1.17 4 | 5 | replace events => ../events 6 | 7 | require ( 8 | events v0.0.0-00010101000000-000000000000 9 | github.com/Shopify/sarama v1.31.1 10 | github.com/spf13/viper v1.10.1 11 | gorm.io/driver/mysql v1.2.3 12 | gorm.io/gorm v1.22.5 13 | ) 14 | 15 | require ( 16 | github.com/davecgh/go-spew v1.1.1 // indirect 17 | github.com/eapache/go-resiliency v1.2.0 // indirect 18 | github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect 19 | github.com/eapache/queue v1.1.0 // indirect 20 | github.com/fsnotify/fsnotify v1.5.1 // indirect 21 | github.com/go-sql-driver/mysql v1.6.0 // indirect 22 | github.com/golang/snappy v0.0.4 // indirect 23 | github.com/hashicorp/go-uuid v1.0.2 // indirect 24 | github.com/hashicorp/hcl v1.0.0 // indirect 25 | github.com/jcmturner/aescts/v2 v2.0.0 // indirect 26 | github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect 27 | github.com/jcmturner/gofork v1.0.0 // indirect 28 | github.com/jcmturner/gokrb5/v8 v8.4.2 // indirect 29 | github.com/jcmturner/rpc/v2 v2.0.3 // indirect 30 | github.com/jinzhu/inflection v1.0.0 // indirect 31 | github.com/jinzhu/now v1.1.4 // indirect 32 | github.com/klauspost/compress v1.14.2 // indirect 33 | github.com/magiconair/properties v1.8.5 // indirect 34 | github.com/mitchellh/mapstructure v1.4.3 // indirect 35 | github.com/pelletier/go-toml v1.9.4 // indirect 36 | github.com/pierrec/lz4 v2.6.1+incompatible // indirect 37 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect 38 | github.com/spf13/afero v1.6.0 // indirect 39 | github.com/spf13/cast v1.4.1 // indirect 40 | github.com/spf13/jwalterweatherman v1.1.0 // indirect 41 | github.com/spf13/pflag v1.0.5 // indirect 42 | github.com/subosito/gotenv v1.2.0 // indirect 43 | golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed // indirect 44 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect 45 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect 46 | golang.org/x/text v0.3.7 // indirect 47 | gopkg.in/ini.v1 v1.66.2 // indirect 48 | gopkg.in/yaml.v2 v2.4.0 // indirect 49 | ) 50 | -------------------------------------------------------------------------------- /project/gokafka/consumer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "consumer/repositories" 5 | "consumer/services" 6 | "context" 7 | "events" 8 | "fmt" 9 | "strings" 10 | 11 | "github.com/Shopify/sarama" 12 | "github.com/spf13/viper" 13 | "gorm.io/driver/mysql" 14 | "gorm.io/gorm" 15 | "gorm.io/gorm/logger" 16 | ) 17 | 18 | func init() { 19 | viper.SetConfigName("config") 20 | viper.SetConfigType("yaml") 21 | viper.AddConfigPath(".") 22 | viper.AutomaticEnv() 23 | viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) 24 | if err := viper.ReadInConfig(); err != nil { 25 | panic(err) 26 | } 27 | } 28 | 29 | func initDatabase() *gorm.DB { 30 | dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v", 31 | viper.GetString("db.username"), 32 | viper.GetString("db.password"), 33 | viper.GetString("db.host"), 34 | viper.GetInt("db.port"), 35 | viper.GetString("db.database"), 36 | ) 37 | 38 | dial := mysql.Open(dsn) 39 | 40 | db, err := gorm.Open(dial, &gorm.Config{ 41 | Logger: logger.Default.LogMode(logger.Silent), 42 | }) 43 | if err != nil { 44 | panic(err) 45 | } 46 | return db 47 | } 48 | 49 | func main() { 50 | 51 | consumer, err := sarama.NewConsumerGroup(viper.GetStringSlice("kafka.servers"), viper.GetString("kafka.group"), nil) 52 | if err != nil { 53 | panic(err) 54 | } 55 | defer consumer.Close() 56 | 57 | db := initDatabase() 58 | accountRepo := repositories.NewAccountRepository(db) 59 | accountEventHandler := services.NewAccountEventHandler(accountRepo) 60 | accountConsumerHandler := services.NewConsumerHandler(accountEventHandler) 61 | 62 | fmt.Println("Account consumer started...") 63 | for { 64 | consumer.Consume(context.Background(), events.Topics, accountConsumerHandler) 65 | } 66 | } 67 | 68 | // func main() { 69 | 70 | // servers := []string{"codebangkok.com:9092"} 71 | 72 | // consumer, err := sarama.NewConsumer(servers, nil) 73 | // if err != nil { 74 | // panic(err) 75 | // } 76 | // defer consumer.Close() 77 | 78 | // partitionConsumer, err := consumer.ConsumePartition("bondhello", 0, sarama.OffsetNewest) 79 | // if err != nil { 80 | // panic(err) 81 | // } 82 | // defer partitionConsumer.Close() 83 | 84 | // fmt.Println("Consumer start.") 85 | // for { 86 | // select { 87 | // case err := <-partitionConsumer.Errors(): 88 | // fmt.Println(err) 89 | // case msg := <-partitionConsumer.Messages(): 90 | // fmt.Println(string(msg.Value)) 91 | // } 92 | // } 93 | // } 94 | -------------------------------------------------------------------------------- /project/gokafka/consumer/repositories/account.go: -------------------------------------------------------------------------------- 1 | package repositories 2 | 3 | import "gorm.io/gorm" 4 | 5 | type BankAccount struct { 6 | ID string 7 | AccountHolder string 8 | AccountType int 9 | Balance float64 10 | } 11 | 12 | type AccountRepository interface { 13 | Save(bankAccount BankAccount) error 14 | Delete(id string) error 15 | FindAll() (bankAccounts []BankAccount, err error) 16 | FindByID(id string) (bankAccount BankAccount, err error) 17 | } 18 | 19 | type accountRepository struct { 20 | db *gorm.DB 21 | } 22 | 23 | func NewAccountRepository(db *gorm.DB) AccountRepository { 24 | db.Table("bond_banks").AutoMigrate(&BankAccount{}) 25 | return accountRepository{db} 26 | } 27 | 28 | func (obj accountRepository) Save(bankAccount BankAccount) error { 29 | return obj.db.Table("bond_banks").Save(bankAccount).Error 30 | } 31 | 32 | func (obj accountRepository) Delete(id string) error { 33 | return obj.db.Table("bond_banks").Where("id=?", id).Delete(&BankAccount{}).Error 34 | } 35 | 36 | func (obj accountRepository) FindAll() (bankAccounts []BankAccount, err error) { 37 | err = obj.db.Table("bond_banks").Find(&bankAccounts).Error 38 | return bankAccounts, err 39 | } 40 | 41 | func (obj accountRepository) FindByID(id string) (bankAccount BankAccount, err error) { 42 | err = obj.db.Table("bond_banks").Where("id=?", id).First(&bankAccount).Error 43 | return bankAccount, err 44 | } 45 | -------------------------------------------------------------------------------- /project/gokafka/consumer/services/account.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "consumer/repositories" 5 | "encoding/json" 6 | "events" 7 | "log" 8 | "reflect" 9 | ) 10 | 11 | type EventHandler interface { 12 | Handle(topic string, eventBytes []byte) 13 | } 14 | 15 | type accountEventHandler struct { 16 | accountRepo repositories.AccountRepository 17 | } 18 | 19 | func NewAccountEventHandler(accountRepo repositories.AccountRepository) EventHandler { 20 | return accountEventHandler{accountRepo} 21 | } 22 | 23 | func (obj accountEventHandler) Handle(topic string, eventBytes []byte) { 24 | switch topic { 25 | case reflect.TypeOf(events.OpenAccountEvent{}).Name(): 26 | event := &events.OpenAccountEvent{} 27 | err := json.Unmarshal(eventBytes, event) 28 | if err != nil { 29 | log.Println(err) 30 | return 31 | } 32 | bankAccount := repositories.BankAccount{ 33 | ID: event.ID, 34 | AccountHolder: event.AccountHolder, 35 | AccountType: event.AccountType, 36 | Balance: event.OpeningBalance, 37 | } 38 | err = obj.accountRepo.Save(bankAccount) 39 | if err != nil { 40 | log.Println(err) 41 | return 42 | } 43 | log.Printf("[%v] %#v", topic, event) 44 | case reflect.TypeOf(events.DepositFundEvent{}).Name(): 45 | event := &events.DepositFundEvent{} 46 | err := json.Unmarshal(eventBytes, event) 47 | if err != nil { 48 | log.Println(err) 49 | return 50 | } 51 | bankAccount, err := obj.accountRepo.FindByID(event.ID) 52 | if err != nil { 53 | log.Println(err) 54 | return 55 | } 56 | bankAccount.Balance += event.Amount 57 | 58 | err = obj.accountRepo.Save(bankAccount) 59 | if err != nil { 60 | log.Println(err) 61 | return 62 | } 63 | log.Printf("[%v] %#v", topic, event) 64 | case reflect.TypeOf(events.WithdrawFundEvent{}).Name(): 65 | event := &events.WithdrawFundEvent{} 66 | err := json.Unmarshal(eventBytes, event) 67 | if err != nil { 68 | log.Println(err) 69 | return 70 | } 71 | bankAccount, err := obj.accountRepo.FindByID(event.ID) 72 | if err != nil { 73 | log.Println(err) 74 | return 75 | } 76 | bankAccount.Balance -= event.Amount 77 | 78 | err = obj.accountRepo.Save(bankAccount) 79 | if err != nil { 80 | log.Println(err) 81 | return 82 | } 83 | log.Printf("[%v] %#v", topic, event) 84 | case reflect.TypeOf(events.CloseAccountEvent{}).Name(): 85 | event := &events.CloseAccountEvent{} 86 | err := json.Unmarshal(eventBytes, event) 87 | if err != nil { 88 | log.Println(err) 89 | return 90 | } 91 | err = obj.accountRepo.Delete(event.ID) 92 | if err != nil { 93 | log.Println(err) 94 | return 95 | } 96 | log.Printf("[%v] %#v", topic, event) 97 | default: 98 | log.Println("no event handler") 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /project/gokafka/consumer/services/consumer.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import "github.com/Shopify/sarama" 4 | 5 | type consumerHandler struct { 6 | eventHandler EventHandler 7 | } 8 | 9 | func NewConsumerHandler(eventHandler EventHandler) sarama.ConsumerGroupHandler { 10 | return consumerHandler{eventHandler} 11 | } 12 | 13 | func (obj consumerHandler) Setup(sarama.ConsumerGroupSession) error { 14 | return nil 15 | } 16 | 17 | func (obj consumerHandler) Cleanup(sarama.ConsumerGroupSession) error { 18 | return nil 19 | } 20 | 21 | func (obj consumerHandler) ConsumeClaim(session sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error { 22 | for msg := range claim.Messages() { 23 | obj.eventHandler.Handle(msg.Topic, msg.Value) 24 | session.MarkMessage(msg, "") 25 | } 26 | 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /project/gokafka/events/event.go: -------------------------------------------------------------------------------- 1 | package events 2 | 3 | import "reflect" 4 | 5 | var Topics = []string{ 6 | reflect.TypeOf(OpenAccountEvent{}).Name(), 7 | reflect.TypeOf(DepositFundEvent{}).Name(), 8 | reflect.TypeOf(WithdrawFundEvent{}).Name(), 9 | reflect.TypeOf(CloseAccountEvent{}).Name(), 10 | } 11 | 12 | type Event interface { 13 | } 14 | 15 | type OpenAccountEvent struct { 16 | ID string 17 | AccountHolder string 18 | AccountType int 19 | OpeningBalance float64 20 | } 21 | 22 | type DepositFundEvent struct { 23 | ID string 24 | Amount float64 25 | } 26 | 27 | type WithdrawFundEvent struct { 28 | ID string 29 | Amount float64 30 | } 31 | 32 | type CloseAccountEvent struct { 33 | ID string 34 | } 35 | -------------------------------------------------------------------------------- /project/gokafka/events/go.mod: -------------------------------------------------------------------------------- 1 | module events 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /project/gokafka/gokafka.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "server" 5 | }, 6 | { 7 | "path": "consumer" 8 | }, 9 | { 10 | "path": "producer" 11 | }, 12 | { 13 | "path": "events" 14 | } 15 | ], 16 | "settings": {} 17 | } -------------------------------------------------------------------------------- /project/gokafka/producer/commands/command.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | type OpenAccountCommand struct { 4 | AccountHolder string 5 | AccountType int 6 | OpeningBalance float64 7 | } 8 | 9 | type DepositFundCommand struct { 10 | ID string 11 | Amount float64 12 | } 13 | 14 | type WithdrawFundCommand struct { 15 | ID string 16 | Amount float64 17 | } 18 | 19 | type CloseAccountCommand struct { 20 | ID string 21 | } 22 | -------------------------------------------------------------------------------- /project/gokafka/producer/config.yaml: -------------------------------------------------------------------------------- 1 | kafka: 2 | servers: 3 | - codebangkok.com:9092 4 | -------------------------------------------------------------------------------- /project/gokafka/producer/controllers/account.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "log" 5 | "producer/commands" 6 | "producer/services" 7 | 8 | "github.com/gofiber/fiber/v2" 9 | ) 10 | 11 | type AccountController interface { 12 | OpenAccount(c *fiber.Ctx) error 13 | DepositFund(c *fiber.Ctx) error 14 | WithdrawFund(c *fiber.Ctx) error 15 | CloseAccount(c *fiber.Ctx) error 16 | } 17 | 18 | type accountController struct { 19 | accountService services.AccountService 20 | } 21 | 22 | func NewAccountController(accountService services.AccountService) AccountController { 23 | return accountController{accountService} 24 | } 25 | 26 | func (obj accountController) OpenAccount(c *fiber.Ctx) error { 27 | command := commands.OpenAccountCommand{} 28 | 29 | err := c.BodyParser(&command) 30 | if err != nil { 31 | return err 32 | } 33 | 34 | id, err := obj.accountService.OpenAccount(command) 35 | if err != nil { 36 | log.Println(err) 37 | return err 38 | } 39 | 40 | c.Status(fiber.StatusCreated) 41 | return c.JSON(fiber.Map{ 42 | "message": "open account success", 43 | "id": id, 44 | }) 45 | } 46 | 47 | func (obj accountController) DepositFund(c *fiber.Ctx) error { 48 | command := commands.DepositFundCommand{} 49 | err := c.BodyParser(&command) 50 | if err != nil { 51 | return err 52 | } 53 | 54 | err = obj.accountService.DepositFund(command) 55 | if err != nil { 56 | log.Println(err) 57 | return err 58 | } 59 | 60 | return c.JSON(fiber.Map{ 61 | "message": "deposit fund success", 62 | }) 63 | } 64 | 65 | func (obj accountController) WithdrawFund(c *fiber.Ctx) error { 66 | command := commands.WithdrawFundCommand{} 67 | err := c.BodyParser(&command) 68 | if err != nil { 69 | return err 70 | } 71 | 72 | err = obj.accountService.WithdrawFund(command) 73 | if err != nil { 74 | log.Println(err) 75 | return err 76 | } 77 | 78 | return c.JSON(fiber.Map{ 79 | "message": "withdraw fund success", 80 | }) 81 | } 82 | 83 | func (obj accountController) CloseAccount(c *fiber.Ctx) error { 84 | command := commands.CloseAccountCommand{} 85 | err := c.BodyParser(&command) 86 | if err != nil { 87 | return err 88 | } 89 | 90 | err = obj.accountService.CloseAccount(command) 91 | if err != nil { 92 | log.Println(err) 93 | return err 94 | } 95 | 96 | return c.JSON(fiber.Map{ 97 | "message": "close account success", 98 | }) 99 | } 100 | -------------------------------------------------------------------------------- /project/gokafka/producer/go.mod: -------------------------------------------------------------------------------- 1 | module producer 2 | 3 | go 1.17 4 | 5 | replace events => ../events 6 | 7 | require ( 8 | events v0.0.0-00010101000000-000000000000 // indirect 9 | github.com/Shopify/sarama v1.31.1 // indirect 10 | github.com/andybalholm/brotli v1.0.4 // indirect 11 | github.com/davecgh/go-spew v1.1.1 // indirect 12 | github.com/eapache/go-resiliency v1.2.0 // indirect 13 | github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect 14 | github.com/eapache/queue v1.1.0 // indirect 15 | github.com/fsnotify/fsnotify v1.5.1 // indirect 16 | github.com/gofiber/fiber/v2 v2.27.0 // indirect 17 | github.com/golang/snappy v0.0.4 // indirect 18 | github.com/google/uuid v1.3.0 // indirect 19 | github.com/hashicorp/go-uuid v1.0.2 // indirect 20 | github.com/hashicorp/hcl v1.0.0 // indirect 21 | github.com/jcmturner/aescts/v2 v2.0.0 // indirect 22 | github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect 23 | github.com/jcmturner/gofork v1.0.0 // indirect 24 | github.com/jcmturner/gokrb5/v8 v8.4.2 // indirect 25 | github.com/jcmturner/rpc/v2 v2.0.3 // indirect 26 | github.com/klauspost/compress v1.14.2 // indirect 27 | github.com/magiconair/properties v1.8.5 // indirect 28 | github.com/mitchellh/mapstructure v1.4.3 // indirect 29 | github.com/pelletier/go-toml v1.9.4 // indirect 30 | github.com/pierrec/lz4 v2.6.1+incompatible // indirect 31 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect 32 | github.com/spf13/afero v1.6.0 // indirect 33 | github.com/spf13/cast v1.4.1 // indirect 34 | github.com/spf13/jwalterweatherman v1.1.0 // indirect 35 | github.com/spf13/pflag v1.0.5 // indirect 36 | github.com/spf13/viper v1.10.1 // indirect 37 | github.com/subosito/gotenv v1.2.0 // indirect 38 | github.com/valyala/bytebufferpool v1.0.0 // indirect 39 | github.com/valyala/fasthttp v1.33.0 // indirect 40 | github.com/valyala/tcplisten v1.0.0 // indirect 41 | golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed // indirect 42 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect 43 | golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect 44 | golang.org/x/text v0.3.7 // indirect 45 | gopkg.in/ini.v1 v1.66.2 // indirect 46 | gopkg.in/yaml.v2 v2.4.0 // indirect 47 | ) 48 | -------------------------------------------------------------------------------- /project/gokafka/producer/go.sum: -------------------------------------------------------------------------------- 1 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 2 | github.com/Shopify/sarama v1.31.1 h1:uxwJ+p4isb52RyV83MCJD8v2wJ/HBxEGMmG/8+sEzG0= 3 | github.com/Shopify/sarama v1.31.1/go.mod h1:99E1xQ1Ql2bYcuJfwdXY3cE17W8+549Ty8PG/11BDqY= 4 | github.com/Shopify/toxiproxy/v2 v2.3.0/go.mod h1:KvQTtB6RjCJY4zqNJn7C7JDFgsG5uoHYDirfUfpIm0c= 5 | github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= 6 | github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 7 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 8 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 9 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 10 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 11 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 12 | github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q= 13 | github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= 14 | github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= 15 | github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= 16 | github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= 17 | github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 18 | github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= 19 | github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= 20 | github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= 21 | github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= 22 | github.com/gofiber/fiber/v2 v2.27.0 h1:u34t1nOea7zz4jcZDK7+ZMiG+MVFYrHqMhTdYQDiFA8= 23 | github.com/gofiber/fiber/v2 v2.27.0/go.mod h1:0bPXdTu+jRqINrEq1T6mHeVBnE0lQd67PGu35jD3hLk= 24 | github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= 25 | github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 26 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 27 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 28 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 29 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 30 | github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= 31 | github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= 32 | github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= 33 | github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 34 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 35 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 36 | github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= 37 | github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= 38 | github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= 39 | github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= 40 | github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8= 41 | github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= 42 | github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= 43 | github.com/jcmturner/gokrb5/v8 v8.4.2 h1:6ZIM6b/JJN0X8UM43ZOM6Z4SJzla+a/u7scXFJzodkA= 44 | github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= 45 | github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= 46 | github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= 47 | github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 48 | github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= 49 | github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 50 | github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 51 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 52 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 53 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 54 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 55 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 56 | github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= 57 | github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 58 | github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= 59 | github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 60 | github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= 61 | github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 62 | github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= 63 | github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= 64 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 65 | github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= 66 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 67 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= 68 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= 69 | github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 70 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 71 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 72 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 73 | github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= 74 | github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= 75 | github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= 76 | github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 77 | github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= 78 | github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= 79 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 80 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 81 | github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= 82 | github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= 83 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 84 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 85 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 86 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 87 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 88 | github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= 89 | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= 90 | github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= 91 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 92 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 93 | github.com/valyala/fasthttp v1.33.0 h1:mHBKd98J5NcXuBddgjvim1i3kWzlng1SzLhrnBOU9g8= 94 | github.com/valyala/fasthttp v1.33.0/go.mod h1:KJRK/MXx0J+yd0c5hlR+s1tIHD72sniU8ZJjl97LIw4= 95 | github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= 96 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 97 | github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= 98 | github.com/xdg-go/scram v1.1.0/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= 99 | github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= 100 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 101 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 102 | golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 103 | golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 104 | golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed h1:YoWVYYAfvQ4ddHv3OKmIvX7NCAhFGTj62VP2l2kfBbA= 105 | golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 106 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 107 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 108 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 109 | golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 110 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= 111 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 112 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 113 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 114 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 115 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 116 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 117 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 118 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 119 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= 120 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 121 | golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY= 122 | golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 123 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 124 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 125 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 126 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 127 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 128 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 129 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 130 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 131 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 132 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 133 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 134 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 135 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 136 | gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= 137 | gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 138 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 139 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 140 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 141 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 142 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 143 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 144 | -------------------------------------------------------------------------------- /project/gokafka/producer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "producer/controllers" 5 | "producer/services" 6 | "strings" 7 | 8 | "github.com/Shopify/sarama" 9 | "github.com/gofiber/fiber/v2" 10 | "github.com/spf13/viper" 11 | ) 12 | 13 | func init() { 14 | viper.SetConfigName("config") 15 | viper.SetConfigType("yaml") 16 | viper.AddConfigPath(".") 17 | viper.AutomaticEnv() 18 | viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) 19 | if err := viper.ReadInConfig(); err != nil { 20 | panic(err) 21 | } 22 | } 23 | 24 | func main() { 25 | producer, err := sarama.NewSyncProducer(viper.GetStringSlice("kafka.servers"), nil) 26 | if err != nil { 27 | panic(err) 28 | } 29 | defer producer.Close() 30 | 31 | eventProducer := services.NewEventProducer(producer) 32 | accountService := services.NewAccountService(eventProducer) 33 | accountController := controllers.NewAccountController(accountService) 34 | 35 | app := fiber.New() 36 | 37 | app.Post("/openAccount", accountController.OpenAccount) 38 | app.Post("/depositFund", accountController.DepositFund) 39 | app.Post("/withdrawFund", accountController.WithdrawFund) 40 | app.Post("/closeAccount", accountController.CloseAccount) 41 | 42 | app.Listen(":8000") 43 | } 44 | 45 | // func main() { 46 | 47 | // servers := []string{"codebangkok.com:9092"} 48 | 49 | // producer, err := sarama.NewSyncProducer(servers, nil) 50 | // if err != nil { 51 | // panic(err) 52 | // } 53 | // defer producer.Close() 54 | 55 | // msg := sarama.ProducerMessage{ 56 | // Topic: "bondhello", 57 | // Value: sarama.StringEncoder("Hello World"), 58 | // } 59 | 60 | // p, o, err := producer.SendMessage(&msg) 61 | // if err != nil { 62 | // panic(err) 63 | // } 64 | // fmt.Printf("partition=%v, offset=%v", p, o) 65 | // } 66 | -------------------------------------------------------------------------------- /project/gokafka/producer/services/account.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "errors" 5 | "events" 6 | "log" 7 | "producer/commands" 8 | 9 | "github.com/google/uuid" 10 | ) 11 | 12 | type AccountService interface { 13 | OpenAccount(command commands.OpenAccountCommand) (id string, err error) 14 | DepositFund(command commands.DepositFundCommand) error 15 | WithdrawFund(command commands.WithdrawFundCommand) error 16 | CloseAccount(command commands.CloseAccountCommand) error 17 | } 18 | 19 | type accountService struct { 20 | eventProducer EventProducer 21 | } 22 | 23 | func NewAccountService(eventProducer EventProducer) AccountService { 24 | return accountService{eventProducer} 25 | } 26 | 27 | func (obj accountService) OpenAccount(command commands.OpenAccountCommand) (id string, err error) { 28 | 29 | if command.AccountHolder == "" || command.AccountType == 0 || command.OpeningBalance == 0 { 30 | return "", errors.New("bad request") 31 | } 32 | 33 | event := events.OpenAccountEvent{ 34 | ID: uuid.NewString(), 35 | AccountHolder: command.AccountHolder, 36 | AccountType: command.AccountType, 37 | OpeningBalance: command.OpeningBalance, 38 | } 39 | 40 | log.Printf("%#v", event) 41 | return event.ID, obj.eventProducer.Produce(event) 42 | } 43 | 44 | func (obj accountService) DepositFund(command commands.DepositFundCommand) error { 45 | if command.ID == "" || command.Amount == 0 { 46 | return errors.New("bad request") 47 | } 48 | 49 | event := events.DepositFundEvent{ 50 | ID: command.ID, 51 | Amount: command.Amount, 52 | } 53 | 54 | log.Printf("%#v", event) 55 | return obj.eventProducer.Produce(event) 56 | } 57 | 58 | func (obj accountService) WithdrawFund(command commands.WithdrawFundCommand) error { 59 | if command.ID == "" || command.Amount == 0 { 60 | return errors.New("bad request") 61 | } 62 | 63 | event := events.WithdrawFundEvent{ 64 | ID: command.ID, 65 | Amount: command.Amount, 66 | } 67 | 68 | log.Printf("%#v", event) 69 | return obj.eventProducer.Produce(event) 70 | } 71 | 72 | func (obj accountService) CloseAccount(command commands.CloseAccountCommand) error { 73 | if command.ID == "" { 74 | return errors.New("bad request") 75 | } 76 | 77 | event := events.CloseAccountEvent{ 78 | ID: command.ID, 79 | } 80 | 81 | log.Printf("%#v", event) 82 | return obj.eventProducer.Produce(event) 83 | } 84 | -------------------------------------------------------------------------------- /project/gokafka/producer/services/producer.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "encoding/json" 5 | "events" 6 | "reflect" 7 | 8 | "github.com/Shopify/sarama" 9 | ) 10 | 11 | type EventProducer interface { 12 | Produce(event events.Event) error 13 | } 14 | 15 | type eventProducer struct { 16 | producer sarama.SyncProducer 17 | } 18 | 19 | func NewEventProducer(producer sarama.SyncProducer) EventProducer { 20 | return eventProducer{producer} 21 | } 22 | 23 | func (obj eventProducer) Produce(event events.Event) error { 24 | topic := reflect.TypeOf(event).Name() 25 | 26 | value, err := json.Marshal(event) 27 | if err != nil { 28 | return err 29 | } 30 | 31 | msg := sarama.ProducerMessage{ 32 | Topic: topic, 33 | Value: sarama.ByteEncoder(value), 34 | } 35 | 36 | _, _, err = obj.producer.SendMessage(&msg) 37 | if err != nil { 38 | return err 39 | } 40 | 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /project/gokafka/server/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | services: 3 | 4 | zookeeper: 5 | image: zookeeper 6 | container_name: zookeeper 7 | volumes: 8 | - ./zookeeper:/data 9 | 10 | kafka: 11 | image: bitnami/kafka 12 | container_name: kafka 13 | ports: 14 | - 9092:9092 15 | volumes: 16 | - ./kafka:/bitnami/kafka/data 17 | environment: 18 | - ALLOW_PLAINTEXT_LISTENER=yes 19 | - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092 20 | - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 21 | - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181 22 | depends_on: 23 | - zookeeper 24 | 25 | mysql: 26 | image: mariadb 27 | container_name: mysql 28 | environment: 29 | - MARIADB_ROOT_PASSWORD=P@ssw0rd 30 | - MARIADB_DATABASE=micro 31 | - MARIADB_USER=bond 32 | - MARIADB_PASSWORD=P@ssw0rd 33 | ports: 34 | - 3306:3306 35 | volumes: 36 | - ./mysql:/var/lib/mysql -------------------------------------------------------------------------------- /project/goredis/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | services: 3 | redis: 4 | image: redis 5 | container_name: redis 6 | ports: 7 | - 6379:6379 8 | volumes: 9 | - ./data/redis:/data 10 | - ./config/redis.conf:/redis.conf 11 | command: redis-server /redis.conf 12 | 13 | k6: 14 | image: loadimpact/k6 15 | container_name: k6 16 | environment: 17 | - K6_OUT=influxdb=http://influxdb:8086/k6 18 | volumes: 19 | - ./scripts:/scripts 20 | 21 | influxdb: 22 | image: influxdb:1.8.10 23 | container_name: influxdb 24 | environment: 25 | - INFLUXDB_DB=k6 26 | - INFLUXDB_HTTP_MAX_BODY_SIZE=0 27 | ports: 28 | - 8086:8086 29 | volumes: 30 | - ./data/influxdb:/var/lib/influxdb 31 | 32 | grafana: 33 | image: grafana/grafana 34 | container_name: grafana 35 | environment: 36 | - GF_AUTH_ANONYMOUS_ENABLED=true 37 | - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin 38 | ports: 39 | - 3000:3000 40 | volumes: 41 | - ./data/grafana:/var/lib/grafana 42 | 43 | mariadb: 44 | image: mariadb 45 | container_name: mariadb 46 | environment: 47 | - MARIADB_ROOT_PASSWORD=P@ssw0rd 48 | - MARIADB_DATABASE=infinitas 49 | ports: 50 | - 3306:3306 51 | volumes: 52 | - ./data/mariadb:/var/lib/mysql 53 | -------------------------------------------------------------------------------- /project/goredis/go.mod: -------------------------------------------------------------------------------- 1 | module goredis 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/go-redis/redis/v8 v8.11.4 7 | github.com/gofiber/fiber/v2 v2.21.0 8 | gorm.io/driver/mysql v1.1.2 9 | gorm.io/gorm v1.21.16 10 | ) 11 | 12 | require ( 13 | github.com/andybalholm/brotli v1.0.2 // indirect 14 | github.com/cespare/xxhash/v2 v2.1.2 // indirect 15 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 16 | github.com/go-sql-driver/mysql v1.6.0 // indirect 17 | github.com/jinzhu/inflection v1.0.0 // indirect 18 | github.com/jinzhu/now v1.1.2 // indirect 19 | github.com/klauspost/compress v1.13.4 // indirect 20 | github.com/valyala/bytebufferpool v1.0.0 // indirect 21 | github.com/valyala/fasthttp v1.31.0 // indirect 22 | github.com/valyala/tcplisten v1.0.0 // indirect 23 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect 24 | ) 25 | -------------------------------------------------------------------------------- /project/goredis/go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E= 2 | github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 3 | github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= 4 | github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 5 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= 8 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 9 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 10 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 11 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 12 | github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg= 13 | github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= 14 | github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= 15 | github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 16 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 17 | github.com/gofiber/fiber/v2 v2.21.0 h1:tdRNrgqWqcHWBwE3o51oAleEVsil4Ro02zd2vMEuP4Q= 18 | github.com/gofiber/fiber/v2 v2.21.0/go.mod h1:MR1usVH3JHYRyQwMe2eZXRSZHRX38fkV+A7CPB+DlDQ= 19 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 20 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 21 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 22 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 23 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 24 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 25 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 26 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 27 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 28 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 29 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 30 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 31 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 32 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 33 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 34 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 35 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 36 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 37 | github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= 38 | github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 39 | github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= 40 | github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 41 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 42 | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= 43 | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 44 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 45 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 46 | github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= 47 | github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= 48 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 49 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 50 | github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= 51 | github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= 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/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 55 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 56 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 57 | github.com/valyala/fasthttp v1.31.0 h1:lrauRLII19afgCs2fnWRJ4M5IkV0lo2FqA61uGkNBfE= 58 | github.com/valyala/fasthttp v1.31.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= 59 | github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= 60 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 61 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 62 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 63 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 64 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 65 | golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 66 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 67 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 68 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 69 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 70 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 71 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 72 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 73 | golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= 74 | golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= 75 | golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 76 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 77 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 78 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 79 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 80 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 81 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 82 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 83 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 84 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 85 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 86 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 87 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 88 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 89 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 90 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= 91 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 92 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 93 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 94 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 95 | golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 96 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 97 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 98 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 99 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 100 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 101 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 102 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 103 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 104 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 105 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 106 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 107 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 108 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 109 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 110 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 111 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 112 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 113 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 114 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 115 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 116 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 117 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 118 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 119 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 120 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 121 | gorm.io/driver/mysql v1.1.2 h1:OofcyE2lga734MxwcCW9uB4mWNXMr50uaGRVwQL2B0M= 122 | gorm.io/driver/mysql v1.1.2/go.mod h1:4P/X9vSc3WTrhTLZ259cpFd6xKNYiSSdSZngkSBGIMM= 123 | gorm.io/gorm v1.21.12/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= 124 | gorm.io/gorm v1.21.16 h1:YBIQLtP5PLfZQz59qfrq7xbrK7KWQ+JsXXCH/THlMqs= 125 | gorm.io/gorm v1.21.16/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= 126 | -------------------------------------------------------------------------------- /project/goredis/handlers/catalog.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import "github.com/gofiber/fiber/v2" 4 | 5 | type CatalogHandler interface { 6 | GetProducts(c *fiber.Ctx) error 7 | } 8 | -------------------------------------------------------------------------------- /project/goredis/handlers/catalog.handler.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "goredis/services" 5 | 6 | "github.com/gofiber/fiber/v2" 7 | ) 8 | 9 | type catalogHandler struct { 10 | catalogSrv services.CatalogService 11 | } 12 | 13 | func NewCatalogHandler(catalogSrv services.CatalogService) CatalogHandler { 14 | return catalogHandler{catalogSrv} 15 | } 16 | 17 | func (h catalogHandler) GetProducts(c *fiber.Ctx) error { 18 | 19 | products, err := h.catalogSrv.GetProducts() 20 | if err != nil { 21 | return err 22 | } 23 | 24 | response := fiber.Map{ 25 | "status": "ok", 26 | "products": products, 27 | } 28 | 29 | return c.JSON(response) 30 | } 31 | -------------------------------------------------------------------------------- /project/goredis/handlers/catalog_redis.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "goredis/services" 8 | "time" 9 | 10 | "github.com/go-redis/redis/v8" 11 | "github.com/gofiber/fiber/v2" 12 | ) 13 | 14 | type catalogHandlerRedis struct { 15 | catalogSrv services.CatalogService 16 | redisClient *redis.Client 17 | } 18 | 19 | func NewCatalogHanlderRedis(catalogSrv services.CatalogService, redisClient *redis.Client) CatalogHandler { 20 | return catalogHandlerRedis{catalogSrv, redisClient} 21 | } 22 | 23 | func (h catalogHandlerRedis) GetProducts(c *fiber.Ctx) error { 24 | 25 | key := "handler::GetProducts" 26 | 27 | // Redis GET 28 | if responseJson, err := h.redisClient.Get(context.Background(), key).Result(); err == nil { 29 | fmt.Println("redis") 30 | c.Set("Content-Type", "application/json") 31 | return c.SendString(responseJson) 32 | } 33 | 34 | // Service 35 | products, err := h.catalogSrv.GetProducts() 36 | if err != nil { 37 | return err 38 | } 39 | 40 | response := fiber.Map{ 41 | "status": "ok", 42 | "products": products, 43 | } 44 | 45 | // Redis SET 46 | if data, err := json.Marshal(response); err == nil { 47 | h.redisClient.Set(context.Background(), key, string(data), time.Second*10) 48 | } 49 | 50 | fmt.Println("database") 51 | return c.JSON(response) 52 | } 53 | -------------------------------------------------------------------------------- /project/goredis/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "goredis/handlers" 5 | "goredis/repositories" 6 | "goredis/services" 7 | 8 | "github.com/go-redis/redis/v8" 9 | "github.com/gofiber/fiber/v2" 10 | "gorm.io/driver/mysql" 11 | "gorm.io/gorm" 12 | ) 13 | 14 | func main() { 15 | db := initDatabase() 16 | redisClient := initRedis() 17 | _ = redisClient 18 | 19 | productRepo := repositories.NewProductRepositoryDB(db) 20 | productService := services.NewCatalogServiceRedis(productRepo, redisClient) 21 | productHandler := handlers.NewCatalogHandler(productService) 22 | 23 | app := fiber.New() 24 | app.Get("/products", productHandler.GetProducts) 25 | app.Listen(":8000") 26 | 27 | } 28 | 29 | func initDatabase() *gorm.DB { 30 | dial := mysql.Open("root:P@ssw0rd@tcp(localhost:3306)/infinitas") 31 | db, err := gorm.Open(dial, &gorm.Config{}) 32 | if err != nil { 33 | panic(err) 34 | } 35 | return db 36 | } 37 | 38 | func initRedis() *redis.Client { 39 | return redis.NewClient(&redis.Options{ 40 | Addr: "localhost:6379", 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /project/goredis/repositories/product.go: -------------------------------------------------------------------------------- 1 | package repositories 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | 8 | "gorm.io/gorm" 9 | ) 10 | 11 | type product struct { 12 | ID int 13 | Name string 14 | Quantity int 15 | } 16 | 17 | type ProductRepository interface { 18 | GetProducts() ([]product, error) 19 | } 20 | 21 | func mockData(db *gorm.DB) error { 22 | 23 | var count int64 24 | db.Model(&product{}).Count(&count) 25 | if count > 0 { 26 | return nil 27 | } 28 | 29 | seed := rand.NewSource(time.Now().UnixNano()) 30 | random := rand.New(seed) 31 | 32 | products := []product{} 33 | for i := 0; i < 5000; i++ { 34 | products = append(products, product{ 35 | Name: fmt.Sprintf("Product%v", i+1), 36 | Quantity: random.Intn(100), 37 | }) 38 | } 39 | return db.Create(&products).Error 40 | } 41 | -------------------------------------------------------------------------------- /project/goredis/repositories/product_db.go: -------------------------------------------------------------------------------- 1 | package repositories 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | ) 6 | 7 | type productRepositoryDB struct { 8 | db *gorm.DB 9 | } 10 | 11 | func NewProductRepositoryDB(db *gorm.DB) ProductRepository { 12 | db.AutoMigrate(&product{}) 13 | mockData(db) 14 | return productRepositoryDB{db} 15 | } 16 | 17 | func (r productRepositoryDB) GetProducts() (products []product, err error) { 18 | err = r.db.Order("quantity desc").Limit(30).Find(&products).Error 19 | return products, err 20 | } 21 | -------------------------------------------------------------------------------- /project/goredis/repositories/product_redis.go: -------------------------------------------------------------------------------- 1 | package repositories 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "time" 8 | 9 | "github.com/go-redis/redis/v8" 10 | "gorm.io/gorm" 11 | ) 12 | 13 | type productRepositoryRedis struct { 14 | db *gorm.DB 15 | redisClient *redis.Client 16 | } 17 | 18 | func NewProductRepositoryRedis(db *gorm.DB, redisClient *redis.Client) ProductRepository { 19 | db.AutoMigrate(&product{}) 20 | mockData(db) 21 | return productRepositoryRedis{db, redisClient} 22 | } 23 | 24 | func (r productRepositoryRedis) GetProducts() (products []product, err error) { 25 | 26 | key := "repository::GetProducts" 27 | 28 | // Redis Get 29 | productsJson, err := r.redisClient.Get(context.Background(), key).Result() 30 | if err == nil { 31 | err = json.Unmarshal([]byte(productsJson), &products) 32 | if err == nil { 33 | fmt.Println("redis") 34 | return products, nil 35 | } 36 | } 37 | 38 | // Database 39 | err = r.db.Order("quantity desc").Limit(30).Find(&products).Error 40 | if err != nil { 41 | return nil, err 42 | } 43 | 44 | // Redis Set 45 | data, err := json.Marshal(products) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | err = r.redisClient.Set(context.Background(), key, string(data), time.Second*10).Err() 51 | if err != nil { 52 | return nil, err 53 | } 54 | 55 | fmt.Println("database") 56 | return products, nil 57 | } 58 | -------------------------------------------------------------------------------- /project/goredis/scripts/test.js: -------------------------------------------------------------------------------- 1 | import http from 'k6/http' 2 | 3 | export let options = { 4 | vus: 5, 5 | duration: '5s' 6 | } 7 | 8 | export default function() { 9 | http.get('http://host.docker.internal:8000/products') 10 | } -------------------------------------------------------------------------------- /project/goredis/services/catalog.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | type Product struct { 4 | ID int `json:"id"` 5 | Name string `json:"name"` 6 | Quantity int `json:"quantity"` 7 | } 8 | 9 | type CatalogService interface { 10 | GetProducts() ([]Product, error) 11 | } 12 | -------------------------------------------------------------------------------- /project/goredis/services/catalog_redis.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "goredis/repositories" 8 | "time" 9 | 10 | "github.com/go-redis/redis/v8" 11 | ) 12 | 13 | type catalogServiceRedis struct { 14 | productRepo repositories.ProductRepository 15 | redisClient *redis.Client 16 | } 17 | 18 | func NewCatalogServiceRedis(productRepo repositories.ProductRepository, redisClient *redis.Client) CatalogService { 19 | return catalogServiceRedis{productRepo, redisClient} 20 | } 21 | 22 | func (s catalogServiceRedis) GetProducts() (products []Product, err error) { 23 | 24 | key := "service::GetProducts" 25 | 26 | //Redis GET 27 | if productJson, err := s.redisClient.Get(context.Background(), key).Result(); err == nil { 28 | if json.Unmarshal([]byte(productJson), &products) == nil { 29 | fmt.Println("redis") 30 | return products, nil 31 | } 32 | } 33 | 34 | // Repository 35 | productsDB, err := s.productRepo.GetProducts() 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | for _, p := range productsDB { 41 | products = append(products, Product{ 42 | ID: p.ID, 43 | Name: p.Name, 44 | Quantity: p.Quantity, 45 | }) 46 | } 47 | 48 | // Redis SET 49 | if data, err := json.Marshal(products); err == nil { 50 | s.redisClient.Set(context.Background(), key, string(data), time.Second*10) 51 | } 52 | 53 | fmt.Println("database") 54 | return products, nil 55 | } 56 | -------------------------------------------------------------------------------- /project/goredis/services/catalog_service.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import "goredis/repositories" 4 | 5 | type catalogService struct { 6 | productRepo repositories.ProductRepository 7 | } 8 | 9 | func NewCatalogService(productRepo repositories.ProductRepository) CatalogService { 10 | return catalogService{productRepo} 11 | } 12 | 13 | func (s catalogService) GetProducts() (products []Product, err error) { 14 | 15 | productsDB, err := s.productRepo.GetProducts() 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | for _, p := range productsDB { 21 | products = append(products, Product{ 22 | ID: p.ID, 23 | Name: p.Name, 24 | Quantity: p.Quantity, 25 | }) 26 | } 27 | 28 | return products, nil 29 | } 30 | -------------------------------------------------------------------------------- /project/gotest/go.mod: -------------------------------------------------------------------------------- 1 | module gotest 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/gofiber/fiber/v2 v2.22.0 7 | github.com/stretchr/testify v1.7.0 8 | ) 9 | 10 | require ( 11 | github.com/andybalholm/brotli v1.0.2 // indirect 12 | github.com/davecgh/go-spew v1.1.0 // indirect 13 | github.com/klauspost/compress v1.13.4 // indirect 14 | github.com/pmezard/go-difflib v1.0.0 // indirect 15 | github.com/stretchr/objx v0.1.0 // indirect 16 | github.com/valyala/bytebufferpool v1.0.0 // indirect 17 | github.com/valyala/fasthttp v1.31.0 // indirect 18 | github.com/valyala/tcplisten v1.0.0 // indirect 19 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect 20 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect 21 | ) 22 | -------------------------------------------------------------------------------- /project/gotest/go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E= 2 | github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 3 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/gofiber/fiber/v2 v2.22.0 h1:+iyKK4ooDH6z0lAHdaWO1AFIB/DZ9AVo6vz8VZIA0EU= 6 | github.com/gofiber/fiber/v2 v2.22.0/go.mod h1:MR1usVH3JHYRyQwMe2eZXRSZHRX38fkV+A7CPB+DlDQ= 7 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 8 | github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= 9 | github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 10 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 11 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 12 | github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= 13 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 14 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 15 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 16 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 17 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 18 | github.com/valyala/fasthttp v1.31.0 h1:lrauRLII19afgCs2fnWRJ4M5IkV0lo2FqA61uGkNBfE= 19 | github.com/valyala/fasthttp v1.31.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= 20 | github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= 21 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 22 | golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 23 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 24 | golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 25 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 26 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 27 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= 28 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 29 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 30 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 31 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 32 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 33 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 34 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 35 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 36 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 37 | -------------------------------------------------------------------------------- /project/gotest/handlers/promotion.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "gotest/services" 5 | "strconv" 6 | 7 | "github.com/gofiber/fiber/v2" 8 | ) 9 | 10 | type PromotionHandler interface { 11 | CalculateDiscount(c *fiber.Ctx) error 12 | } 13 | 14 | type promotionHandler struct { 15 | promoService services.PromotionService 16 | } 17 | 18 | func NewPromotionHandler(promoService services.PromotionService) PromotionHandler { 19 | return promotionHandler{promoService: promoService} 20 | } 21 | 22 | func (h promotionHandler) CalculateDiscount(c *fiber.Ctx) error { 23 | //http://localhost:8000/calculate?amount=100 24 | 25 | amountStr := c.Query("amount") 26 | amount, err := strconv.Atoi(amountStr) 27 | if err != nil { 28 | return c.SendStatus(fiber.StatusBadRequest) 29 | } 30 | 31 | discount, err := h.promoService.CalculateDiscount(amount) 32 | if err != nil { 33 | return c.SendStatus(fiber.StatusNotFound) 34 | } 35 | 36 | return c.SendString(strconv.Itoa(discount)) 37 | } 38 | -------------------------------------------------------------------------------- /project/gotest/handlers/promotion_integration_test.go: -------------------------------------------------------------------------------- 1 | //go:build integration 2 | 3 | package handlers_test 4 | 5 | import ( 6 | "fmt" 7 | "gotest/handlers" 8 | "gotest/repositories" 9 | "gotest/services" 10 | "io" 11 | "net/http/httptest" 12 | "strconv" 13 | "testing" 14 | 15 | "github.com/gofiber/fiber/v2" 16 | "github.com/stretchr/testify/assert" 17 | ) 18 | 19 | func TestPromotionCalculateDiscountIntegrationService(t *testing.T) { 20 | 21 | t.Run("success", func(t *testing.T) { 22 | amount := 100 23 | expected := 80 24 | 25 | promoRepo := repositories.NewPromotionRepositoryMock() 26 | promoRepo.On("GetPromotion").Return(repositories.Promotion{ 27 | ID: 1, 28 | PurchaseMin: 100, 29 | DiscountPercent: 20, 30 | }, nil) 31 | 32 | promoService := services.NewPromotionService(promoRepo) 33 | promoHandler := handlers.NewPromotionHandler(promoService) 34 | 35 | //http://localhost:8000/calculate?amount=100 36 | app := fiber.New() 37 | app.Get("/calculate", promoHandler.CalculateDiscount) 38 | 39 | req := httptest.NewRequest("GET", fmt.Sprintf("/calculate?amount=%v", amount), nil) 40 | 41 | //Act 42 | res, _ := app.Test(req) 43 | defer res.Body.Close() 44 | 45 | //Assert 46 | if assert.Equal(t, fiber.StatusOK, res.StatusCode) { 47 | body, _ := io.ReadAll(res.Body) 48 | assert.Equal(t, strconv.Itoa(expected), string(body)) 49 | } 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /project/gotest/handlers/promotion_test.go: -------------------------------------------------------------------------------- 1 | //go:build unit 2 | 3 | package handlers_test 4 | 5 | import ( 6 | "fmt" 7 | "gotest/handlers" 8 | "gotest/services" 9 | "io" 10 | "net/http/httptest" 11 | "strconv" 12 | "testing" 13 | 14 | "github.com/gofiber/fiber/v2" 15 | "github.com/stretchr/testify/assert" 16 | ) 17 | 18 | func TestPromotionCalculateDiscount(t *testing.T) { 19 | t.Run("success", func(t *testing.T) { 20 | 21 | //Arrange 22 | amount := 100 23 | expected := 80 24 | 25 | promoService := services.NewPromotionServiceMock() 26 | promoService.On("CalculateDiscount", amount).Return(expected, nil) 27 | 28 | promoHandler := handlers.NewPromotionHandler(promoService) 29 | 30 | //http://localhost:8000/calculate?amount=100 31 | app := fiber.New() 32 | app.Get("/calculate", promoHandler.CalculateDiscount) 33 | 34 | req := httptest.NewRequest("GET", fmt.Sprintf("/calculate?amount=%v", amount), nil) 35 | 36 | //Act 37 | res, _ := app.Test(req) 38 | defer res.Body.Close() 39 | 40 | //Assert 41 | if assert.Equal(t, fiber.StatusOK, res.StatusCode) { 42 | body, _ := io.ReadAll(res.Body) 43 | assert.Equal(t, strconv.Itoa(expected), string(body)) 44 | } 45 | 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /project/gotest/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/stretchr/testify/mock" 8 | ) 9 | 10 | func main() { 11 | // fmt.Println("Hello World") 12 | 13 | c := CustomerRepositoryMock{} 14 | c.On("GetCustomer", 1).Return("Bond", 18, nil) 15 | c.On("GetCustomer", 2).Return("", 0, errors.New("not found")) 16 | 17 | //===== 18 | name, age, err := c.GetCustomer(2) 19 | if err != nil { 20 | fmt.Println(err) 21 | return 22 | } 23 | fmt.Println(name, age) 24 | } 25 | 26 | type CustomerReposity interface { 27 | GetCustomer(id int) (name string, age int, err error) 28 | Hello() 29 | } 30 | 31 | type CustomerRepositoryMock struct { 32 | mock.Mock 33 | } 34 | 35 | func (m *CustomerRepositoryMock) GetCustomer(id int) (name string, age int, err error) { 36 | args := m.Called(id) 37 | return args.String(0), args.Int(1), args.Error(2) 38 | } 39 | 40 | func (m *CustomerRepositoryMock) Hello() { 41 | println(m) 42 | } 43 | -------------------------------------------------------------------------------- /project/gotest/repositories/promotion.go: -------------------------------------------------------------------------------- 1 | package repositories 2 | 3 | type PromotionRepository interface { 4 | GetPromotion() (Promotion, error) 5 | } 6 | 7 | type Promotion struct { 8 | ID int 9 | PurchaseMin int 10 | DiscountPercent int 11 | } 12 | -------------------------------------------------------------------------------- /project/gotest/repositories/promotion_mock.go: -------------------------------------------------------------------------------- 1 | package repositories 2 | 3 | import "github.com/stretchr/testify/mock" 4 | 5 | type promotionRepositoryMock struct { 6 | mock.Mock 7 | } 8 | 9 | func NewPromotionRepositoryMock() *promotionRepositoryMock { 10 | return &promotionRepositoryMock{} 11 | } 12 | 13 | func (m *promotionRepositoryMock) GetPromotion() (Promotion, error) { 14 | args := m.Called() 15 | return args.Get(0).(Promotion), args.Error(1) 16 | } 17 | -------------------------------------------------------------------------------- /project/gotest/services/errs.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrZeroAmount = errors.New("purchase amount could not be zero") 7 | ErrRepository = errors.New("repository error") 8 | ) 9 | -------------------------------------------------------------------------------- /project/gotest/services/grade.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | func CheckGrade(score int) string { 4 | switch { 5 | case score >= 80: 6 | return "A" 7 | case score >= 70: 8 | return "B" 9 | case score >= 60: 10 | return "C" 11 | case score >= 50: 12 | return "D" 13 | default: 14 | return "F" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /project/gotest/services/grade_test.go: -------------------------------------------------------------------------------- 1 | package services_test 2 | 3 | import ( 4 | "fmt" 5 | "gotest/services" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestCheckGrade(t *testing.T) { 12 | 13 | type testCase struct { 14 | name string 15 | score int 16 | expected string 17 | } 18 | 19 | cases := []testCase{ 20 | {name: "a", score: 80, expected: "A"}, 21 | {name: "b", score: 70, expected: "B"}, 22 | {name: "c", score: 60, expected: "C"}, 23 | {name: "d", score: 50, expected: "D"}, 24 | {name: "f", score: 0, expected: "F"}, 25 | } 26 | 27 | for _, c := range cases { 28 | t.Run(c.name, func(t *testing.T) { 29 | grade := services.CheckGrade(c.score) 30 | 31 | assert.Equal(t, c.expected, grade) 32 | // if grade != c.expected { 33 | // t.Errorf("got %v expected %v", grade, c.expected) 34 | // } 35 | }) 36 | } 37 | 38 | } 39 | 40 | func BenchmarkCheckGrade(b *testing.B) { 41 | 42 | for i := 0; i < b.N; i++ { 43 | services.CheckGrade(80) 44 | } 45 | 46 | } 47 | 48 | func ExampleCheckGrade() { 49 | grade := services.CheckGrade(80) 50 | fmt.Println(grade) 51 | // Output: A 52 | } 53 | -------------------------------------------------------------------------------- /project/gotest/services/promotion.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "gotest/repositories" 5 | ) 6 | 7 | type PromotionService interface { 8 | CalculateDiscount(amount int) (int, error) 9 | } 10 | 11 | type promotionService struct { 12 | promoRepo repositories.PromotionRepository 13 | } 14 | 15 | func NewPromotionService(promoRepo repositories.PromotionRepository) PromotionService { 16 | return promotionService{promoRepo: promoRepo} 17 | } 18 | 19 | func (s promotionService) CalculateDiscount(amount int) (int, error) { 20 | 21 | if amount <= 0 { 22 | return 0, ErrZeroAmount 23 | } 24 | 25 | promotion, err := s.promoRepo.GetPromotion() 26 | if err != nil { 27 | return 0, ErrRepository 28 | } 29 | 30 | if amount >= promotion.PurchaseMin { 31 | return amount - (promotion.DiscountPercent * amount / 100), nil 32 | } 33 | 34 | return amount, nil 35 | } 36 | -------------------------------------------------------------------------------- /project/gotest/services/promotion_mock.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import "github.com/stretchr/testify/mock" 4 | 5 | type promotionServiceMock struct { 6 | mock.Mock 7 | } 8 | 9 | func NewPromotionServiceMock() *promotionServiceMock { 10 | return &promotionServiceMock{} 11 | } 12 | 13 | func (m *promotionServiceMock) CalculateDiscount(amount int) (int, error) { 14 | args := m.Called(amount) 15 | return args.Int(0), args.Error(1) 16 | } 17 | -------------------------------------------------------------------------------- /project/gotest/services/promotion_test.go: -------------------------------------------------------------------------------- 1 | package services_test 2 | 3 | import ( 4 | "errors" 5 | "gotest/repositories" 6 | "gotest/services" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestPromotionCalculateDiscount(t *testing.T) { 13 | 14 | type testCase struct { 15 | name string 16 | purchaseMin int 17 | discountPercent int 18 | amount int 19 | expected int 20 | } 21 | 22 | cases := []testCase{ 23 | {name: "applied 100", purchaseMin: 100, discountPercent: 20, amount: 100, expected: 80}, 24 | {name: "applied 200", purchaseMin: 100, discountPercent: 20, amount: 200, expected: 160}, 25 | {name: "applied 300", purchaseMin: 100, discountPercent: 20, amount: 300, expected: 240}, 26 | {name: "not applied 50", purchaseMin: 100, discountPercent: 20, amount: 50, expected: 50}, 27 | } 28 | 29 | for _, c := range cases { 30 | t.Run(c.name, func(t *testing.T) { 31 | //Arrage 32 | promoRepo := repositories.NewPromotionRepositoryMock() 33 | promoRepo.On("GetPromotion").Return(repositories.Promotion{ 34 | ID: 1, 35 | PurchaseMin: c.purchaseMin, 36 | DiscountPercent: c.discountPercent, 37 | }, nil) 38 | 39 | promoService := services.NewPromotionService(promoRepo) 40 | 41 | //Act 42 | discount, _ := promoService.CalculateDiscount(c.amount) 43 | expected := c.expected 44 | 45 | //Assert 46 | assert.Equal(t, expected, discount) 47 | }) 48 | } 49 | 50 | t.Run("purchase amount zero", func(t *testing.T) { 51 | //Arrage 52 | promoRepo := repositories.NewPromotionRepositoryMock() 53 | promoRepo.On("GetPromotion").Return(repositories.Promotion{ 54 | ID: 1, 55 | PurchaseMin: 100, 56 | DiscountPercent: 20, 57 | }, nil) 58 | 59 | promoService := services.NewPromotionService(promoRepo) 60 | 61 | //Act 62 | _, err := promoService.CalculateDiscount(0) 63 | 64 | //Assert 65 | assert.ErrorIs(t, err, services.ErrZeroAmount) 66 | promoRepo.AssertNotCalled(t, "GetPromotion") 67 | }) 68 | 69 | t.Run("repository error", func(t *testing.T) { 70 | //Arrage 71 | promoRepo := repositories.NewPromotionRepositoryMock() 72 | promoRepo.On("GetPromotion").Return(repositories.Promotion{}, errors.New("")) 73 | 74 | promoService := services.NewPromotionService(promoRepo) 75 | 76 | //Act 77 | _, err := promoService.CalculateDiscount(100) 78 | 79 | //Assert 80 | assert.ErrorIs(t, err, services.ErrRepository) 81 | }) 82 | 83 | } 84 | -------------------------------------------------------------------------------- /project/orm/go.mod: -------------------------------------------------------------------------------- 1 | module orm 2 | 3 | go 1.16 4 | 5 | require ( 6 | gorm.io/driver/mysql v1.1.1 7 | gorm.io/gorm v1.21.11 8 | ) 9 | -------------------------------------------------------------------------------- /project/orm/go.sum: -------------------------------------------------------------------------------- 1 | github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= 2 | github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 3 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 4 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 5 | github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= 6 | github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 7 | gorm.io/driver/mysql v1.1.1 h1:yr1bpyqiwuSPJ4aGGUX9nu46RHXlF8RASQVb1QQNcvo= 8 | gorm.io/driver/mysql v1.1.1/go.mod h1:KdrTanmfLPPyAOeYGyG+UpDys7/7eeWT1zCq+oekYnU= 9 | gorm.io/gorm v1.21.9/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= 10 | gorm.io/gorm v1.21.11 h1:CxkXW6Cc+VIBlL8yJEHq+Co4RYXdSLiMKNvgoZPjLK4= 11 | gorm.io/gorm v1.21.11/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= 12 | -------------------------------------------------------------------------------- /project/orm/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "database/sql" 6 | "fmt" 7 | "time" 8 | 9 | "gorm.io/driver/mysql" 10 | "gorm.io/gorm" 11 | "gorm.io/gorm/clause" 12 | "gorm.io/gorm/logger" 13 | ) 14 | 15 | type SqlLogger struct { 16 | logger.Interface 17 | } 18 | 19 | func (l SqlLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) { 20 | sql, _ := fc() 21 | fmt.Printf("%v\n=============================\n", sql) 22 | } 23 | 24 | var db *gorm.DB 25 | 26 | func main() { 27 | dsn := "root:P@ssw0rd@tcp(13.76.163.73:3306)/bond?parseTime=true" 28 | dial := mysql.Open(dsn) 29 | 30 | var err error 31 | db, err = gorm.Open(dial, &gorm.Config{ 32 | Logger: &SqlLogger{}, 33 | DryRun: false, 34 | }) 35 | if err != nil { 36 | panic(err) 37 | } 38 | 39 | //db.AutoMigrate(Gender{}, Test{}, Customer{}) 40 | //CreateGender("xxxx") 41 | //GetGenders() 42 | //GetGender(10) 43 | //GetGenderByName("Male") 44 | //UpdateGender(4, "xxxcx") 45 | //DeleteGender(4) 46 | // CreateTest(0, "Test1") 47 | // CreateTest(0, "Test2") 48 | //CreateTest(0, "Test3") 49 | 50 | //DeleteTest(2) 51 | //GetTests() 52 | 53 | //db.Migrator().CreateTable(Customer{}) 54 | 55 | //CreateCustomer("Note", 2) 56 | 57 | //UpdateGender2(1, "ชาย") 58 | //GetCustomers() 59 | } 60 | 61 | func GetCustomers() { 62 | customers := []Customer{} 63 | tx := db.Preload(clause.Associations).Find(&customers) 64 | if tx.Error != nil { 65 | fmt.Println(tx.Error) 66 | return 67 | } 68 | for _, customer := range customers { 69 | fmt.Printf("%v|%v|%v\n", customer.ID, customer.Name, customer.Gender.Name) 70 | } 71 | } 72 | 73 | func CreateCustomer(name string, genderID uint) { 74 | customer := Customer{Name: name, GenderID: genderID} 75 | tx := db.Create(&customer) 76 | if tx.Error != nil { 77 | fmt.Println(tx.Error) 78 | return 79 | } 80 | fmt.Println(customer) 81 | } 82 | 83 | type Customer struct { 84 | ID uint 85 | Name string 86 | Gender Gender 87 | GenderID uint 88 | } 89 | 90 | func CreateTest(code uint, name string) { 91 | test := Test{Code: code, Name: name} 92 | db.Create(&test) 93 | } 94 | 95 | func GetTests() { 96 | tests := []Test{} 97 | db.Find(&tests) 98 | for _, t := range tests { 99 | fmt.Printf("%v|%v\n", t.ID, t.Name) 100 | } 101 | } 102 | 103 | func DeleteTest(id uint) { 104 | db.Unscoped().Delete(&Test{}, id) 105 | } 106 | 107 | func DeleteGender(id uint) { 108 | tx := db.Delete(&Gender{}, id) 109 | if tx.Error != nil { 110 | fmt.Println(tx.Error) 111 | return 112 | } 113 | fmt.Println("Deleted") 114 | GetGender(id) 115 | } 116 | 117 | func UpdateGender(id uint, name string) { 118 | gender := Gender{} 119 | tx := db.First(&gender, id) 120 | if tx.Error != nil { 121 | fmt.Println(tx.Error) 122 | return 123 | } 124 | gender.Name = name 125 | tx = db.Save(&gender) 126 | if tx.Error != nil { 127 | fmt.Println(tx.Error) 128 | return 129 | } 130 | GetGender(id) 131 | } 132 | 133 | func UpdateGender2(id uint, name string) { 134 | gender := Gender{Name: name} 135 | tx := db.Model(&Gender{}).Where("id=@myid", sql.Named("myid", id)).Updates(gender) 136 | if tx.Error != nil { 137 | fmt.Println(tx.Error) 138 | return 139 | } 140 | GetGender(id) 141 | } 142 | 143 | func GetGenders() { 144 | genders := []Gender{} 145 | tx := db.Order("id").Find(&genders) 146 | if tx.Error != nil { 147 | fmt.Println(tx.Error) 148 | return 149 | } 150 | fmt.Println(genders) 151 | } 152 | 153 | func GetGenderByName(name string) { 154 | genders := []Gender{} 155 | tx := db.Where("name=?", name).Find(&genders) 156 | if tx.Error != nil { 157 | fmt.Println(tx.Error) 158 | return 159 | } 160 | fmt.Println(genders) 161 | } 162 | 163 | func GetGender(id uint) { 164 | gender := Gender{} 165 | tx := db.First(&gender, id) 166 | if tx.Error != nil { 167 | fmt.Println(tx.Error) 168 | return 169 | } 170 | fmt.Println(gender) 171 | } 172 | 173 | func CreateGender(name string) { 174 | gender := Gender{Name: name} 175 | tx := db.Create(&gender) 176 | if tx.Error != nil { 177 | fmt.Println(tx.Error) 178 | return 179 | } 180 | fmt.Println(gender) 181 | } 182 | 183 | type Gender struct { 184 | ID uint 185 | Name string `gorm:"unique;size(10)"` 186 | } 187 | 188 | func (g Gender) BeforeUpdate(*gorm.DB) error { 189 | fmt.Printf("Before Update Gender: %v => %v\n", g.ID, g.Name) 190 | return nil 191 | } 192 | 193 | func (g Gender) AfterUpdate(*gorm.DB) error { 194 | fmt.Printf("After Update Gender: %v => %v\n", g.ID, g.Name) 195 | return nil 196 | } 197 | 198 | type Test struct { 199 | gorm.Model 200 | Code uint `gorm:"comment:This is Code"` 201 | Name string `gorm:"column:myname;size:20;unique;default:Hello;not null"` 202 | } 203 | 204 | func (t Test) TableName() string { 205 | return "MyTest" 206 | } 207 | -------------------------------------------------------------------------------- /resource/banking.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE banking; 2 | USE banking; 3 | 4 | DROP TABLE IF EXISTS `customers`; 5 | CREATE TABLE `customers` ( 6 | `customer_id` int(11) NOT NULL AUTO_INCREMENT, 7 | `name` varchar(100) NOT NULL, 8 | `date_of_birth` date NOT NULL, 9 | `city` varchar(100) NOT NULL, 10 | `zipcode` varchar(10) NOT NULL, 11 | `status` tinyint(1) NOT NULL DEFAULT '1', 12 | PRIMARY KEY (`customer_id`) 13 | ) ENGINE=InnoDB AUTO_INCREMENT=2006 DEFAULT CHARSET=latin1; 14 | INSERT INTO `customers` VALUES 15 | (2000,'Steve','1978-12-15','Delhi','110075',1), 16 | (2001,'Arian','1988-05-21','Newburgh, NY','12550',1), 17 | (2002,'Hadley','1988-04-30','Englewood, NJ','07631',1), 18 | (2003,'Ben','1988-01-04','Manchester, NH','03102',0), 19 | (2004,'Nina','1988-05-14','Clarkston, MI','48348',1), 20 | (2005,'Osman','1988-11-08','Hyattsville, MD','20782',0); 21 | 22 | 23 | DROP TABLE IF EXISTS `accounts`; 24 | CREATE TABLE `accounts` ( 25 | `account_id` int(11) NOT NULL AUTO_INCREMENT, 26 | `customer_id` int(11) NOT NULL, 27 | `opening_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 28 | `account_type` varchar(10) NOT NULL, 29 | `amount` decimal(10,2) NOT NULL, 30 | `status` tinyint(1) NOT NULL DEFAULT '1', 31 | PRIMARY KEY (`account_id`), 32 | KEY `accounts_FK` (`customer_id`), 33 | CONSTRAINT `accounts_FK` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`customer_id`) 34 | ) ENGINE=InnoDB AUTO_INCREMENT=95471 DEFAULT CHARSET=latin1; 35 | INSERT INTO `accounts` VALUES 36 | (95470,2000,'2020-08-22 10:20:06', 'saving', 6823.23, 1), 37 | (95471,2002,'2020-08-09 10:27:22', 'checking', 3342.96, 1), 38 | (95472,2001,'2020-08-09 10:35:22', 'saving', 7000, 1), 39 | (95473,2001,'2020-08-09 10:38:22', 'saving', 5861.86, 1); 40 | 41 | 42 | DROP TABLE IF EXISTS `transactions`; 43 | CREATE TABLE `transactions` ( 44 | `transaction_id` int(11) NOT NULL AUTO_INCREMENT, 45 | `account_id` int(11) NOT NULL, 46 | `amount` decimal(10,2) NOT NULL, 47 | `transaction_type` varchar(10) NOT NULL, 48 | `transaction_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 49 | PRIMARY KEY (`transaction_id`), 50 | KEY `transactions_FK` (`account_id`), 51 | CONSTRAINT `transactions_FK` FOREIGN KEY (`account_id`) REFERENCES `accounts` (`account_id`) 52 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 53 | 54 | 55 | DROP TABLE IF EXISTS `users`; 56 | CREATE TABLE `users` ( 57 | `username` varchar(20) NOT NULL, 58 | `password` varchar(20) NOT NULL, 59 | `role` varchar(20) NOT NULL, 60 | `customer_id` int(11) DEFAULT NULL, 61 | `created_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 62 | PRIMARY KEY (`username`) 63 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 64 | INSERT INTO `users` VALUES 65 | ('admin','abc123','admin', NULL, '2020-08-09 10:27:22'), 66 | ('2001','abc123','user', 2001, '2020-08-09 10:27:22'), 67 | ('2000','abc123','user', 2000, '2020-08-09 10:27:22'); 68 | 69 | DROP TABLE IF EXISTS `refresh_token_store`; 70 | 71 | CREATE TABLE `refresh_token_store` ( 72 | `refresh_token` varchar(300) NOT NULL, 73 | created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 74 | PRIMARY KEY (`refresh_token`) 75 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 76 | -------------------------------------------------------------------------------- /resource/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "run", 8 | "type": "shell", 9 | "command": "go run main.go", 10 | "group": { 11 | "kind": "build", 12 | "isDefault": true 13 | } 14 | }, 15 | { 16 | "label": "test", 17 | "type": "shell", 18 | "command": "go test", 19 | "group": { 20 | "kind": "test", 21 | "isDefault": true 22 | } 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /resource/tls/gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Inspired from: https://github.com/grpc/grpc-java/tree/master/examples#generating-self-signed-certificates-for-use-with-grpc 3 | 4 | # Output files 5 | # ca.key: Certificate Authority private key file (this shouldn't be shared in real-life) 6 | # ca.crt: Certificate Authority trust certificate (this should be shared with users in real-life) 7 | # server.key: Server private key, password protected (this shouldn't be shared) 8 | # server.pem: Conversion of server.key into a format gRPC likes (this shouldn't be shared) 9 | # server.csr: Server certificate signing request (this should be shared with the CA owner) 10 | # server.crt: Server certificate signed by the CA (this would be sent back by the CA owner) - keep on server 11 | 12 | # Summary 13 | # Private files: ca.key, server.key, server.pem, server.crt 14 | # "Share" files: ca.crt (needed by the client), server.csr (needed by the CA) 15 | 16 | # Changes these CN's to match your hosts in your environment if needed. 17 | SERVER_CN=localhost 18 | 19 | # Step 1: Generate Certificate Authority + Trust Certificate (ca.crt) 20 | openssl genrsa -passout pass:1111 -des3 -out ca.key 4096 21 | openssl req -passin pass:1111 -new -x509 -sha256 -days 365 -key ca.key -out ca.crt -subj "/CN=${SERVER_CN}" 22 | 23 | # Step 2: Generate the Server Private Key (server.key) 24 | openssl genrsa -passout pass:1111 -des3 -out server.key 4096 25 | 26 | # Step 3: Convert the server certificate to .pem format (server.pem) - usable by gRPC 27 | openssl pkcs8 -topk8 -nocrypt -passin pass:1111 -in server.key -out server.pem 28 | 29 | # Step 4: Get a certificate signing request from the CA (server.csr) 30 | openssl req -passin pass:1111 -new -sha256 -key server.key -out server.csr -subj "/CN=${SERVER_CN}" -config ssl.cnf 31 | 32 | # Step 5: Sign the certificate with the CA we created (it's called self signing) - server.crt 33 | openssl x509 -req -passin pass:1111 -sha256 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt -extensions req_ext -extfile ssl.cnf 34 | -------------------------------------------------------------------------------- /resource/tls/ssl.cnf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 4096 3 | distinguished_name = dn 4 | req_extensions = req_ext 5 | prompt = no 6 | 7 | [ dn ] 8 | CN = localhost 9 | 10 | [ req_ext ] 11 | subjectAltName = @alt_names 12 | 13 | [alt_names] 14 | DNS.1 = localhost --------------------------------------------------------------------------------