├── .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
--------------------------------------------------------------------------------