├── showcases ├── mq │ └── .gitkeep ├── go-boot │ ├── doc.go │ ├── README.md │ ├── go.mod │ ├── version.go │ ├── middleware.go │ ├── utils │ │ ├── encrypt │ │ │ ├── md5.go │ │ │ ├── aes_test.go │ │ │ └── aes.go │ │ ├── codec │ │ │ ├── json.go │ │ │ ├── xml.go │ │ │ ├── protobuf.go │ │ │ ├── codec.go │ │ │ └── string.go │ │ └── convert │ │ │ └── convert_test.go │ ├── error.go │ ├── config.go │ ├── .gitignore │ ├── plugins │ │ ├── debug.go │ │ └── cryption.go │ ├── hook.go │ ├── retry.go │ ├── cmd │ │ ├── server.go │ │ ├── server_test.go │ │ └── callback.go │ ├── session │ │ └── session.go │ ├── packet.go │ ├── server.go │ └── router.go ├── minitask │ ├── input │ │ └── .gitignore │ ├── logs │ │ └── .gitignore │ ├── output │ │ └── .gitignore │ ├── .DS_Store │ ├── src │ │ ├── .DS_Store │ │ ├── logger │ │ │ └── logger.go │ │ ├── httpbuilder │ │ │ └── httpbuilder.go │ │ ├── executer │ │ │ └── executer.go │ │ └── commandrunner │ │ │ └── commandrunner.go │ ├── compile.sh │ └── LICENSE ├── 2024~simplebank │ ├── .gitignore │ ├── db │ │ ├── migration │ │ │ ├── 000003_add_sessions.down.sql │ │ │ ├── 000005_add_role_to_users.down.sql │ │ │ ├── 000005_add_role_to_users.up.sql │ │ │ ├── 000001_init_schema.down.sql │ │ │ ├── 000004_add_verify_emails.down.sql │ │ │ ├── 000002_add_users.down.sql │ │ │ ├── 000003_add_sessions.up.sql │ │ │ ├── 000004_add_verify_emails.up.sql │ │ │ ├── 000002_add_users.up.sql │ │ │ └── 000001_init_schema.up.sql │ │ ├── query │ │ │ ├── session.sql │ │ │ ├── entry.sql │ │ │ ├── verify_email.sql │ │ │ ├── transfer.sql │ │ │ ├── user.sql │ │ │ └── account.sql │ │ └── sqlc │ │ │ ├── error.go │ │ │ ├── exec_tx.go │ │ │ ├── main_test.go │ │ │ ├── tx_create_user.go │ │ │ ├── db.go │ │ │ ├── store.go │ │ │ └── tx_verify_email.go │ ├── start.sh │ ├── util │ │ ├── role.go │ │ ├── currency.go │ │ ├── password.go │ │ ├── password_test.go │ │ ├── random.go │ │ └── config.go │ ├── backend-master.png │ ├── doc │ │ └── swagger │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── index.css │ │ │ ├── swagger-initializer.js │ │ │ └── index.html │ ├── eks │ │ ├── ingress-nginx.yaml │ │ ├── install.sh │ │ ├── aws-auth.yaml │ │ ├── service.yaml │ │ ├── issuer.yaml │ │ ├── ingress-http.yaml │ │ ├── deployment.yaml │ │ └── ingress-grpc.yaml │ ├── proto │ │ ├── rpc_verify_email.proto │ │ ├── rpc_create_user.proto │ │ ├── user.proto │ │ ├── rpc_update_user.proto │ │ ├── rpc_login_user.proto │ │ └── google │ │ │ └── api │ │ │ └── annotations.proto │ ├── api │ │ ├── validator.go │ │ ├── main_test.go │ │ └── middleware.go │ ├── Dockerfile │ ├── token │ │ ├── maker.go │ │ ├── payload.go │ │ ├── paseto_maker_test.go │ │ └── paseto_maker.go │ ├── sqlc.yaml │ ├── app.env │ ├── gapi │ │ ├── converter.go │ │ ├── error.go │ │ ├── metadata.go │ │ ├── server.go │ │ ├── main_test.go │ │ ├── rpc_verify_email.go │ │ └── authorization.go │ ├── worker │ │ ├── distributor.go │ │ └── logger.go │ ├── mail │ │ ├── sender_test.go │ │ └── sender.go │ ├── docker-compose.yaml │ ├── LICENSE │ ├── .github │ │ └── workflows │ │ │ └── test.yml │ └── val │ │ └── validator.go ├── .DS_Store ├── gorm.db ├── db │ ├── .DS_Store │ ├── redis │ │ ├── .DS_Store │ │ ├── sessions │ │ │ ├── sessions.go │ │ │ ├── memory.go │ │ │ ├── middleware.go │ │ │ └── redis.go │ │ ├── example │ │ │ └── main.go │ │ ├── logger │ │ │ └── logger.go │ │ ├── config.go │ │ ├── exec_test.go │ │ ├── sort_test.go │ │ ├── config_test.go │ │ ├── exec.go │ │ ├── sort.go │ │ └── cmd │ │ │ ├── qclient │ │ │ └── main.go │ │ │ ├── pserver │ │ │ └── main.go │ │ │ ├── qserver │ │ │ └── main.go │ │ │ ├── pclient │ │ │ └── main.go │ │ │ └── server │ │ │ └── main.go │ ├── dbinterface │ │ ├── mockgen.sh │ │ ├── exec.go │ │ ├── create.go │ │ ├── transaction.go │ │ ├── example │ │ │ └── main.go │ │ ├── query.go │ │ ├── create_test.go │ │ ├── query_test.go │ │ └── exec_test.go │ ├── mongodb │ │ ├── example │ │ │ └── main.go │ │ ├── config.go │ │ ├── exec_test.go │ │ ├── config_test.go │ │ └── exec.go │ ├── storage │ │ ├── example │ │ │ └── main.go │ │ ├── storage.go │ │ ├── mongoconfig.go │ │ ├── mongointerface.go │ │ └── exec.go │ ├── pools │ │ ├── example │ │ │ └── main.go │ │ ├── timeout.go │ │ ├── pools.go │ │ ├── timeout_test.go │ │ └── pools_test.go │ ├── database │ │ ├── example │ │ │ └── main.go │ │ ├── exec.go │ │ ├── create.go │ │ ├── config.go │ │ ├── config_test.go │ │ ├── query.go │ │ ├── query_test.go │ │ ├── create_test.go │ │ └── exec_test.go │ └── firebase │ │ ├── auth_test.go │ │ ├── example │ │ └── main.go │ │ ├── client.go │ │ ├── auth.go │ │ └── client_test.go ├── gloc │ ├── .DS_Store │ ├── Gopkg.toml │ ├── bspool.go │ ├── Makefile │ ├── option.go │ ├── examples │ │ ├── files.go │ │ └── languages.go │ ├── utils_test.go │ └── xml.go ├── go-http-proxy-cli │ ├── .DS_Store │ ├── go.mod │ ├── model │ │ ├── file_type.go │ │ └── file.go │ ├── client │ │ └── bp_client.go │ └── cli │ │ └── main.go ├── golang-gin-realworld-example-app │ ├── logo.png │ ├── scripts │ │ ├── gofmt.sh │ │ └── coverage.sh │ ├── doc.go │ ├── users │ │ ├── doc.go │ │ └── serializers.go │ ├── articles │ │ └── doc.go │ ├── BACKEND_INSTRUCTIONS.md │ ├── .gitignore │ ├── .travis.yml │ ├── MOBILE_INSTRUCTIONS.md │ ├── LICENSE │ ├── common │ │ └── database.go │ └── go.mod └── minimal-server │ └── main.go ├── boilerplates ├── standards-layout │ ├── api │ │ ├── .keep │ │ └── README.md │ ├── assets │ │ ├── .keep │ │ └── README.md │ ├── configs │ │ ├── .keep │ │ └── README.md │ ├── docs │ │ ├── .keep │ │ └── README.md │ ├── init │ │ ├── .keep │ │ └── README.md │ ├── scripts │ │ ├── .keep │ │ └── README.md │ ├── test │ │ ├── .keep │ │ └── README.md │ ├── tools │ │ ├── .keep │ │ └── README.md │ ├── vendor │ │ ├── .keep │ │ └── README.md │ ├── web │ │ ├── app │ │ │ └── .keep │ │ ├── static │ │ │ └── .keep │ │ ├── template │ │ │ └── .keep │ │ └── README.md │ ├── deployments │ │ ├── .keep │ │ └── README.md │ ├── examples │ │ ├── .keep │ │ └── README.md │ ├── githooks │ │ ├── .keep │ │ └── README.md │ ├── third_party │ │ ├── .keep │ │ └── README.md │ ├── cmd │ │ ├── _your_app_ │ │ │ └── .keep │ │ └── README.md │ ├── pkg │ │ └── _your_public_lib_ │ │ │ └── .keep │ ├── internal │ │ ├── app │ │ │ └── _your_app_ │ │ │ │ └── .keep │ │ ├── pkg │ │ │ └── _your_private_lib_ │ │ │ │ └── .keep │ │ └── README.md │ ├── Makefile │ ├── website │ │ └── README.md │ └── .gitignore ├── go-backend-clean-architecture │ ├── internal │ │ └── fakeutil │ │ │ └── fakeutil.go │ ├── .gitignore │ ├── domain │ │ ├── error_response.go │ │ ├── success_response.go │ │ ├── profile.go │ │ ├── jwt_custom.go │ │ ├── login.go │ │ ├── user.go │ │ ├── refresh_token.go │ │ ├── task.go │ │ ├── signup.go │ │ └── mocks │ │ │ └── ProfileUsecase.go │ ├── assets │ │ ├── button-view-api-docs.png │ │ ├── go-backend-arch-diagram.png │ │ ├── go-backend-clean-architecture.png │ │ ├── go-arch-private-api-request-flow.png │ │ └── go-arch-public-api-request-flow.png │ ├── Dockerfile │ ├── .env.example │ ├── bootstrap │ │ ├── app.go │ │ ├── database.go │ │ └── env.go │ ├── api │ │ ├── controller │ │ │ ├── profile_controller.go │ │ │ └── task_controller.go │ │ ├── route │ │ │ └── v1 │ │ │ │ ├── profile_route.go │ │ │ │ ├── login_route.go │ │ │ │ ├── task_route.go │ │ │ │ ├── signup_route.go │ │ │ │ ├── refresh_token_route.go │ │ │ │ └── route.go │ │ └── middleware │ │ │ └── jwt_auth_middleware.go │ ├── cmd │ │ └── main.go │ ├── docker-compose.yaml │ ├── usecase │ │ ├── profile_usecase.go │ │ ├── task_usecase.go │ │ ├── login_usecase.go │ │ ├── signup_usecase.go │ │ └── refresh_token_usecase.go │ ├── mongo │ │ └── mocks │ │ │ ├── SingleResult.go │ │ │ └── Database.go │ └── repository │ │ └── task_repository.go ├── .DS_Store └── go-clean-architecture │ ├── .DS_Store │ ├── api │ ├── .DS_Store │ └── middleware │ │ ├── cors.go │ │ └── auth.go │ ├── pkg │ ├── .DS_Store │ ├── user │ │ ├── entity.go │ │ └── repository.go │ ├── admin │ │ ├── entity.go │ │ └── repository.go │ └── errors.go │ ├── README.md │ ├── Makefile │ ├── .gitignore │ ├── .air.conf │ ├── docker-compose.yml │ ├── config.json │ └── go.mod ├── .DS_Store └── LICENSE /showcases/mq/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/api/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/configs/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/docs/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/init/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/scripts/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/test/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/tools/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/vendor/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/web/app/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/deployments/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/examples/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/githooks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/third_party/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/web/static/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/web/template/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /showcases/go-boot/doc.go: -------------------------------------------------------------------------------- 1 | package go_boot 2 | -------------------------------------------------------------------------------- /showcases/minitask/input/.gitignore: -------------------------------------------------------------------------------- 1 | *.txt 2 | -------------------------------------------------------------------------------- /showcases/minitask/logs/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | -------------------------------------------------------------------------------- /showcases/minitask/output/.gitignore: -------------------------------------------------------------------------------- 1 | *.txt 2 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/cmd/_your_app_/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/pkg/_your_public_lib_/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .vscode 3 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/internal/app/_your_app_/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/internal/pkg/_your_private_lib_/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/Makefile: -------------------------------------------------------------------------------- 1 | # note: call scripts from /scripts -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/.DS_Store -------------------------------------------------------------------------------- /boilerplates/standards-layout/githooks/README.md: -------------------------------------------------------------------------------- 1 | # `/githooks` 2 | 3 | Git hooks. 4 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/internal/fakeutil/fakeutil.go: -------------------------------------------------------------------------------- 1 | package fakeutil 2 | -------------------------------------------------------------------------------- /showcases/go-boot/README.md: -------------------------------------------------------------------------------- 1 | # go-boot 2 | 3 | go-boot 是从零实现的 TCP/UDP/HTTP/WebSocket 服务器。 4 | -------------------------------------------------------------------------------- /showcases/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/.DS_Store -------------------------------------------------------------------------------- /showcases/gorm.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/gorm.db -------------------------------------------------------------------------------- /boilerplates/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/boilerplates/.DS_Store -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/migration/000003_add_sessions.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS "sessions"; 2 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | echo "start the app" 6 | exec "$@" 7 | -------------------------------------------------------------------------------- /showcases/db/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/db/.DS_Store -------------------------------------------------------------------------------- /showcases/gloc/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/gloc/.DS_Store -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | bin/ 3 | /.idea 4 | .idea 5 | .env 6 | .vscode -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/migration/000005_add_role_to_users.down.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE "users" DROP COLUMN "role"; 2 | -------------------------------------------------------------------------------- /showcases/db/redis/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/db/redis/.DS_Store -------------------------------------------------------------------------------- /showcases/minitask/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/minitask/.DS_Store -------------------------------------------------------------------------------- /showcases/minitask/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/minitask/src/.DS_Store -------------------------------------------------------------------------------- /showcases/go-http-proxy-cli/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/go-http-proxy-cli/.DS_Store -------------------------------------------------------------------------------- /boilerplates/standards-layout/assets/README.md: -------------------------------------------------------------------------------- 1 | # `/assets` 2 | 3 | Other assets to go along with your repository (images, logos, etc). 4 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/util/role.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | const ( 4 | DepositorRole = "depositor" 5 | BankerRole = "banker" 6 | ) 7 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/boilerplates/go-clean-architecture/.DS_Store -------------------------------------------------------------------------------- /showcases/2024~simplebank/backend-master.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/2024~simplebank/backend-master.png -------------------------------------------------------------------------------- /boilerplates/standards-layout/web/README.md: -------------------------------------------------------------------------------- 1 | # `/web` 2 | 3 | Web application specific components: static web assets, server side templates and SPAs. 4 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/migration/000005_add_role_to_users.up.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE "users" ADD COLUMN "role" varchar NOT NULL DEFAULT 'depositor'; 2 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/api/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/boilerplates/go-clean-architecture/api/.DS_Store -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/pkg/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/boilerplates/go-clean-architecture/pkg/.DS_Store -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/golang-gin-realworld-example-app/logo.png -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/domain/error_response.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | type ErrorResponse struct { 4 | Message string `json:"message"` 5 | } 6 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/init/README.md: -------------------------------------------------------------------------------- 1 | # `/init` 2 | 3 | System init (systemd, upstart, sysv) and process manager/supervisor (runit, supervisord) configs. 4 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/third_party/README.md: -------------------------------------------------------------------------------- 1 | # `/third_party` 2 | 3 | External helper tools, forked code and other 3rd party utilities (e.g., Swagger UI). 4 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/domain/success_response.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | type SuccessResponse struct { 4 | Message string `json:"message"` 5 | } 6 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/migration/000001_init_schema.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS entries; 2 | DROP TABLE IF EXISTS transfers; 3 | DROP TABLE IF EXISTS accounts; 4 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/doc/swagger/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/2024~simplebank/doc/swagger/favicon-16x16.png -------------------------------------------------------------------------------- /showcases/2024~simplebank/doc/swagger/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/showcases/2024~simplebank/doc/swagger/favicon-32x32.png -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/README.md: -------------------------------------------------------------------------------- 1 | # Clean Architecture Sample 2 | Reference code for my article on [Clean Architecture, the right way](https://bit.ly/CleanArch). 3 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/Makefile: -------------------------------------------------------------------------------- 1 | .Phony: begin 2 | begin: 3 | @~/.air -d -c .air.conf 4 | 5 | .phony: build 6 | build: 7 | CGOENABLED=0 go build -o bin/main api/main.go 8 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/migration/000004_add_verify_emails.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS "verify_emails" CASCADE; 2 | 3 | ALTER TABLE "users" DROP COLUMN "is_email_verified"; 4 | -------------------------------------------------------------------------------- /showcases/db/dbinterface/mockgen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | mockgen -destination mocks_test.go -package dbinterface github.com/agtorre/go-cookbook/chapter5/dbinterface DB,Transaction 3 | -------------------------------------------------------------------------------- /showcases/go-boot/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/wxyyxc1992/go-boot 2 | 3 | require ( 4 | github.com/golang/protobuf v1.3.0 5 | github.com/gorilla/websocket v1.4.0 6 | ) 7 | 8 | go 1.13 9 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/configs/README.md: -------------------------------------------------------------------------------- 1 | # `/configs` 2 | 3 | Configuration file templates or default configs. 4 | 5 | Put your `confd` or `consule-template` template files here. 6 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/eks/ingress-nginx.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: IngressClass 3 | metadata: 4 | name: nginx 5 | spec: 6 | controller: k8s.io/ingress-nginx 7 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/assets/button-view-api-docs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/boilerplates/go-backend-clean-architecture/assets/button-view-api-docs.png -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/assets/go-backend-arch-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/boilerplates/go-backend-clean-architecture/assets/go-backend-arch-diagram.png -------------------------------------------------------------------------------- /showcases/go-http-proxy-cli/go.mod: -------------------------------------------------------------------------------- 1 | module dev.wx 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/imroc/req v0.2.4 7 | github.com/json-iterator/go v1.1.8 8 | github.com/urfave/cli/v2 v2.0.0 9 | ) 10 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.19-alpine 2 | 3 | RUN mkdir /app 4 | 5 | ADD . /app 6 | 7 | WORKDIR /app 8 | 9 | RUN go build -o main cmd/main.go 10 | 11 | CMD ["/app/main"] -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/assets/go-backend-clean-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/boilerplates/go-backend-clean-architecture/assets/go-backend-clean-architecture.png -------------------------------------------------------------------------------- /boilerplates/standards-layout/deployments/README.md: -------------------------------------------------------------------------------- 1 | # `/deployments` 2 | 3 | IaaS, PaaS, system and container orchestration deployment configurations and templates (docker-compose, kubernetes/helm, mesos, terraform, bosh). 4 | -------------------------------------------------------------------------------- /showcases/db/mongodb/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/agtorre/go-solutions/section5/mongodb" 4 | 5 | func main() { 6 | if err := mongodb.Exec(); err != nil { 7 | panic(err) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /showcases/db/storage/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/agtorre/go-solutions/section5/storage" 4 | 5 | func main() { 6 | if err := storage.Exec(); err != nil { 7 | panic(err) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/assets/go-arch-private-api-request-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/boilerplates/go-backend-clean-architecture/assets/go-arch-private-api-request-flow.png -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/assets/go-arch-public-api-request-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/go-examples/main/boilerplates/go-backend-clean-architecture/assets/go-arch-public-api-request-flow.png -------------------------------------------------------------------------------- /showcases/db/pools/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/agtorre/go-solutions/section5/pools" 4 | 5 | func main() { 6 | if err := pools.ExecWithTimeout(); err != nil { 7 | panic(err) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /showcases/go-boot/version.go: -------------------------------------------------------------------------------- 1 | package go_boot 2 | 3 | const ( 4 | // Version current Linker version 5 | Version = "1.0.0" 6 | 7 | // MinimumGoVersion minimum required Go version for Linker 8 | MinimumGoVersion = ">=1.9" 9 | ) 10 | -------------------------------------------------------------------------------- /showcases/db/redis/sessions/sessions.go: -------------------------------------------------------------------------------- 1 | package sessions 2 | 3 | type Session struct { 4 | VisitCount int `json:"visitCount"` 5 | } 6 | 7 | type Store interface { 8 | Get(string) (Session, error) 9 | Set(string, Session) error 10 | } 11 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/api/middleware/cors.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/rs/cors" 7 | ) 8 | 9 | func CorsEveryWhere(mux http.Handler) http.Handler { 10 | return cors.Default().Handler(mux) 11 | } 12 | -------------------------------------------------------------------------------- /showcases/db/mongodb/config.go: -------------------------------------------------------------------------------- 1 | package mongodb 2 | 3 | import mgo "gopkg.in/mgo.v2" 4 | 5 | func Setup() (*mgo.Session, error) { 6 | session, err := mgo.Dial("localhost") 7 | if err != nil { 8 | return nil, err 9 | } 10 | return session, nil 11 | } 12 | -------------------------------------------------------------------------------- /showcases/gloc/Gopkg.toml: -------------------------------------------------------------------------------- 1 | [[constraint]] 2 | name = "github.com/jessevdk/go-flags" 3 | version = "1.4.0" 4 | 5 | [[constraint]] 6 | name = "gopkg.in/src-d/enry.v1" 7 | version = "1.6.3" 8 | 9 | [prune] 10 | go-tests = true 11 | unused-packages = true 12 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/api/README.md: -------------------------------------------------------------------------------- 1 | # `/api` 2 | 3 | OpenAPI/Swagger specs, JSON schema files, protocol definition files. 4 | 5 | Examples: 6 | 7 | * https://github.com/kubernetes/kubernetes/tree/master/api 8 | * https://github.com/openshift/origin/tree/master/api 9 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/migration/000002_add_users.down.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE IF EXISTS "accounts" DROP CONSTRAINT IF EXISTS "owner_currency_key"; 2 | 3 | ALTER TABLE IF EXISTS "accounts" DROP CONSTRAINT IF EXISTS "accounts_owner_fkey"; 4 | 5 | DROP TABLE IF EXISTS "users"; 6 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/docs/README.md: -------------------------------------------------------------------------------- 1 | # `/docs` 2 | 3 | Design and user documents (in addition to your godoc generated documentation). 4 | 5 | Examples: 6 | 7 | * https://github.com/gohugoio/hugo/tree/master/docs 8 | * https://github.com/openshift/origin/tree/master/docs 9 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/eks/install.sh: -------------------------------------------------------------------------------- 1 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/aws/deploy.yaml 2 | kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.1/cert-manager.yaml 3 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/vendor/README.md: -------------------------------------------------------------------------------- 1 | # `/vendor` 2 | 3 | Application dependencies (managed manually or by your favorite dependency management tool like [`dep`](https://github.com/golang/dep)). 4 | 5 | Don't commit your application dependencies if you are building a library. 6 | -------------------------------------------------------------------------------- /showcases/db/redis/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/agtorre/go-solutions/section5/redis" 4 | 5 | func main() { 6 | if err := redis.Exec(); err != nil { 7 | panic(err) 8 | } 9 | 10 | if err := redis.Sort(); err != nil { 11 | panic(err) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /showcases/db/storage/storage.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import "context" 4 | 5 | type Item struct { 6 | Name string 7 | Price int64 8 | } 9 | 10 | type Storage interface { 11 | GetByName(context.Context, string) (*Item, error) 12 | Put(context.Context, *Item) error 13 | } 14 | -------------------------------------------------------------------------------- /showcases/go-boot/middleware.go: -------------------------------------------------------------------------------- 1 | package go_boot 2 | 3 | // 全局中间件,每个请求都有执行的操作 4 | type Middleware interface { 5 | Handle(Context) Context 6 | } 7 | 8 | // 响应数据被发送到客户端以后需要执行的操作 9 | type TerminateMiddleware interface { 10 | Handle(Context) Context 11 | Terminate(Context) 12 | } 13 | -------------------------------------------------------------------------------- /showcases/go-boot/utils/encrypt/md5.go: -------------------------------------------------------------------------------- 1 | package encrypt 2 | 3 | import ( 4 | "crypto/md5" 5 | "encoding/hex" 6 | ) 7 | 8 | func Md5(src string) string { 9 | hash := md5.New() 10 | hash.Write([]byte(src)) 11 | cipher := hash.Sum(nil) 12 | return hex.EncodeToString(cipher) 13 | } 14 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/website/README.md: -------------------------------------------------------------------------------- 1 | # `/website` 2 | 3 | This is the place to put your project's website data if you are not using Github pages. 4 | 5 | Examples: 6 | 7 | * https://github.com/hashicorp/vault/tree/master/website 8 | * https://github.com/perkeep/perkeep/tree/master/website 9 | -------------------------------------------------------------------------------- /showcases/db/dbinterface/exec.go: -------------------------------------------------------------------------------- 1 | package dbinterface 2 | 3 | func Exec(db DB) error { 4 | 5 | defer db.Exec("DROP TABLE example") 6 | 7 | if err := Create(db); err != nil { 8 | return err 9 | } 10 | 11 | if err := Query(db); err != nil { 12 | return err 13 | } 14 | return nil 15 | } 16 | -------------------------------------------------------------------------------- /showcases/gloc/bspool.go: -------------------------------------------------------------------------------- 1 | package gocloc 2 | 3 | import "sync" 4 | 5 | var bsPool = sync.Pool{New: func() interface{} { return make([]byte, 0, 128*1024) }} 6 | 7 | func getByteSlice() []byte { 8 | return bsPool.Get().([]byte) 9 | } 10 | 11 | func putByteSlice(bs []byte) { 12 | bsPool.Put(bs) 13 | } 14 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/tools/README.md: -------------------------------------------------------------------------------- 1 | # `/tools` 2 | 3 | Supporting tools for this project. Note that these tools can import code from the `/pkg` and `/internal` directories. 4 | 5 | Examples: 6 | 7 | * https://github.com/istio/istio/tree/master/tools 8 | * https://github.com/openshift/origin/tree/master/tools 9 | -------------------------------------------------------------------------------- /showcases/db/redis/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "github.com/labstack/echo" 5 | "github.com/sirupsen/logrus" 6 | ) 7 | 8 | func FromContext(ectx echo.Context) *logrus.Entry { 9 | sessionID := ectx.Get("sessionID").(string) 10 | return logrus.WithField("sessionID", sessionID) 11 | } 12 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/doc/swagger/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | overflow: -moz-scrollbars-vertical; 4 | overflow-y: scroll; 5 | } 6 | 7 | *, 8 | *:before, 9 | *:after { 10 | box-sizing: inherit; 11 | } 12 | 13 | body { 14 | margin: 0; 15 | background: #fafafa; 16 | } 17 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/eks/aws-auth.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: aws-auth 5 | namespace: kube-system 6 | data: 7 | mapUsers: | 8 | - userarn: arn:aws:iam::760486049168:user/github-ci 9 | username: github-ci 10 | groups: 11 | - system:masters 12 | -------------------------------------------------------------------------------- /showcases/go-http-proxy-cli/model/file_type.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | type FileType string 4 | 5 | const ( 6 | INI FileType = "INI" 7 | BPP FileType = "BPP" 8 | CLI FileType = "CLI" 9 | ) 10 | 11 | type FileSource string 12 | 13 | const ( 14 | local FileSource = "local" 15 | remote FileSource = "remote" 16 | ) 17 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/domain/profile.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import "context" 4 | 5 | type Profile struct { 6 | Name string `json:"name"` 7 | Email string `json:"email"` 8 | } 9 | 10 | type ProfileUsecase interface { 11 | GetProfileByID(c context.Context, userID string) (*Profile, error) 12 | } 13 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/scripts/gofmt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gofmt=$(govendor fmt +l) 4 | echo $gofmt 5 | 6 | if [ ${#gofmt} != 0 ]; then 7 | echo "There is unformatted code, you should use `go fmt ./\.\.\.` to format it." 8 | exit 1 9 | else 10 | echo "Codes are formatted." 11 | exit 0 12 | fi 13 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/proto/rpc_verify_email.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | option go_package = "github.com/techschool/simplebank/pb"; 6 | 7 | message VerifyEmailRequest { 8 | int64 email_id = 1; 9 | string secret_code = 2; 10 | } 11 | 12 | message VerifyEmailResponse { 13 | bool is_verified = 1; 14 | } 15 | -------------------------------------------------------------------------------- /showcases/db/database/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/agtorre/go-solutions/section5/database" 5 | _ "github.com/go-sql-driver/mysql" 6 | ) 7 | 8 | func main() { 9 | db, err := database.Setup() 10 | if err != nil { 11 | panic(err) 12 | } 13 | 14 | if err := database.Exec(db); err != nil { 15 | panic(err) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /showcases/minitask/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | dir=$(cd -P -- "$(dirname -- "$0")" && pwd -P) 4 | 5 | export GOROOT=/usr/local/go 6 | export PATH=$PATH:/usr/local/go/bin 7 | export GOBIN=$dir/bin 8 | export GOPATH=$GOPATH:$dir 9 | export PKG_CONFIG_PATH=/usr/lib/pkgconfig/ 10 | 11 | echo "/usr/local/go/bin/go install "$dir"/src/"$1 12 | go install $dir/src/$1 -------------------------------------------------------------------------------- /showcases/go-boot/error.go: -------------------------------------------------------------------------------- 1 | package go_boot 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | type SystemError struct { 9 | when time.Time 10 | file string 11 | line int 12 | what string 13 | } 14 | 15 | func (e SystemError) Error() string { 16 | return fmt.Sprintf("[datetime]:%v [file]:%v [line]:%v [message]:%v", e.when, e.file, e.line, e.what) 17 | } 18 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Golang Gonic/Gin startup project fork form RealWorld https://realworld.io 3 | 4 | You can find all the spec and front end demo in the Realworld project 5 | 6 | This project will include objects and relationships' CRUD, you will know how to write a golang/gin app though small perfectly formed. 7 | */ 8 | package main 9 | -------------------------------------------------------------------------------- /showcases/gloc/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test build 2 | 3 | build: 4 | go build 5 | mkdir -p bin 6 | go build -o ./bin/gocloc cmd/gocloc/main.go 7 | 8 | update-vendor: 9 | dep ensure 10 | 11 | update-package: 12 | go get -u github.com/hhatto/gocloc 13 | 14 | run-example: 15 | go run examples/languages.go 16 | go run examples/files.go 17 | 18 | test: 19 | go test -v 20 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/users/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | The user module containing the user CRU operation. 3 | 4 | model.go: definition of orm based data model 5 | 6 | routers.go: router binding and core logic 7 | 8 | serializers.go: definition the schema of return data 9 | 10 | validators.go: definition the validator of form data 11 | */ 12 | package users 13 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/domain/jwt_custom.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "github.com/golang-jwt/jwt/v4" 5 | ) 6 | 7 | type JwtCustomClaims struct { 8 | Name string `json:"name"` 9 | ID string `json:"id"` 10 | jwt.StandardClaims 11 | } 12 | 13 | type JwtCustomRefreshClaims struct { 14 | ID string `json:"id"` 15 | jwt.StandardClaims 16 | } 17 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/query/session.sql: -------------------------------------------------------------------------------- 1 | -- name: CreateSession :one 2 | INSERT INTO sessions ( 3 | id, 4 | username, 5 | refresh_token, 6 | user_agent, 7 | client_ip, 8 | is_blocked, 9 | expires_at 10 | ) VALUES ( 11 | $1, $2, $3, $4, $5, $6, $7 12 | ) RETURNING *; 13 | 14 | -- name: GetSession :one 15 | SELECT * FROM sessions 16 | WHERE id = $1 LIMIT 1; 17 | -------------------------------------------------------------------------------- /showcases/db/database/exec.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | func Exec(db *sql.DB) error { 10 | defer db.Exec("DROP TABLE example") 11 | 12 | if err := Create(db); err != nil { 13 | return err 14 | } 15 | 16 | if err := Query(db); err != nil { 17 | return err 18 | } 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /showcases/db/pools/timeout.go: -------------------------------------------------------------------------------- 1 | package pools 2 | 3 | import ( 4 | "context" 5 | "time" 6 | ) 7 | 8 | func ExecWithTimeout() error { 9 | db, err := Setup() 10 | if err != nil { 11 | return err 12 | } 13 | 14 | ctx := context.Background() 15 | ctx, can := context.WithDeadline(ctx, time.Now()) 16 | 17 | defer can() 18 | 19 | _, err = db.BeginTx(ctx, nil) 20 | return err 21 | } 22 | -------------------------------------------------------------------------------- /showcases/db/redis/config.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "os" 5 | 6 | redis "gopkg.in/redis.v5" 7 | ) 8 | 9 | func Setup() (*redis.Client, error) { 10 | client := redis.NewClient(&redis.Options{ 11 | Addr: "localhost:6379", 12 | Password: os.Getenv("REDISPASSWORD"), 13 | DB: 0, 14 | }) 15 | 16 | _, err := client.Ping().Result() 17 | return client, err 18 | } 19 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/.env.example: -------------------------------------------------------------------------------- 1 | APP_ENV=development 2 | SERVER_ADDRESS=:8080 3 | PORT=8080 4 | CONTEXT_TIMEOUT=2 5 | DB_HOST=mongodb 6 | DB_PORT=27017 7 | DB_USER= 8 | DB_PASS= 9 | DB_NAME=go-backend-clean-architecture-db 10 | ACCESS_TOKEN_EXPIRY_HOUR = 2 11 | REFRESH_TOKEN_EXPIRY_HOUR = 168 12 | ACCESS_TOKEN_SECRET=access_token_secret 13 | REFRESH_TOKEN_SECRET=refresh_token_secret -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/query/entry.sql: -------------------------------------------------------------------------------- 1 | -- name: CreateEntry :one 2 | INSERT INTO entries ( 3 | account_id, 4 | amount 5 | ) VALUES ( 6 | $1, $2 7 | ) RETURNING *; 8 | 9 | -- name: GetEntry :one 10 | SELECT * FROM entries 11 | WHERE id = $1 LIMIT 1; 12 | 13 | -- name: ListEntries :many 14 | SELECT * FROM entries 15 | WHERE account_id = $1 16 | ORDER BY id 17 | LIMIT $2 18 | OFFSET $3; 19 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/examples/README.md: -------------------------------------------------------------------------------- 1 | # `/examples` 2 | 3 | Examples for your applications and/or public libraries. 4 | 5 | Examples: 6 | 7 | * https://github.com/nats-io/go-nats/tree/master/examples 8 | * https://github.com/docker-slim/docker-slim/tree/master/examples 9 | * https://github.com/gohugoio/hugo/tree/master/examples 10 | * https://github.com/hashicorp/packer/tree/master/examples 11 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/util/currency.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | // Constants for all supported currencies 4 | const ( 5 | USD = "USD" 6 | EUR = "EUR" 7 | CAD = "CAD" 8 | ) 9 | 10 | // IsSupportedCurrency returns true if the currency is supported 11 | func IsSupportedCurrency(currency string) bool { 12 | switch currency { 13 | case USD, EUR, CAD: 14 | return true 15 | } 16 | return false 17 | } 18 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/articles/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | The article module containing the article CRUD operation and relationship CRUD. 3 | 4 | model.go: definition of orm based data model 5 | 6 | routers.go: router binding and core logic 7 | 8 | serializers.go: definition the schema of return data 9 | 10 | validators.go: definition the validator of form data 11 | */ 12 | package articles 13 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/api/validator.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-playground/validator/v10" 5 | "github.com/techschool/simplebank/util" 6 | ) 7 | 8 | var validCurrency validator.Func = func(fieldLevel validator.FieldLevel) bool { 9 | if currency, ok := fieldLevel.Field().Interface().(string); ok { 10 | return util.IsSupportedCurrency(currency) 11 | } 12 | return false 13 | } 14 | -------------------------------------------------------------------------------- /showcases/go-boot/utils/codec/json.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import "encoding/json" 4 | 5 | type JsonCoder struct{} 6 | 7 | func (c *JsonCoder) Encoder(data interface{}) ([]byte, error) { 8 | return json.Marshal(data) 9 | } 10 | 11 | func (c *JsonCoder) Decoder(data []byte, v interface{}) error { 12 | return json.Unmarshal(data, v) 13 | } 14 | 15 | func init() { 16 | Register(JSON, &JsonCoder{}) 17 | } 18 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X files 2 | .DS_Store 3 | 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.dll 7 | *.so 8 | *.dylib 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 17 | .glide/ 18 | -------------------------------------------------------------------------------- /showcases/go-boot/utils/codec/xml.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "encoding/xml" 5 | ) 6 | 7 | type XMLCoder struct{} 8 | 9 | func (c *XMLCoder) Encoder(data interface{}) ([]byte, error) { 10 | return xml.Marshal(data) 11 | } 12 | 13 | func (c *XMLCoder) Decoder(data []byte, v interface{}) error { 14 | return xml.Unmarshal(data, v) 15 | } 16 | 17 | func init() { 18 | Register(XML, &JsonCoder{}) 19 | } 20 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/BACKEND_INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | > *Note: Delete this file before publishing your app!* 2 | 3 | # [Backend API spec](https://github.com/gothinkster/realworld/tree/master/api) 4 | 5 | For your convenience, we have a [Postman collection](https://github.com/gothinkster/realworld/blob/master/api/Conduit.postman_collection.json) that you can use to test your API endpoints as you build your app. 6 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/scripts/README.md: -------------------------------------------------------------------------------- 1 | # `/scripts` 2 | 3 | Scripts to perform various build, install, analysis, etc operations. 4 | 5 | These scripts keep the root level Makefile small and simple. 6 | 7 | Examples: 8 | 9 | * https://github.com/kubernetes/helm/tree/master/scripts 10 | * https://github.com/cockroachdb/cockroach/tree/master/scripts 11 | * https://github.com/hashicorp/terraform/tree/master/scripts -------------------------------------------------------------------------------- /showcases/2024~simplebank/proto/rpc_create_user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | import "user.proto"; 6 | 7 | option go_package = "github.com/techschool/simplebank/pb"; 8 | 9 | message CreateUserRequest { 10 | string username = 1; 11 | string full_name = 2; 12 | string email = 3; 13 | string password = 4; 14 | } 15 | 16 | message CreateUserResponse { 17 | User user = 1; 18 | } 19 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/proto/user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | import "google/protobuf/timestamp.proto"; 6 | 7 | option go_package = "github.com/techschool/simplebank/pb"; 8 | 9 | message User { 10 | string username = 1; 11 | string full_name = 2; 12 | string email = 3; 13 | google.protobuf.Timestamp password_changed_at = 4; 14 | google.protobuf.Timestamp created_at = 5; 15 | } 16 | -------------------------------------------------------------------------------- /showcases/db/dbinterface/create.go: -------------------------------------------------------------------------------- 1 | package dbinterface 2 | 3 | import _ "github.com/go-sql-driver/mysql" 4 | 5 | func Create(db DB) error { 6 | if _, err := db.Exec("CREATE TABLE example (name VARCHAR(20), created DATETIME)"); err != nil { 7 | return err 8 | } 9 | 10 | if _, err := db.Exec(`INSERT INTO example (name, created) values ("Aaron", NOW())`); err != nil { 11 | return err 12 | } 13 | 14 | return nil 15 | } 16 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/eks/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: simple-bank-api-service 5 | spec: 6 | selector: 7 | app: simple-bank-api 8 | ports: 9 | - protocol: TCP 10 | port: 80 11 | targetPort: http-server 12 | name: http-service 13 | - protocol: TCP 14 | port: 90 15 | targetPort: grpc-server 16 | name: grpc-service 17 | type: ClusterIP 18 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build stage 2 | FROM golang:1.22-alpine3.19 AS builder 3 | WORKDIR /app 4 | COPY . . 5 | RUN go build -o main main.go 6 | 7 | # Run stage 8 | FROM alpine:3.19 9 | WORKDIR /app 10 | COPY --from=builder /app/main . 11 | COPY app.env . 12 | COPY start.sh . 13 | COPY wait-for.sh . 14 | COPY db/migration ./db/migration 15 | 16 | EXPOSE 8080 9090 17 | CMD [ "/app/main" ] 18 | ENTRYPOINT [ "/app/start.sh" ] 19 | -------------------------------------------------------------------------------- /showcases/go-boot/config.go: -------------------------------------------------------------------------------- 1 | package go_boot 2 | 3 | import "time" 4 | 5 | // Config for socket server 6 | type Config struct { 7 | Debug bool 8 | ReadBufferSize int 9 | WriteBufferSize int 10 | Timeout time.Duration 11 | MaxPayload uint32 12 | ContentType string 13 | PluginForPacketSender []PacketPlugin 14 | PluginForPacketReceiver []PacketPlugin 15 | } 16 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/proto/rpc_update_user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | import "user.proto"; 6 | 7 | option go_package = "github.com/techschool/simplebank/pb"; 8 | 9 | message UpdateUserRequest { 10 | string username = 1; 11 | optional string full_name = 2; 12 | optional string email = 3; 13 | optional string password = 4; 14 | } 15 | 16 | message UpdateUserResponse { 17 | User user = 1; 18 | } 19 | -------------------------------------------------------------------------------- /showcases/db/redis/exec_test.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "testing" 4 | 5 | func TestExec(t *testing.T) { 6 | tests := []struct { 7 | name string 8 | wantErr bool 9 | }{ 10 | {"base-case", false}, 11 | } 12 | for _, tt := range tests { 13 | t.Run(tt.name, func(t *testing.T) { 14 | if err := Exec(); (err != nil) != tt.wantErr { 15 | t.Errorf("Exec() error = %v, wantErr %v", err, tt.wantErr) 16 | } 17 | }) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /showcases/db/redis/sort_test.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "testing" 4 | 5 | func TestSort(t *testing.T) { 6 | tests := []struct { 7 | name string 8 | wantErr bool 9 | }{ 10 | {"base-case", false}, 11 | } 12 | for _, tt := range tests { 13 | t.Run(tt.name, func(t *testing.T) { 14 | if err := Sort(); (err != nil) != tt.wantErr { 15 | t.Errorf("Sort() error = %v, wantErr %v", err, tt.wantErr) 16 | } 17 | }) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /showcases/db/mongodb/exec_test.go: -------------------------------------------------------------------------------- 1 | package mongodb 2 | 3 | import "testing" 4 | 5 | func TestExec(t *testing.T) { 6 | tests := []struct { 7 | name string 8 | wantErr bool 9 | }{ 10 | {"base-case", false}, 11 | } 12 | for _, tt := range tests { 13 | t.Run(tt.name, func(t *testing.T) { 14 | if err := Exec(); (err != nil) != tt.wantErr { 15 | t.Errorf("Exec() error = %v, wantErr %v", err, tt.wantErr) 16 | } 17 | }) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/.air.conf: -------------------------------------------------------------------------------- 1 | root = "." 2 | 3 | watch_dir = "." 4 | tmp_dir = "" 5 | 6 | [build] 7 | cmd = "go build -o ./api/main ./api/main.go" 8 | bin = "api/main" 9 | include_ext = ["go", "tpl", "tmpl", "html"] 10 | exclude_dir = ["assets", "tmp", "vendor", "postgres-data"] 11 | delay = 100 # ms 12 | 13 | [log] 14 | time = true 15 | 16 | [color] 17 | main = "magenta" 18 | watcher = "cyan" 19 | build = "yellow" 20 | runner = "green" 21 | -------------------------------------------------------------------------------- /showcases/go-http-proxy-cli/model/file.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | type File struct { 4 | fileId string "" 5 | fileType FileType "INI | BPP | CLI" 6 | fileSource FileSource "remote" 7 | url string 8 | fileHash string 9 | } 10 | 11 | func NewFile(fileId string, fileType FileType, fileSource FileSource, url string, fileHash string) *File { 12 | file := &File{fileId, fileType, fileSource, url, fileHash} 13 | 14 | return file 15 | } 16 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/token/maker.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // Maker is an interface for managing tokens 8 | type Maker interface { 9 | // CreateToken creates a new token for a specific username and duration 10 | CreateToken(username string, role string, duration time.Duration) (string, *Payload, error) 11 | 12 | // VerifyToken checks if the token is valid or not 13 | VerifyToken(token string) (*Payload, error) 14 | } 15 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/query/verify_email.sql: -------------------------------------------------------------------------------- 1 | -- name: CreateVerifyEmail :one 2 | INSERT INTO verify_emails ( 3 | username, 4 | email, 5 | secret_code 6 | ) VALUES ( 7 | $1, $2, $3 8 | ) RETURNING *; 9 | 10 | -- name: UpdateVerifyEmail :one 11 | UPDATE verify_emails 12 | SET 13 | is_used = TRUE 14 | WHERE 15 | id = @id 16 | AND secret_code = @secret_code 17 | AND is_used = FALSE 18 | AND expired_at > now() 19 | RETURNING *; 20 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /bower_components 6 | 7 | # IDEs and editors 8 | /.idea 9 | .project 10 | .classpath 11 | *.launch 12 | .settings/ 13 | 14 | #System Files 15 | .DS_Store 16 | Thumbs.db 17 | 18 | vendor/* 19 | !vendor/vendor.json 20 | 21 | tmp/* 22 | gorm.db 23 | coverage.txt 24 | 25 | bak.* 26 | 27 | build 28 | -------------------------------------------------------------------------------- /showcases/minimal-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | ) 8 | 9 | func sayHelloName(w http.ResponseWriter, r *http.Request) { 10 | r.ParseForm() 11 | fmt.Println("path:", r.URL.Path) 12 | fmt.Fprintf(w, "hello go") 13 | } 14 | 15 | func main() { 16 | http.HandleFunc("/", sayHelloName) 17 | err := http.ListenAndServe(":9090", nil) 18 | 19 | if err != nil { 20 | log.Fatal("ListenAndServer: ", err) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /showcases/db/database/create.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | func Create(db *sql.DB) error { 10 | if _, err := db.Exec("CREATE TABLE example (name VARCHAR(20), 11 | created DATETIME)"); err != nil { 12 | return err 13 | } 14 | 15 | if _, err := db.Exec(`INSERT INTO example (name, created) 16 | values ("Aaron", NOW())`); err != nil { 17 | return err 18 | } 19 | 20 | return nil 21 | } 22 | -------------------------------------------------------------------------------- /showcases/db/mongodb/config_test.go: -------------------------------------------------------------------------------- 1 | package mongodb 2 | 3 | import "testing" 4 | 5 | func TestSetup(t *testing.T) { 6 | tests := []struct { 7 | name string 8 | wantErr bool 9 | }{ 10 | {"base-case", false}, 11 | } 12 | for _, tt := range tests { 13 | t.Run(tt.name, func(t *testing.T) { 14 | _, err := Setup() 15 | if (err != nil) != tt.wantErr { 16 | t.Errorf("Setup() error = %v, wantErr %v", err, tt.wantErr) 17 | return 18 | } 19 | }) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /showcases/db/pools/pools.go: -------------------------------------------------------------------------------- 1 | package pools 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "os" 7 | 8 | _ "github.com/go-sql-driver/mysql" 9 | ) 10 | 11 | func Setup() (*sql.DB, error) { 12 | db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@/gosolutions?parseTime=true", os.Getenv("MYSQLUSERNAME"), os.Getenv("MYSQLPASSWORD"))) 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | db.SetMaxOpenConns(24) 18 | db.SetMaxIdleConns(24) 19 | 20 | return db, nil 21 | } 22 | -------------------------------------------------------------------------------- /showcases/db/pools/timeout_test.go: -------------------------------------------------------------------------------- 1 | package pools 2 | 3 | import "testing" 4 | 5 | func TestExecWithTimeout(t *testing.T) { 6 | tests := []struct { 7 | name string 8 | wantErr bool 9 | }{ 10 | {"base-case", true}, 11 | } 12 | for _, tt := range tests { 13 | t.Run(tt.name, func(t *testing.T) { 14 | if err := ExecWithTimeout(); (err != nil) != tt.wantErr { 15 | t.Errorf("ExecWithTimeout() error = %v, wantErr %v", err, tt.wantErr) 16 | } 17 | }) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/query/transfer.sql: -------------------------------------------------------------------------------- 1 | -- name: CreateTransfer :one 2 | INSERT INTO transfers ( 3 | from_account_id, 4 | to_account_id, 5 | amount 6 | ) VALUES ( 7 | $1, $2, $3 8 | ) RETURNING *; 9 | 10 | -- name: GetTransfer :one 11 | SELECT * FROM transfers 12 | WHERE id = $1 LIMIT 1; 13 | 14 | -- name: ListTransfers :many 15 | SELECT * FROM transfers 16 | WHERE 17 | from_account_id = $1 OR 18 | to_account_id = $2 19 | ORDER BY id 20 | LIMIT $3 21 | OFFSET $4; 22 | -------------------------------------------------------------------------------- /showcases/db/redis/config_test.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "testing" 4 | 5 | func TestSetup(t *testing.T) { 6 | tests := []struct { 7 | name string 8 | wantErr bool 9 | }{ 10 | {"base-case", false}, 11 | } 12 | for _, tt := range tests { 13 | t.Run(tt.name, func(t *testing.T) { 14 | _, err := Setup() 15 | if (err != nil) != tt.wantErr { 16 | t.Errorf("Setup() error = %v, wantErr %v", err, tt.wantErr) 17 | return 18 | } 19 | 20 | }) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /showcases/db/dbinterface/transaction.go: -------------------------------------------------------------------------------- 1 | package dbinterface 2 | 3 | import "database/sql" 4 | 5 | type DB interface { 6 | Exec(query string, args ...interface{}) (sql.Result, error) 7 | Prepare(query string) (*sql.Stmt, error) 8 | Query(query string, args ...interface{}) (*sql.Rows, error) 9 | QueryRow(query string, args ...interface{}) *sql.Row 10 | } 11 | 12 | type Transaction interface { 13 | DB 14 | Commit() error 15 | Rollback() error 16 | Stmt(stmt *sql.Stmt) *sql.Stmt 17 | } 18 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/bootstrap/app.go: -------------------------------------------------------------------------------- 1 | package bootstrap 2 | 3 | import "github.com/amitshekhariitbhu/go-backend-clean-architecture/mongo" 4 | 5 | type Application struct { 6 | Env *Env 7 | Mongo mongo.Client 8 | } 9 | 10 | func App() Application { 11 | app := &Application{} 12 | app.Env = NewEnv() 13 | app.Mongo = NewMongoDatabase(app.Env) 14 | return *app 15 | } 16 | 17 | func (app *Application) CloseDBConnection() { 18 | CloseMongoDBConnection(app.Mongo) 19 | } 20 | -------------------------------------------------------------------------------- /showcases/db/firebase/auth_test.go: -------------------------------------------------------------------------------- 1 | package firebase 2 | 3 | import "testing" 4 | 5 | func TestAuthenticate(t *testing.T) { 6 | 7 | tests := []struct { 8 | name string 9 | wantErr bool 10 | }{ 11 | {"base-case", false}, 12 | } 13 | for _, tt := range tests { 14 | t.Run(tt.name, func(t *testing.T) { 15 | _, err := Authenticate() 16 | if (err != nil) != tt.wantErr { 17 | t.Errorf("Authenticate() error = %v, wantErr %v", err, tt.wantErr) 18 | return 19 | } 20 | }) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/migration/000003_add_sessions.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE "sessions" ( 2 | "id" uuid PRIMARY KEY, 3 | "username" varchar NOT NULL, 4 | "refresh_token" varchar NOT NULL, 5 | "user_agent" varchar NOT NULL, 6 | "client_ip" varchar NOT NULL, 7 | "is_blocked" boolean NOT NULL DEFAULT false, 8 | "expires_at" timestamptz NOT NULL, 9 | "created_at" timestamptz NOT NULL DEFAULT (now()) 10 | ); 11 | 12 | ALTER TABLE "sessions" ADD FOREIGN KEY ("username") REFERENCES "users" ("username"); 13 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/sqlc.yaml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | sql: 3 | - schema: "db/migration" 4 | queries: "db/query" 5 | engine: "postgresql" 6 | gen: 7 | go: 8 | package: "db" 9 | out: "db/sqlc" 10 | sql_package: "pgx/v5" 11 | emit_json_tags: true 12 | emit_interface: true 13 | emit_empty_slices: true 14 | overrides: 15 | - db_type: "timestamptz" 16 | go_type: "time.Time" 17 | - db_type: "uuid" 18 | go_type: "github.com/google/uuid.UUID" 19 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/pkg/user/entity.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import "github.com/jinzhu/gorm" 4 | 5 | type User struct { 6 | gorm.Model 7 | FirstName string `json:"first_name,omitempty"` 8 | LastName string `json:"last_name,omitempty"` 9 | Password string `json:"password,omitempty"` 10 | PhoneNumber string `json:"phone_number,omitempty"` 11 | Email string `json:"email,omitempty"` 12 | Address string `json:"address,omitempty"` 13 | DisplayPic string `json:"display_pic,omitempty"` 14 | } 15 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/app.env: -------------------------------------------------------------------------------- 1 | ENVIRONMENT=development 2 | DB_SOURCE=postgresql://root:secret@localhost:5432/simple_bank?sslmode=disable 3 | MIGRATION_URL=file://db/migration 4 | HTTP_SERVER_ADDRESS=0.0.0.0:8080 5 | GRPC_SERVER_ADDRESS=0.0.0.0:9090 6 | TOKEN_SYMMETRIC_KEY=12345678901234567890123456789012 7 | ACCESS_TOKEN_DURATION=15m 8 | REFRESH_TOKEN_DURATION=24h 9 | REDIS_ADDRESS=0.0.0.0:6379 10 | EMAIL_SENDER_NAME=Simple Bank 11 | EMAIL_SENDER_ADDRESS=simplebanktest@gmail.com 12 | EMAIL_SENDER_PASSWORD=jekfcygyenvzekke 13 | -------------------------------------------------------------------------------- /showcases/db/storage/mongoconfig.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import mgo "gopkg.in/mgo.v2" 4 | 5 | type MongoStorage struct { 6 | *mgo.Session 7 | DB string 8 | Collection string 9 | } 10 | 11 | func NewMongoStorage(connection, db, collection string) 12 | (*MongoStorage, error) { 13 | session, err := mgo.Dial("localhost") 14 | if err != nil { 15 | return nil, err 16 | } 17 | ms := MongoStorage{ 18 | Session: session, 19 | DB: db, 20 | Collection: collection, 21 | } 22 | return &ms, nil 23 | } 24 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/pkg/admin/entity.go: -------------------------------------------------------------------------------- 1 | package admin 2 | 3 | import "github.com/jinzhu/gorm" 4 | 5 | type Admin struct { 6 | gorm.Model 7 | FirstName string `json:"first_name,omitempty"` 8 | LastName string `json:"last_name,omitempty"` 9 | Password string `json:"password,omitempty"` 10 | PhoneNumber string `json:"phone_number,omitempty"` 11 | Email string `json:"email,omitempty"` 12 | Address string `json:"address,omitempty"` 13 | DisplayPic string `json:"display_pic,omitempty"` 14 | } 15 | -------------------------------------------------------------------------------- /showcases/db/database/config.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "os" 7 | "time" 8 | 9 | _ "github.com/go-sql-driver/mysql" 10 | ) 11 | 12 | type Example struct { 13 | Name string 14 | Created *time.Time 15 | } 16 | 17 | func Setup() (*sql.DB, error) { 18 | db, err := sql.Open("mysql", 19 | fmt.Sprintf("%s:%s@/gosolutions?parseTime=true", 20 | os.Getenv("MYSQLUSERNAME"), os.Getenv("MYSQLPASSWORD"))) 21 | if err != nil { 22 | return nil, err 23 | } 24 | return db, nil 25 | } 26 | -------------------------------------------------------------------------------- /showcases/db/pools/pools_test.go: -------------------------------------------------------------------------------- 1 | package pools 2 | 3 | import ( 4 | "testing" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | func TestSetup(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | wantErr bool 13 | }{ 14 | {"base-case", false}, 15 | } 16 | for _, tt := range tests { 17 | t.Run(tt.name, func(t *testing.T) { 18 | _, err := Setup() 19 | if (err != nil) != tt.wantErr { 20 | t.Errorf("Setup() error = %v, wantErr %v", err, tt.wantErr) 21 | return 22 | } 23 | }) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /showcases/go-boot/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Go template 3 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 4 | *.o 5 | *.a 6 | *.so 7 | 8 | # Folders 9 | _obj 10 | _test 11 | 12 | # Architecture specific extensions/prefixes 13 | *.[568vq] 14 | [568vq].out 15 | 16 | *.cgo1.go 17 | *.cgo2.c 18 | _cgo_defun.c 19 | _cgo_gotypes.go 20 | _cgo_export.* 21 | 22 | _testmain.go 23 | 24 | *.exe 25 | *.test 26 | *.prof 27 | *~ 28 | .DS_Store 29 | 30 | /.idea/ 31 | /linker.iml 32 | /vendor/ 33 | -------------------------------------------------------------------------------- /showcases/db/database/config_test.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "testing" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | func TestSetup(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | wantErr bool 13 | }{ 14 | {"base-case", false}, 15 | } 16 | for _, tt := range tests { 17 | t.Run(tt.name, func(t *testing.T) { 18 | _, err := Setup() 19 | if (err != nil) != tt.wantErr { 20 | t.Errorf("Setup() error = %v, wantErr %v", err, tt.wantErr) 21 | return 22 | } 23 | }) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /showcases/gloc/option.go: -------------------------------------------------------------------------------- 1 | package gocloc 2 | 3 | import "regexp" 4 | 5 | type ClocOptions struct { 6 | Debug bool 7 | SkipDuplicated bool 8 | ExcludeExts map[string]struct{} 9 | IncludeLangs map[string]struct{} 10 | ReNotMatchDir *regexp.Regexp 11 | ReMatchDir *regexp.Regexp 12 | } 13 | 14 | func NewClocOptions() *ClocOptions { 15 | return &ClocOptions{ 16 | Debug: false, 17 | SkipDuplicated: false, 18 | ExcludeExts: make(map[string]struct{}), 19 | IncludeLangs: make(map[string]struct{}), 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/sqlc/error.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/jackc/pgx/v5" 7 | "github.com/jackc/pgx/v5/pgconn" 8 | ) 9 | 10 | const ( 11 | ForeignKeyViolation = "23503" 12 | UniqueViolation = "23505" 13 | ) 14 | 15 | var ErrRecordNotFound = pgx.ErrNoRows 16 | 17 | var ErrUniqueViolation = &pgconn.PgError{ 18 | Code: UniqueViolation, 19 | } 20 | 21 | func ErrorCode(err error) string { 22 | var pgErr *pgconn.PgError 23 | if errors.As(err, &pgErr) { 24 | return pgErr.Code 25 | } 26 | return "" 27 | } 28 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/gapi/converter.go: -------------------------------------------------------------------------------- 1 | package gapi 2 | 3 | import ( 4 | db "github.com/techschool/simplebank/db/sqlc" 5 | "github.com/techschool/simplebank/pb" 6 | "google.golang.org/protobuf/types/known/timestamppb" 7 | ) 8 | 9 | func convertUser(user db.User) *pb.User { 10 | return &pb.User{ 11 | Username: user.Username, 12 | FullName: user.FullName, 13 | Email: user.Email, 14 | PasswordChangedAt: timestamppb.New(user.PasswordChangedAt), 15 | CreatedAt: timestamppb.New(user.CreatedAt), 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /showcases/db/storage/mongointerface.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "context" 5 | 6 | "gopkg.in/mgo.v2/bson" 7 | ) 8 | 9 | func (m *MongoStorage) GetByName(ctx context.Context, name string) 10 | (*Item, error) { 11 | c := m.Session.DB(m.DB).C(m.Collection) 12 | var i Item 13 | if err := c.Find(bson.M{"name": name}).One(&i); err != nil { 14 | return nil, err 15 | } 16 | return &i, nil 17 | } 18 | 19 | func (m *MongoStorage) Put(ctx context.Context, i *Item) error { 20 | c := m.Session.DB(m.DB).C(m.Collection) 21 | return c.Insert(i) 22 | } 23 | -------------------------------------------------------------------------------- /showcases/db/redis/exec.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | redis "gopkg.in/redis.v5" 8 | ) 9 | 10 | func Exec() error { 11 | conn, err := Setup() 12 | if err != nil { 13 | return err 14 | } 15 | 16 | c1 := "value" 17 | conn.Set("key", c1, 5*time.Second) 18 | 19 | var result string 20 | if err := conn.Get("key").Scan(&result); err != nil { 21 | switch err { 22 | case redis.Nil: 23 | return nil 24 | default: 25 | return err 26 | } 27 | } 28 | 29 | fmt.Println("result =", result) 30 | 31 | return nil 32 | } 33 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | 3 | services: 4 | 5 | db: 6 | image: postgres 7 | restart: always 8 | ports: 9 | - 5432:5432 10 | env_file: "./config.json" 11 | environment: 12 | POSTGRES_PASSWORD: "${POSTGRES_PASSWORD_dev}" 13 | POSTGRES_USER: "${POSTGRES_USER_dev}" 14 | POSTGRES_DB: "${POSTGRES_DB_dev}" 15 | volumes: 16 | - ./postgres-data:/var/lib/postgresql/data 17 | 18 | adminer: 19 | image: adminer 20 | restart: always 21 | ports: 22 | - 8080:8080 23 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/scripts/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | # http://stackoverflow.com/a/21142256/2055281 6 | 7 | echo "mode: atomic" > coverage.txt 8 | 9 | for d in $(find ./* -maxdepth 10 -type d); do 10 | if ls $d/*.go &> /dev/null; then 11 | go test -coverprofile=profile.out -covermode=atomic $d 12 | if [ -f profile.out ]; then 13 | echo "$(pwd)" 14 | cat profile.out | grep -v "mode: " >> coverage.txt 15 | rm profile.out 16 | fi 17 | fi 18 | done 19 | 20 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/eks/issuer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: ClusterIssuer 3 | metadata: 4 | name: letsencrypt 5 | spec: 6 | acme: 7 | email: techschool.guru@gmail.com 8 | server: https://acme-v02.api.letsencrypt.org/directory 9 | privateKeySecretRef: 10 | # Secret resource that will be used to store the account's private key. 11 | name: letsencrypt-account-private-key 12 | # Add a single challenge solver, HTTP01 using nginx 13 | solvers: 14 | - http01: 15 | ingress: 16 | ingressClassName: nginx 17 | -------------------------------------------------------------------------------- /showcases/db/firebase/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/agtorre/go-solutions/section5/firebase" 8 | ) 9 | 10 | func main() { 11 | f, err := firebase.Authenticate() 12 | if err != nil { 13 | log.Fatalf("error authenticating") 14 | } 15 | f.Set("key", []string{"val1", "val2"}) 16 | res, _ := f.Get() 17 | fmt.Println(res) 18 | 19 | vals := res["key"].([]interface{}) 20 | vals = append(vals, map[string][]string{"key2": []string{"val3"}}) 21 | f.Set("key", vals) 22 | res, _ = f.Get() 23 | fmt.Println(res) 24 | } 25 | -------------------------------------------------------------------------------- /showcases/go-boot/utils/encrypt/aes_test.go: -------------------------------------------------------------------------------- 1 | package encrypt 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "testing" 7 | ) 8 | 9 | func TestAES(t *testing.T) { 10 | src := "hello,你好世界" 11 | encodeBytes, err := Encrypt([]byte(src)) 12 | if err != nil { 13 | t.Error(err) 14 | } 15 | fmt.Println(base64.StdEncoding.EncodeToString(encodeBytes)) 16 | 17 | decodeBytes, err := Decrypt(encodeBytes) 18 | if err != nil { 19 | t.Error(err) 20 | } 21 | 22 | if string(decodeBytes) != src { 23 | t.Error(err) 24 | } 25 | 26 | fmt.Println(string(decodeBytes)) 27 | } 28 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.7 5 | - 1.8.x 6 | - master 7 | 8 | go_import_path: github.com/gothinkster/golang-gin-realworld-example-app 9 | 10 | services: 11 | - sqlite3 12 | 13 | install: 14 | - go get -u github.com/gothinkster/golang-gin-realworld-example-app 15 | - go get -u github.com/kardianos/govendor 16 | - govendor sync 17 | script: 18 | # - go test -v ./... 19 | - bash ./scripts/gofmt.sh 20 | - bash ./scripts/coverage.sh 21 | 22 | after_success: 23 | - bash <(curl -s https://codecov.io/bash) 24 | -------------------------------------------------------------------------------- /showcases/go-boot/plugins/debug.go: -------------------------------------------------------------------------------- 1 | package plugins 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/wxyyxc1992/go-boot/utils/encrypt" 7 | ) 8 | 9 | type Debug struct { 10 | Sender bool 11 | } 12 | 13 | func (d *Debug) Handle(header, body []byte) (h, b []byte) { 14 | if d.Sender { 15 | th, _ := encrypt.Decrypt(header) 16 | tb, _ := encrypt.Decrypt(body) 17 | 18 | fmt.Println("[send packet]", "header:", string(th), "body:", string(tb)) 19 | } else { 20 | fmt.Println("[receive packet]", "header:", string(header), "body:", string(body)) 21 | } 22 | 23 | return header, body 24 | } 25 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/pkg/errors.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | var ( 8 | ErrNotFound = errors.New("Error: Document not found") 9 | ErrNoContent = errors.New("Error: Document not found") 10 | ErrInvalidSlug = errors.New("Error: Invalid slug") 11 | ErrExists = errors.New("Error: Document already exists") 12 | ErrDatabase = errors.New("Error: Database error") 13 | ErrUnauthorized = errors.New("Error: You are not allowed to perform this action") 14 | ErrForbidden = errors.New("Error: Access to this resource is forbidden") 15 | ) 16 | -------------------------------------------------------------------------------- /showcases/db/dbinterface/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/agtorre/go-solutions/section5/database" 5 | "github.com/agtorre/go-solutions/section5/dbinterface" 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | func main() { 10 | db, err := database.Setup() 11 | if err != nil { 12 | panic(err) 13 | } 14 | 15 | tx, err := db.Begin() 16 | if err != nil { 17 | panic(err) 18 | } 19 | defer tx.Rollback() 20 | 21 | if err := dbinterface.Exec(db); err != nil { 22 | panic(err) 23 | } 24 | if err := tx.Commit(); err != nil { 25 | panic(err) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/internal/README.md: -------------------------------------------------------------------------------- 1 | # `/internal` 2 | 3 | Private application and library code. This is the code you don't want others importing in their applications or libraries. 4 | 5 | You can optionally add a bit of extra structure to your internal packages to separate your shared and non-shared internal code. It's not required, but it's nice to have visual clues showing the intended package use. Your actual application code can go in the `/internal/app` directory (e.g., `/internal/app/myapp`) and the code shared by those apps in the `/internal/pkg` directory (e.g., `/internal/pkg/myprivlib`). 6 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/sqlc/exec_tx.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | ) 7 | 8 | // ExecTx executes a function within a database transaction 9 | func (store *SQLStore) execTx(ctx context.Context, fn func(*Queries) error) error { 10 | tx, err := store.connPool.Begin(ctx) 11 | if err != nil { 12 | return err 13 | } 14 | 15 | q := New(tx) 16 | err = fn(q) 17 | if err != nil { 18 | if rbErr := tx.Rollback(ctx); rbErr != nil { 19 | return fmt.Errorf("tx err: %v, rb err: %v", err, rbErr) 20 | } 21 | return err 22 | } 23 | 24 | return tx.Commit(ctx) 25 | } 26 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/migration/000004_add_verify_emails.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE "verify_emails" ( 2 | "id" bigserial PRIMARY KEY, 3 | "username" varchar NOT NULL, 4 | "email" varchar NOT NULL, 5 | "secret_code" varchar NOT NULL, 6 | "is_used" bool NOT NULL DEFAULT false, 7 | "created_at" timestamptz NOT NULL DEFAULT (now()), 8 | "expired_at" timestamptz NOT NULL DEFAULT (now() + interval '15 minutes') 9 | ); 10 | 11 | ALTER TABLE "verify_emails" ADD FOREIGN KEY ("username") REFERENCES "users" ("username"); 12 | 13 | ALTER TABLE "users" ADD COLUMN "is_email_verified" bool NOT NULL DEFAULT false; 14 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/worker/distributor.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/hibiken/asynq" 7 | ) 8 | 9 | type TaskDistributor interface { 10 | DistributeTaskSendVerifyEmail( 11 | ctx context.Context, 12 | payload *PayloadSendVerifyEmail, 13 | opts ...asynq.Option, 14 | ) error 15 | } 16 | 17 | type RedisTaskDistributor struct { 18 | client *asynq.Client 19 | } 20 | 21 | func NewRedisTaskDistributor(redisOpt asynq.RedisClientOpt) TaskDistributor { 22 | client := asynq.NewClient(redisOpt) 23 | return &RedisTaskDistributor{ 24 | client: client, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /showcases/db/dbinterface/query.go: -------------------------------------------------------------------------------- 1 | package dbinterface 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/agtorre/go-solutions/section5/database" 7 | ) 8 | 9 | func Query(db DB) error { 10 | name := "Aaron" 11 | rows, err := db.Query("SELECT name, created FROM example where name=?", name) 12 | if err != nil { 13 | return err 14 | } 15 | defer rows.Close() 16 | for rows.Next() { 17 | var e database.Example 18 | if err := rows.Scan(&e.Name, &e.Created); err != nil { 19 | return err 20 | } 21 | fmt.Printf("Results:\n\tName: %s\n\tCreated: %v\n", e.Name, e.Created) 22 | } 23 | return rows.Err() 24 | } 25 | -------------------------------------------------------------------------------- /showcases/db/redis/sessions/memory.go: -------------------------------------------------------------------------------- 1 | package sessions 2 | 3 | import "errors" 4 | 5 | type memoryStore struct { 6 | sessions map[string]Session 7 | } 8 | 9 | func NewMemoryStore() Store { 10 | return &memoryStore{ 11 | sessions: make(map[string]Session), 12 | } 13 | } 14 | 15 | func (m memoryStore) Get(id string) (Session, error) { 16 | session, ok := m.sessions[id] 17 | if !ok { 18 | return Session{}, errors.New("session not found") 19 | } 20 | 21 | return session, nil 22 | } 23 | 24 | func (m *memoryStore) Set(id string, session Session) error { 25 | m.sessions[id] = session 26 | return nil 27 | } 28 | -------------------------------------------------------------------------------- /showcases/gloc/examples/files.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/hhatto/gocloc" 7 | ) 8 | 9 | func main() { 10 | languages := gocloc.NewDefinedLanguages() 11 | options := gocloc.NewClocOptions() 12 | paths := []string{ 13 | ".", 14 | } 15 | 16 | processor := gocloc.NewProcessor(languages, options) 17 | result, err := processor.Analyze(paths) 18 | if err != nil { 19 | fmt.Printf("gocloc fail. error: %v\n", err) 20 | return 21 | } 22 | 23 | for _, item := range result.Files { 24 | fmt.Println(item) 25 | } 26 | fmt.Println(result.Total) 27 | fmt.Printf("%+v", result) 28 | } 29 | -------------------------------------------------------------------------------- /showcases/db/database/query.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | 7 | _ "github.com/go-sql-driver/mysql" 8 | ) 9 | 10 | func Query(db *sql.DB) error { 11 | name := "Aaron" 12 | rows, err := db.Query("SELECT name, 13 | created FROM example where name=?", name) 14 | if err != nil { 15 | return err 16 | } 17 | defer rows.Close() 18 | for rows.Next() { 19 | var e Example 20 | if err := rows.Scan(&e.Name, &e.Created); err != nil { 21 | return err 22 | } 23 | fmt.Printf("Results:\n\tName: %s\n\tCreated: %v\n", 24 | e.Name, e.Created) 25 | } 26 | return rows.Err() 27 | } 28 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/test/README.md: -------------------------------------------------------------------------------- 1 | # `/test` 2 | 3 | Additional external test apps and test data. Feel free to structure the `/test` directory anyway you want. For bigger projects it makes sense to have a data subdirectory. For example, you can have `/test/data` or `/test/testdata` if you need Go to ignore what's in that directory. Note that Go will also ignore directories or files that begin with "." or "_", so you have more flexibility in terms of how you name your test data directory. 4 | 5 | Examples: 6 | 7 | * https://github.com/openshift/origin/tree/master/test (test data is in the `/testdata` subdirectory) 8 | 9 | 10 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/migration/000002_add_users.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE "users" ( 2 | "username" varchar PRIMARY KEY, 3 | "hashed_password" varchar NOT NULL, 4 | "full_name" varchar NOT NULL, 5 | "email" varchar UNIQUE NOT NULL, 6 | "password_changed_at" timestamptz NOT NULL DEFAULT('0001-01-01 00:00:00Z'), 7 | "created_at" timestamptz NOT NULL DEFAULT (now()) 8 | ); 9 | 10 | ALTER TABLE "accounts" ADD FOREIGN KEY ("owner") REFERENCES "users" ("username"); 11 | 12 | -- CREATE UNIQUE INDEX ON "accounts" ("owner", "currency"); 13 | ALTER TABLE "accounts" ADD CONSTRAINT "owner_currency_key" UNIQUE ("owner", "currency"); 14 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/proto/rpc_login_user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | import "user.proto"; 6 | import "google/protobuf/timestamp.proto"; 7 | 8 | option go_package = "github.com/techschool/simplebank/pb"; 9 | 10 | message LoginUserRequest { 11 | string username = 1; 12 | string password = 2; 13 | } 14 | 15 | message LoginUserResponse { 16 | User user = 1; 17 | string session_id = 2; 18 | string access_token = 3; 19 | string refresh_token = 4; 20 | google.protobuf.Timestamp access_token_expires_at = 5; 21 | google.protobuf.Timestamp refresh_token_expires_at = 6; 22 | } 23 | -------------------------------------------------------------------------------- /showcases/gloc/examples/languages.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/hhatto/gocloc" 7 | ) 8 | 9 | func main() { 10 | languages := gocloc.NewDefinedLanguages() 11 | options := gocloc.NewClocOptions() 12 | paths := []string{ 13 | ".", 14 | } 15 | 16 | processor := gocloc.NewProcessor(languages, options) 17 | result, err := processor.Analyze(paths) 18 | if err != nil { 19 | fmt.Printf("gocloc fail. error: %v\n", err) 20 | return 21 | } 22 | 23 | for _, lang := range result.Languages { 24 | fmt.Println(lang) 25 | } 26 | fmt.Println(result.Total) 27 | fmt.Printf("%+v", result) 28 | } 29 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/sqlc/main_test.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "os" 7 | "testing" 8 | 9 | "github.com/jackc/pgx/v5/pgxpool" 10 | "github.com/techschool/simplebank/util" 11 | ) 12 | 13 | var testStore Store 14 | 15 | func TestMain(m *testing.M) { 16 | config, err := util.LoadConfig("../..") 17 | if err != nil { 18 | log.Fatal("cannot load config:", err) 19 | } 20 | 21 | connPool, err := pgxpool.New(context.Background(), config.DBSource) 22 | if err != nil { 23 | log.Fatal("cannot connect to db:", err) 24 | } 25 | 26 | testStore = NewStore(connPool) 27 | os.Exit(m.Run()) 28 | } 29 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/eks/ingress-http.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: simple-bank-ingress-http 5 | annotations: 6 | cert-manager.io/cluster-issuer: letsencrypt 7 | spec: 8 | ingressClassName: nginx 9 | rules: 10 | - host: "api.simplebanktest.com" 11 | http: 12 | paths: 13 | - pathType: Prefix 14 | path: "/" 15 | backend: 16 | service: 17 | name: simple-bank-api-service 18 | port: 19 | number: 80 20 | tls: 21 | - hosts: 22 | - api.simplebanktest.com 23 | secretName: simple-bank-api-cert 24 | -------------------------------------------------------------------------------- /showcases/db/redis/sort.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "fmt" 5 | 6 | redis "gopkg.in/redis.v5" 7 | ) 8 | 9 | func Sort() error { 10 | conn, err := Setup() 11 | if err != nil { 12 | return err 13 | } 14 | 15 | if err := conn.LPush("list", 1).Err(); err != nil { 16 | return err 17 | } 18 | if err := conn.LPush("list", 3).Err(); err != nil { 19 | return err 20 | } 21 | if err := conn.LPush("list", 2).Err(); err != nil { 22 | return err 23 | } 24 | 25 | res, err := conn.Sort("list", redis.Sort{Order: "ASC"}).Result() 26 | if err != nil { 27 | return err 28 | } 29 | fmt.Println(res) 30 | conn.Del("list") 31 | return nil 32 | } 33 | -------------------------------------------------------------------------------- /showcases/gloc/utils_test.go: -------------------------------------------------------------------------------- 1 | package gocloc 2 | 3 | import "testing" 4 | 5 | func TestContainComments(t *testing.T) { 6 | line := "/* hoge */" 7 | st := "/*" 8 | ed := "*/" 9 | if containComments(line, st, ed) { 10 | t.Errorf("invalid") 11 | } 12 | 13 | line = "/* comment" 14 | if !containComments(line, st, ed) { 15 | t.Errorf("invalid") 16 | } 17 | } 18 | 19 | func TestCheckMD5SumIgnore(t *testing.T) { 20 | fileCache := make(map[string]struct{}) 21 | 22 | if checkMD5Sum("./utils_test.go", fileCache) { 23 | t.Errorf("invalid sequence") 24 | } 25 | if !checkMD5Sum("./utils_test.go", fileCache) { 26 | t.Errorf("invalid sequence") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /showcases/go-boot/hook.go: -------------------------------------------------------------------------------- 1 | package go_boot 2 | 3 | import ( 4 | "net" 5 | "sync" 6 | 7 | "github.com/gorilla/websocket" 8 | ) 9 | 10 | // fix panic as websocket concurrency write 11 | type webSocketConn struct { 12 | mutex sync.Mutex 13 | conn *websocket.Conn 14 | } 15 | 16 | func (ws *webSocketConn) WriteMessage(messageType int, data []byte) error { 17 | ws.mutex.Lock() 18 | err := ws.conn.WriteMessage(messageType, data) 19 | ws.mutex.Unlock() 20 | 21 | return err 22 | } 23 | 24 | func (ws *webSocketConn) LocalAddr() net.Addr { 25 | return ws.conn.LocalAddr() 26 | } 27 | 28 | func (ws *webSocketConn) RemoteAddr() net.Addr { 29 | return ws.conn.RemoteAddr() 30 | } 31 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/api/controller/profile_controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 7 | "github.com/gin-gonic/gin" 8 | ) 9 | 10 | type ProfileController struct { 11 | ProfileUsecase domain.ProfileUsecase 12 | } 13 | 14 | func (pc *ProfileController) Fetch(c *gin.Context) { 15 | userID := c.GetString("x-user-id") 16 | 17 | profile, err := pc.ProfileUsecase.GetProfileByID(c, userID) 18 | if err != nil { 19 | c.JSON(http.StatusInternalServerError, domain.ErrorResponse{Message: err.Error()}) 20 | return 21 | } 22 | 23 | c.JSON(http.StatusOK, profile) 24 | } 25 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/pkg/user/repository.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Repository interface { 8 | FindByID(ctx context.Context, id uint) (*User, error) 9 | 10 | BuildProfile(ctx context.Context, user *User) (*User, error) 11 | 12 | CreateMinimal(ctx context.Context, email, password, phoneNumber string) (*User, error) 13 | 14 | FindByEmailAndPassword(ctx context.Context, email, password string) (*User, error) 15 | 16 | FindByEmail(ctx context.Context, email string) (*User, error) 17 | 18 | DoesEmailExist(ctx context.Context, email string) (bool, error) 19 | 20 | ChangePassword(ctx context.Context, email, password string) error 21 | } 22 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/pkg/admin/repository.go: -------------------------------------------------------------------------------- 1 | package admin 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Repository interface { 8 | FindByID(ctx context.Context, id uint) (*Admin, error) 9 | 10 | BuildProfile(ctx context.Context, user *Admin) (*Admin, error) 11 | 12 | CreateMinimal(ctx context.Context, email, password, phoneNumber string) (*Admin, error) 13 | 14 | FindByEmailAndPassword(ctx context.Context, email, password string) (*Admin, error) 15 | 16 | FindByEmail(ctx context.Context, email string) (*Admin, error) 17 | 18 | DoesEmailExist(ctx context.Context, email string) (bool, error) 19 | 20 | ChangePassword(ctx context.Context, email, password string) error 21 | } 22 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "time" 5 | 6 | routeV1 "github.com/amitshekhariitbhu/go-backend-clean-architecture/api/route/v1" 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/bootstrap" 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | func main() { 12 | 13 | app := bootstrap.App() 14 | 15 | env := app.Env 16 | 17 | db := app.Mongo.Database(env.DBName) 18 | defer app.CloseDBConnection() 19 | 20 | timeout := time.Duration(env.ContextTimeout) * time.Second 21 | 22 | gin := gin.Default() 23 | 24 | routerV1 := gin.Group("v1") 25 | 26 | routeV1.Setup(env, timeout, db, routerV1) 27 | 28 | gin.Run(env.ServerAddress) 29 | } 30 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/api/main_test.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | "time" 7 | 8 | "github.com/gin-gonic/gin" 9 | "github.com/stretchr/testify/require" 10 | db "github.com/techschool/simplebank/db/sqlc" 11 | "github.com/techschool/simplebank/util" 12 | ) 13 | 14 | func newTestServer(t *testing.T, store db.Store) *Server { 15 | config := util.Config{ 16 | TokenSymmetricKey: util.RandomString(32), 17 | AccessTokenDuration: time.Minute, 18 | } 19 | 20 | server, err := NewServer(config, store) 21 | require.NoError(t, err) 22 | 23 | return server 24 | } 25 | 26 | func TestMain(m *testing.M) { 27 | gin.SetMode(gin.TestMode) 28 | 29 | os.Exit(m.Run()) 30 | } 31 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/eks/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: simple-bank-api-deployment 5 | labels: 6 | app: simple-bank-api 7 | spec: 8 | replicas: 2 9 | selector: 10 | matchLabels: 11 | app: simple-bank-api 12 | template: 13 | metadata: 14 | labels: 15 | app: simple-bank-api 16 | spec: 17 | containers: 18 | - name: simple-bank-api 19 | image: 760486049168.dkr.ecr.eu-west-1.amazonaws.com/simplebank:latest 20 | imagePullPolicy: Always 21 | ports: 22 | - containerPort: 8080 23 | name: http-server 24 | - containerPort: 9090 25 | name: grpc-server 26 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/domain/login.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type LoginRequest struct { 8 | Email string `form:"email" binding:"required,email"` 9 | Password string `form:"password" binding:"required"` 10 | } 11 | 12 | type LoginResponse struct { 13 | AccessToken string `json:"accessToken"` 14 | RefreshToken string `json:"refreshToken"` 15 | } 16 | 17 | type LoginUsecase interface { 18 | GetUserByEmail(c context.Context, email string) (User, error) 19 | CreateAccessToken(user *User, secret string, expiry int) (accessToken string, err error) 20 | CreateRefreshToken(user *User, secret string, expiry int) (refreshToken string, err error) 21 | } 22 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/domain/user.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "context" 5 | 6 | "go.mongodb.org/mongo-driver/bson/primitive" 7 | ) 8 | 9 | const ( 10 | CollectionUser = "users" 11 | ) 12 | 13 | type User struct { 14 | ID primitive.ObjectID `bson:"_id"` 15 | Name string `bson:"name"` 16 | Email string `bson:"email"` 17 | Password string `bson:"password"` 18 | } 19 | 20 | type UserRepository interface { 21 | Create(c context.Context, user *User) error 22 | Fetch(c context.Context) ([]User, error) 23 | GetByEmail(c context.Context, email string) (User, error) 24 | GetByID(c context.Context, id string) (User, error) 25 | } 26 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/sqlc/tx_create_user.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import "context" 4 | 5 | type CreateUserTxParams struct { 6 | CreateUserParams 7 | AfterCreate func(user User) error 8 | } 9 | 10 | type CreateUserTxResult struct { 11 | User User 12 | } 13 | 14 | func (store *SQLStore) CreateUserTx(ctx context.Context, arg CreateUserTxParams) (CreateUserTxResult, error) { 15 | var result CreateUserTxResult 16 | 17 | err := store.execTx(ctx, func(q *Queries) error { 18 | var err error 19 | 20 | result.User, err = q.CreateUser(ctx, arg.CreateUserParams) 21 | if err != nil { 22 | return err 23 | } 24 | 25 | return arg.AfterCreate(result.User) 26 | }) 27 | 28 | return result, err 29 | } 30 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/doc/swagger/swagger-initializer.js: -------------------------------------------------------------------------------- 1 | window.onload = function() { 2 | // 3 | 4 | // the following lines will be replaced by docker/configurator, when it runs in a docker-container 5 | window.ui = SwaggerUIBundle({ 6 | url: "simple_bank.swagger.json", 7 | dom_id: '#swagger-ui', 8 | deepLinking: true, 9 | presets: [ 10 | SwaggerUIBundle.presets.apis, 11 | SwaggerUIStandalonePreset 12 | ], 13 | plugins: [ 14 | SwaggerUIBundle.plugins.DownloadUrl 15 | ], 16 | layout: "StandaloneLayout" 17 | }); 18 | 19 | // 20 | }; -------------------------------------------------------------------------------- /showcases/go-boot/plugins/cryption.go: -------------------------------------------------------------------------------- 1 | package plugins 2 | 3 | import "github.com/wxyyxc1992/go-boot/utils/encrypt" 4 | 5 | type Encryption struct{} 6 | 7 | func (e *Encryption) Handle(header, body []byte) (h, b []byte) { 8 | h, err := encrypt.Encrypt(header) 9 | if err != nil { 10 | return 11 | } 12 | 13 | b, err = encrypt.Encrypt(body) 14 | if err != nil { 15 | return 16 | } 17 | 18 | return 19 | } 20 | 21 | type Decryption struct{} 22 | 23 | func (d *Decryption) Handle(header, body []byte) (h, b []byte) { 24 | h, err := encrypt.Decrypt(header) 25 | if err != nil { 26 | return 27 | } 28 | 29 | b, err = encrypt.Decrypt(body) 30 | if err != nil { 31 | return 32 | } 33 | 34 | return 35 | } 36 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/util/password.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | 6 | "golang.org/x/crypto/bcrypt" 7 | ) 8 | 9 | // HashPassword returns the bcrypt hash of the password 10 | func HashPassword(password string) (string, error) { 11 | hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) 12 | if err != nil { 13 | return "", fmt.Errorf("failed to hash password: %w", err) 14 | } 15 | return string(hashedPassword), nil 16 | } 17 | 18 | // CheckPassword checks if the provided password is correct or not 19 | func CheckPassword(password string, hashedPassword string) error { 20 | return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) 21 | } 22 | -------------------------------------------------------------------------------- /showcases/db/redis/cmd/qclient/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "time" 6 | 7 | redis "gopkg.in/redis.v4" 8 | ) 9 | 10 | func main() { 11 | client := redis.NewClient(&redis.Options{ 12 | Addr: "localhost:6379", 13 | Password: "", // no password set 14 | DB: 0, // use default DB 15 | }) 16 | 17 | _, err := client.Ping().Result() 18 | if err != nil { 19 | log.Fatalf("Failed to ping Redis: %v", err) 20 | } 21 | 22 | for { 23 | time.Sleep(5 * time.Second) 24 | 25 | task, err := client.BLPop(0, "queue-key").Result() 26 | if err != nil { 27 | log.Fatalf("Failed to get task from queue: %v\n", err) 28 | } 29 | 30 | log.Printf("Working on '%s' task...\n", task[1]) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /showcases/go-boot/utils/codec/protobuf.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/golang/protobuf/proto" 7 | ) 8 | 9 | type ProtoBufCoder struct{} 10 | 11 | func (c *ProtoBufCoder) Encoder(data interface{}) ([]byte, error) { 12 | v, ok := data.(proto.Message) 13 | if !ok { 14 | return nil, errors.New("unsupported data for protobuf") 15 | } 16 | 17 | return proto.Marshal(v) 18 | } 19 | 20 | func (c *ProtoBufCoder) Decoder(data []byte, des interface{}) error { 21 | v, ok := des.(proto.Message) 22 | if !ok { 23 | return errors.New("unsupported data for protobuf") 24 | } 25 | 26 | return proto.Unmarshal(data, v) 27 | } 28 | 29 | func init() { 30 | Register(PROTOBUF, &ProtoBufCoder{}) 31 | } 32 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | web: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | image: app 9 | container_name: app 10 | restart: unless-stopped 11 | env_file: .env 12 | ports: 13 | - "$PORT:$PORT" 14 | depends_on: 15 | - mongodb 16 | 17 | mongodb: 18 | image: mongo:6.0 19 | container_name: mongodb 20 | restart: unless-stopped 21 | env_file: .env 22 | environment: 23 | - MONGO_INITDB_ROOT_USERNAME=$DB_USER 24 | - MONGO_INITDB_ROOT_PASSWORD=$DB_PASS 25 | ports: 26 | - "$DB_PORT:$DB_PORT" 27 | volumes: 28 | - dbdata:/data/db 29 | 30 | volumes: 31 | dbdata: 32 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/sqlc/db.go: -------------------------------------------------------------------------------- 1 | // Code generated by sqlc. DO NOT EDIT. 2 | // versions: 3 | // sqlc v1.22.0 4 | 5 | package db 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/jackc/pgx/v5" 11 | "github.com/jackc/pgx/v5/pgconn" 12 | ) 13 | 14 | type DBTX interface { 15 | Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) 16 | Query(context.Context, string, ...interface{}) (pgx.Rows, error) 17 | QueryRow(context.Context, string, ...interface{}) pgx.Row 18 | } 19 | 20 | func New(db DBTX) *Queries { 21 | return &Queries{db: db} 22 | } 23 | 24 | type Queries struct { 25 | db DBTX 26 | } 27 | 28 | func (q *Queries) WithTx(tx pgx.Tx) *Queries { 29 | return &Queries{ 30 | db: tx, 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/domain/refresh_token.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type RefreshTokenRequest struct { 8 | RefreshToken string `form:"refreshToken" binding:"required"` 9 | } 10 | 11 | type RefreshTokenResponse struct { 12 | AccessToken string `json:"accessToken"` 13 | RefreshToken string `json:"refreshToken"` 14 | } 15 | 16 | type RefreshTokenUsecase interface { 17 | GetUserByID(c context.Context, id string) (User, error) 18 | CreateAccessToken(user *User, secret string, expiry int) (accessToken string, err error) 19 | CreateRefreshToken(user *User, secret string, expiry int) (refreshToken string, err error) 20 | ExtractIDFromToken(requestToken string, secret string) (string, error) 21 | } 22 | -------------------------------------------------------------------------------- /showcases/db/firebase/client.go: -------------------------------------------------------------------------------- 1 | package firebase 2 | 3 | import ( 4 | "log" 5 | 6 | "gopkg.in/zabawaba99/firego.v1" 7 | ) 8 | 9 | type Client interface { 10 | Get() (map[string]interface{}, error) 11 | Set(key string, value interface{}) error 12 | } 13 | type firebaseClient struct { 14 | *firego.Firebase 15 | } 16 | 17 | func (f *firebaseClient) Get() (map[string]interface{}, error) { 18 | var v2 map[string]interface{} 19 | if err := f.Value(&v2); err != nil { 20 | log.Fatalf("error getting") 21 | } 22 | return v2, nil 23 | } 24 | 25 | func (f *firebaseClient) Set(key string, value interface{}) error { 26 | v := map[string]interface{}{key: value} 27 | if err := f.Firebase.Set(v); err != nil { 28 | return err 29 | } 30 | return nil 31 | } 32 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/eks/ingress-grpc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: simple-bank-ingress-grpc 5 | annotations: 6 | cert-manager.io/cluster-issuer: letsencrypt 7 | nginx.ingress.kubernetes.io/ssl-redirect: "true" 8 | nginx.ingress.kubernetes.io/backend-protocol: "GRPC" 9 | spec: 10 | ingressClassName: nginx 11 | rules: 12 | - host: "gapi.simplebanktest.com" 13 | http: 14 | paths: 15 | - pathType: Prefix 16 | path: "/" 17 | backend: 18 | service: 19 | name: simple-bank-api-service 20 | port: 21 | number: 90 22 | tls: 23 | - hosts: 24 | - gapi.simplebanktest.com 25 | secretName: simple-bank-gapi-cert 26 | -------------------------------------------------------------------------------- /showcases/db/mongodb/exec.go: -------------------------------------------------------------------------------- 1 | package mongodb 2 | 3 | import ( 4 | "fmt" 5 | 6 | "gopkg.in/mgo.v2/bson" 7 | ) 8 | 9 | type State struct { 10 | Name string `bson:"name"` 11 | Population int `bson:"pop"` 12 | } 13 | 14 | func Exec() error { 15 | db, err := Setup() 16 | if err != nil { 17 | return err 18 | } 19 | 20 | conn := db.DB("gosolutions").C("example") 21 | 22 | if err := conn.Insert(&State{"Washington", 7062000}, &State{"Oregon", 3970000}); err != nil { 23 | return err 24 | } 25 | 26 | var s State 27 | if err := conn.Find(bson.M{"name": "Washington"}).One(&s); err != nil { 28 | return err 29 | } 30 | 31 | if err := conn.DropCollection(); err != nil { 32 | return err 33 | } 34 | 35 | fmt.Printf("State: %#v\n", s) 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/domain/task.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "context" 5 | 6 | "go.mongodb.org/mongo-driver/bson/primitive" 7 | ) 8 | 9 | const ( 10 | CollectionTask = "tasks" 11 | ) 12 | 13 | type Task struct { 14 | ID primitive.ObjectID `bson:"_id" json:"-"` 15 | Title string `bson:"title" form:"title" binding:"required" json:"title"` 16 | UserID primitive.ObjectID `bson:"userID" json:"-"` 17 | } 18 | 19 | type TaskRepository interface { 20 | Create(c context.Context, task *Task) error 21 | FetchByUserID(c context.Context, userID string) ([]Task, error) 22 | } 23 | 24 | type TaskUsecase interface { 25 | Create(c context.Context, task *Task) error 26 | FetchByUserID(c context.Context, userID string) ([]Task, error) 27 | } 28 | -------------------------------------------------------------------------------- /showcases/db/firebase/auth.go: -------------------------------------------------------------------------------- 1 | package firebase 2 | 3 | import ( 4 | "io/ioutil" 5 | 6 | "golang.org/x/oauth2" 7 | "golang.org/x/oauth2/google" 8 | "gopkg.in/zabawaba99/firego.v1" 9 | ) 10 | // https://console.firebase.google.com/project/project name/settings/serviceaccounts/adminsdk 11 | func Authenticate() (Client, error) { 12 | d, err := ioutil.ReadFile("/tmp/service_account.json") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | conf, err := google.JWTConfigFromJSON(d, "https://www.googleapis.com/auth/userinfo.email", 18 | "https://www.googleapis.com/auth/firebase.database") 19 | if err != nil { 20 | return nil, err 21 | } 22 | f := firego.New("https://go-solutions.firebaseio.com", conf.Client(oauth2.NoContext)) 23 | return &firebaseClient{f}, err 24 | } 25 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/query/user.sql: -------------------------------------------------------------------------------- 1 | -- name: CreateUser :one 2 | INSERT INTO users ( 3 | username, 4 | hashed_password, 5 | full_name, 6 | email 7 | ) VALUES ( 8 | $1, $2, $3, $4 9 | ) RETURNING *; 10 | 11 | -- name: GetUser :one 12 | SELECT * FROM users 13 | WHERE username = $1 LIMIT 1; 14 | 15 | -- name: UpdateUser :one 16 | UPDATE users 17 | SET 18 | hashed_password = COALESCE(sqlc.narg(hashed_password), hashed_password), 19 | password_changed_at = COALESCE(sqlc.narg(password_changed_at), password_changed_at), 20 | full_name = COALESCE(sqlc.narg(full_name), full_name), 21 | email = COALESCE(sqlc.narg(email), email), 22 | is_email_verified = COALESCE(sqlc.narg(is_email_verified), is_email_verified) 23 | WHERE 24 | username = sqlc.arg(username) 25 | RETURNING *; 26 | -------------------------------------------------------------------------------- /showcases/db/redis/sessions/middleware.go: -------------------------------------------------------------------------------- 1 | package sessions 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/labstack/echo" 7 | uuid "github.com/satori/go.uuid" 8 | ) 9 | 10 | func Middleware(store Store) echo.MiddlewareFunc { 11 | return func(hf echo.HandlerFunc) echo.HandlerFunc { 12 | return func(ectx echo.Context) error { 13 | cookie, err := ectx.Cookie("sessionID") 14 | if err != nil { 15 | sessionID := uuid.NewV4().String() 16 | ectx.SetCookie(&http.Cookie{ 17 | Name: "sessionID", 18 | Value: sessionID, 19 | }) 20 | ectx.Set("sessionID", sessionID) 21 | store.Set(sessionID, Session{}) 22 | return hf(ectx) 23 | } 24 | 25 | sessionID := cookie.Value 26 | ectx.Set("sessionID", sessionID) 27 | return hf(ectx) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "mode": "dev", 3 | "server_dev": { 4 | "host": "0.0.0.0", 5 | "port": "3000" 6 | }, 7 | "server_prod": { 8 | "host": "0.0.0.0", 9 | "port": "443", 10 | "cert_path": "", 11 | "key_path": "" 12 | }, 13 | "database_dev": { 14 | "host": "127.0.0.1", 15 | "port": "5432", 16 | "user": "angad", 17 | "password": "1234", 18 | "dbname": "mhrd", 19 | "sslmode": "disable" 20 | }, 21 | "database_prod": { 22 | "host": "", 23 | "port": "", 24 | "user": "", 25 | "password": "", 26 | "dbname": "", 27 | "sslmode": "enable" 28 | }, 29 | "context": { 30 | "timeout": 10 31 | }, 32 | "jwt_secret": "L04DB4L4NC3R", 33 | 34 | "POSTGRES_PASSWORD_dev":"1234", 35 | "POSTGRES_USER_dev":"angad", 36 | "POSTGRES_DB_dev":"mhrd" 37 | } 38 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/domain/signup.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type SignupRequest struct { 8 | Name string `form:"name" binding:"required"` 9 | Email string `form:"email" binding:"required,email"` 10 | Password string `form:"password" binding:"required"` 11 | } 12 | 13 | type SignupResponse struct { 14 | AccessToken string `json:"accessToken"` 15 | RefreshToken string `json:"refreshToken"` 16 | } 17 | 18 | type SignupUsecase interface { 19 | Create(c context.Context, user *User) error 20 | GetUserByEmail(c context.Context, email string) (User, error) 21 | CreateAccessToken(user *User, secret string, expiry int) (accessToken string, err error) 22 | CreateRefreshToken(user *User, secret string, expiry int) (refreshToken string, err error) 23 | } 24 | -------------------------------------------------------------------------------- /showcases/db/storage/exec.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | ) 7 | 8 | func Exec() error { 9 | m, err := NewMongoStorage("localhost", "gosolutions", "items") 10 | if err != nil { 11 | return err 12 | } 13 | if err := PerformOperations(m); err != nil { 14 | return err 15 | } 16 | 17 | if err := m.Session.DB(m.DB).C(m.Collection).DropCollection(); err != nil { 18 | return err 19 | } 20 | 21 | return nil 22 | } 23 | 24 | func PerformOperations(s Storage) error { 25 | ctx := context.Background() 26 | i := Item{Name: "candles", Price: 100} 27 | if err := s.Put(ctx, &i); err != nil { 28 | return err 29 | } 30 | 31 | candles, err := s.GetByName(ctx, "candles") 32 | if err != nil { 33 | return err 34 | } 35 | fmt.Printf("Result: %#v\n", candles) 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/doc/swagger/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/util/password_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | "golang.org/x/crypto/bcrypt" 8 | ) 9 | 10 | func TestPassword(t *testing.T) { 11 | password := RandomString(6) 12 | 13 | hashedPassword1, err := HashPassword(password) 14 | require.NoError(t, err) 15 | require.NotEmpty(t, hashedPassword1) 16 | 17 | err = CheckPassword(password, hashedPassword1) 18 | require.NoError(t, err) 19 | 20 | wrongPassword := RandomString(6) 21 | err = CheckPassword(wrongPassword, hashedPassword1) 22 | require.EqualError(t, err, bcrypt.ErrMismatchedHashAndPassword.Error()) 23 | 24 | hashedPassword2, err := HashPassword(password) 25 | require.NoError(t, err) 26 | require.NotEmpty(t, hashedPassword2) 27 | require.NotEqual(t, hashedPassword1, hashedPassword2) 28 | } 29 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/mail/sender_test.go: -------------------------------------------------------------------------------- 1 | package mail 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | "github.com/techschool/simplebank/util" 8 | ) 9 | 10 | func TestSendEmailWithGmail(t *testing.T) { 11 | if testing.Short() { 12 | t.Skip() 13 | } 14 | 15 | config, err := util.LoadConfig("..") 16 | require.NoError(t, err) 17 | 18 | sender := NewGmailSender(config.EmailSenderName, config.EmailSenderAddress, config.EmailSenderPassword) 19 | 20 | subject := "A test email" 21 | content := ` 22 |

Hello world

23 |

This is a test message from Tech School

24 | ` 25 | to := []string{"techschool.guru@gmail.com"} 26 | attachFiles := []string{"../README.md"} 27 | 28 | err = sender.SendEmail(subject, content, to, nil, nil, attachFiles) 29 | require.NoError(t, err) 30 | } 31 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/sqlc/store.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/jackc/pgx/v5/pgxpool" 7 | ) 8 | 9 | // Store defines all functions to execute db queries and transactions 10 | type Store interface { 11 | Querier 12 | TransferTx(ctx context.Context, arg TransferTxParams) (TransferTxResult, error) 13 | CreateUserTx(ctx context.Context, arg CreateUserTxParams) (CreateUserTxResult, error) 14 | VerifyEmailTx(ctx context.Context, arg VerifyEmailTxParams) (VerifyEmailTxResult, error) 15 | } 16 | 17 | // SQLStore provides all functions to execute SQL queries and transactions 18 | type SQLStore struct { 19 | connPool *pgxpool.Pool 20 | *Queries 21 | } 22 | 23 | // NewStore creates a new store 24 | func NewStore(connPool *pgxpool.Pool) Store { 25 | return &SQLStore{ 26 | connPool: connPool, 27 | Queries: New(connPool), 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /showcases/db/redis/cmd/pserver/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "log" 6 | 7 | redis "gopkg.in/redis.v4" 8 | ) 9 | 10 | var task string 11 | 12 | func init() { 13 | flag.StringVar(&task, "task", "", "task to be handled by client") 14 | } 15 | 16 | func main() { 17 | flag.Parse() 18 | 19 | if task == "" { 20 | log.Fatal("Task must not be empty") 21 | } 22 | 23 | client := redis.NewClient(&redis.Options{ 24 | Addr: "localhost:6379", 25 | Password: "", // no password set 26 | DB: 0, // use default DB 27 | }) 28 | 29 | _, err := client.Ping().Result() 30 | if err != nil { 31 | log.Fatalf("Failed to ping Redis: %v", err) 32 | } 33 | 34 | if err := client.Publish("pubsub-key", task).Err(); err != nil { 35 | log.Fatalf("Failed to put stuff into queue: %v", err) 36 | } 37 | log.Printf("'%v' task put into queue", task) 38 | } 39 | -------------------------------------------------------------------------------- /showcases/db/redis/cmd/qserver/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "log" 6 | 7 | redis "gopkg.in/redis.v4" 8 | ) 9 | 10 | var task string 11 | 12 | func init() { 13 | flag.StringVar(&task, "task", "", "task to be handled by client") 14 | } 15 | 16 | func main() { 17 | flag.Parse() 18 | 19 | if task == "" { 20 | log.Fatal("Task must not be empty") 21 | } 22 | 23 | client := redis.NewClient(&redis.Options{ 24 | Addr: "localhost:6379", 25 | Password: "", // no password set 26 | DB: 0, // use default DB 27 | }) 28 | 29 | _, err := client.Ping().Result() 30 | if err != nil { 31 | log.Fatalf("Failed to ping Redis: %v", err) 32 | } 33 | 34 | if err := client.RPush("queue-key", task).Err(); err != nil { 35 | log.Fatalf("Failed to put stuff into queue: %v", err) 36 | } 37 | log.Printf("'%v' task put into queue", task) 38 | } 39 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/query/account.sql: -------------------------------------------------------------------------------- 1 | -- name: CreateAccount :one 2 | INSERT INTO accounts ( 3 | owner, 4 | balance, 5 | currency 6 | ) VALUES ( 7 | $1, $2, $3 8 | ) RETURNING *; 9 | 10 | -- name: GetAccount :one 11 | SELECT * FROM accounts 12 | WHERE id = $1 LIMIT 1; 13 | 14 | -- name: GetAccountForUpdate :one 15 | SELECT * FROM accounts 16 | WHERE id = $1 LIMIT 1 17 | FOR NO KEY UPDATE; 18 | 19 | -- name: ListAccounts :many 20 | SELECT * FROM accounts 21 | WHERE owner = $1 22 | ORDER BY id 23 | LIMIT $2 24 | OFFSET $3; 25 | 26 | -- name: UpdateAccount :one 27 | UPDATE accounts 28 | SET balance = $2 29 | WHERE id = $1 30 | RETURNING *; 31 | 32 | -- name: AddAccountBalance :one 33 | UPDATE accounts 34 | SET balance = balance + sqlc.arg(amount) 35 | WHERE id = sqlc.arg(id) 36 | RETURNING *; 37 | 38 | -- name: DeleteAccount :exec 39 | DELETE FROM accounts 40 | WHERE id = $1; 41 | -------------------------------------------------------------------------------- /showcases/go-boot/utils/codec/codec.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import "fmt" 4 | 5 | const ( 6 | JSON = "text/json" 7 | PROTOBUF = "text/protobuf" 8 | String = "text/string" 9 | XML = "text/xml" 10 | ) 11 | 12 | type Coder interface { 13 | Encoder(data interface{}) ([]byte, error) 14 | Decoder(data []byte, v interface{}) error 15 | } 16 | 17 | var adapters = make(map[string]Coder) 18 | 19 | func Register(name string, adapter Coder) { 20 | if adapter == nil { 21 | panic("codec: register adapter is nil") 22 | } 23 | 24 | if _, ok := adapters["name"]; ok { 25 | panic("codec: register called twice for adapter " + name) 26 | } 27 | 28 | adapters[name] = adapter 29 | } 30 | 31 | func NewCoder(adapterName string) (Coder, error) { 32 | if v, ok := adapters[adapterName]; ok { 33 | return v, nil 34 | } 35 | 36 | return nil, fmt.Errorf("codec: unknown adapter name %q (forgot to import?)", adapterName) 37 | } 38 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/api/route/v1/profile_route.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/api/controller" 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/bootstrap" 8 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 9 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/mongo" 10 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/repository" 11 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/usecase" 12 | "github.com/gin-gonic/gin" 13 | ) 14 | 15 | func NewProfileRouter(env *bootstrap.Env, timeout time.Duration, db mongo.Database, group *gin.RouterGroup) { 16 | ur := repository.NewUserRepository(db, domain.CollectionUser) 17 | pc := &controller.ProfileController{ 18 | ProfileUsecase: usecase.NewProfileUsecase(ur, timeout), 19 | } 20 | group.GET("/profile", pc.Fetch) 21 | } 22 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/usecase/profile_usecase.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 8 | ) 9 | 10 | type profileUsecase struct { 11 | userRepository domain.UserRepository 12 | contextTimeout time.Duration 13 | } 14 | 15 | func NewProfileUsecase(userRepository domain.UserRepository, timeout time.Duration) domain.ProfileUsecase { 16 | return &profileUsecase{ 17 | userRepository: userRepository, 18 | contextTimeout: timeout, 19 | } 20 | } 21 | 22 | func (pu *profileUsecase) GetProfileByID(c context.Context, userID string) (*domain.Profile, error) { 23 | ctx, cancel := context.WithTimeout(c, pu.contextTimeout) 24 | defer cancel() 25 | 26 | user, err := pu.userRepository.GetByID(ctx, userID) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | return &domain.Profile{Name: user.Name, Email: user.Email}, nil 32 | } 33 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/api/route/v1/login_route.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/api/controller" 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/bootstrap" 8 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 9 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/mongo" 10 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/repository" 11 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/usecase" 12 | "github.com/gin-gonic/gin" 13 | ) 14 | 15 | func NewLoginRouter(env *bootstrap.Env, timeout time.Duration, db mongo.Database, group *gin.RouterGroup) { 16 | ur := repository.NewUserRepository(db, domain.CollectionUser) 17 | lc := &controller.LoginController{ 18 | LoginUsecase: usecase.NewLoginUsecase(ur, timeout), 19 | Env: env, 20 | } 21 | group.POST("/login", lc.Login) 22 | } 23 | -------------------------------------------------------------------------------- /showcases/go-boot/retry.go: -------------------------------------------------------------------------------- 1 | package go_boot 2 | 3 | import ( 4 | "sync" 5 | "time" 6 | ) 7 | 8 | var ( 9 | rt *ReTry 10 | once sync.Once 11 | ) 12 | 13 | type ReTry struct { 14 | items sync.Map 15 | timeout time.Duration 16 | } 17 | 18 | type Item struct { 19 | Channel string 20 | Ctx Context 21 | Value interface{} 22 | } 23 | 24 | func NewRetry(timeout time.Duration) *ReTry { 25 | once.Do(func() { 26 | rt = &ReTry{items: sync.Map{}, timeout: timeout} 27 | }) 28 | 29 | return rt 30 | } 31 | 32 | func (rt *ReTry) Put(key interface{}, value *Item) { 33 | rt.items.Store(key, value) 34 | 35 | go func(rt *ReTry) { 36 | <-time.NewTimer(rt.timeout).C 37 | if v, ok := rt.items.Load(key); ok { 38 | if i, ok := v.(*Item); ok { 39 | i.Ctx.Write(i.Channel, i.Value) 40 | rt.Delete(key) 41 | } 42 | } 43 | 44 | return 45 | }(rt) 46 | } 47 | 48 | func (rt *ReTry) Delete(key interface{}) { 49 | rt.items.Delete(key) 50 | } 51 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/api/route/v1/task_route.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/api/controller" 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/bootstrap" 8 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 9 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/mongo" 10 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/repository" 11 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/usecase" 12 | "github.com/gin-gonic/gin" 13 | ) 14 | 15 | func NewTaskRouter(env *bootstrap.Env, timeout time.Duration, db mongo.Database, group *gin.RouterGroup) { 16 | tr := repository.NewTaskRepository(db, domain.CollectionTask) 17 | tc := &controller.TaskController{ 18 | TaskUsecase: usecase.NewTaskUsecase(tr, timeout), 19 | } 20 | group.GET("/task", tc.Fetch) 21 | group.POST("/task", tc.Create) 22 | } 23 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/api/route/v1/signup_route.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/api/controller" 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/bootstrap" 8 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 9 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/mongo" 10 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/repository" 11 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/usecase" 12 | "github.com/gin-gonic/gin" 13 | ) 14 | 15 | func NewSignupRouter(env *bootstrap.Env, timeout time.Duration, db mongo.Database, group *gin.RouterGroup) { 16 | ur := repository.NewUserRepository(db, domain.CollectionUser) 17 | sc := controller.SignupController{ 18 | SignupUsecase: usecase.NewSignupUsecase(ur, timeout), 19 | Env: env, 20 | } 21 | group.POST("/signup", sc.Signup) 22 | } 23 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | postgres: 4 | image: postgres:14-alpine 5 | environment: 6 | - POSTGRES_USER=root 7 | - POSTGRES_PASSWORD=secret 8 | - POSTGRES_DB=simple_bank 9 | ports: 10 | - "5432:5432" 11 | volumes: 12 | - data-volume:/var/lib/postgresql/data 13 | redis: 14 | image: redis:7-alpine 15 | api: 16 | build: 17 | context: . 18 | dockerfile: Dockerfile 19 | ports: 20 | - "8080:8080" 21 | - "9090:9090" 22 | environment: 23 | - DB_SOURCE=postgresql://root:secret@postgres:5432/simple_bank?sslmode=disable 24 | - REDIS_ADDRESS=redis:6379 25 | depends_on: 26 | - postgres 27 | - redis 28 | entrypoint: 29 | [ 30 | "/app/wait-for.sh", 31 | "postgres:5432", 32 | "--", 33 | "/app/start.sh" 34 | ] 35 | command: [ "/app/main" ] 36 | volumes: 37 | data-volume: 38 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/gapi/error.go: -------------------------------------------------------------------------------- 1 | package gapi 2 | 3 | import ( 4 | "google.golang.org/genproto/googleapis/rpc/errdetails" 5 | "google.golang.org/grpc/codes" 6 | "google.golang.org/grpc/status" 7 | ) 8 | 9 | func fieldViolation(field string, err error) *errdetails.BadRequest_FieldViolation { 10 | return &errdetails.BadRequest_FieldViolation{ 11 | Field: field, 12 | Description: err.Error(), 13 | } 14 | } 15 | 16 | func invalidArgumentError(violations []*errdetails.BadRequest_FieldViolation) error { 17 | badRequest := &errdetails.BadRequest{FieldViolations: violations} 18 | statusInvalid := status.New(codes.InvalidArgument, "invalid parameters") 19 | 20 | statusDetails, err := statusInvalid.WithDetails(badRequest) 21 | if err != nil { 22 | return statusInvalid.Err() 23 | } 24 | 25 | return statusDetails.Err() 26 | } 27 | 28 | func unauthenticatedError(err error) error { 29 | return status.Errorf(codes.Unauthenticated, "unauthorized: %s", err) 30 | } 31 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/MOBILE_INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | > *Note: Delete this file before publishing your app!* 2 | 3 | # [Mobile Icons (iOS/Android)](https://github.com/gothinkster/realworld/tree/master/spec/mobile_icons) 4 | 5 | ### Using the hosted API 6 | 7 | Simply point your [API requests](https://github.com/gothinkster/realworld/tree/master/api) to `https://conduit.productionready.io/api` and you're good to go! 8 | 9 | ### Styles/Templates 10 | 11 | Unfortunately, there isn't a common way for us to reuse & share styles/templates for cross-platform mobile apps. 12 | 13 | Instead, we recommend using the Medium.com [iOS](https://itunes.apple.com/us/app/medium/id828256236?mt=8) and [Android](https://play.google.com/store/apps/details?id=com.medium.reader&hl=en) apps as a "north star" regarding general UI functionality/layout, but try not to go too overboard otherwise it will unnecessarily complicate your codebase (in other words, [KISS](https://en.wikipedia.org/wiki/KISS_principle) :) 14 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/api/route/v1/refresh_token_route.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/api/controller" 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/bootstrap" 8 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 9 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/mongo" 10 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/repository" 11 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/usecase" 12 | "github.com/gin-gonic/gin" 13 | ) 14 | 15 | func NewRefreshTokenRouter(env *bootstrap.Env, timeout time.Duration, db mongo.Database, group *gin.RouterGroup) { 16 | ur := repository.NewUserRepository(db, domain.CollectionUser) 17 | rtc := &controller.RefreshTokenController{ 18 | RefreshTokenUsecase: usecase.NewRefreshTokenUsecase(ur, timeout), 19 | Env: env, 20 | } 21 | group.POST("/refresh", rtc.RefreshToken) 22 | } 23 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/usecase/task_usecase.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 8 | ) 9 | 10 | type taskUsecase struct { 11 | taskRepository domain.TaskRepository 12 | contextTimeout time.Duration 13 | } 14 | 15 | func NewTaskUsecase(taskRepository domain.TaskRepository, timeout time.Duration) domain.TaskUsecase { 16 | return &taskUsecase{ 17 | taskRepository: taskRepository, 18 | contextTimeout: timeout, 19 | } 20 | } 21 | 22 | func (tu *taskUsecase) Create(c context.Context, task *domain.Task) error { 23 | ctx, cancel := context.WithTimeout(c, tu.contextTimeout) 24 | defer cancel() 25 | return tu.taskRepository.Create(ctx, task) 26 | } 27 | 28 | func (tu *taskUsecase) FetchByUserID(c context.Context, userID string) ([]domain.Task, error) { 29 | ctx, cancel := context.WithTimeout(c, tu.contextTimeout) 30 | defer cancel() 31 | return tu.taskRepository.FetchByUserID(ctx, userID) 32 | } 33 | -------------------------------------------------------------------------------- /showcases/go-boot/utils/codec/string.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type StringCoder struct{} 8 | 9 | func (c *StringCoder) Encoder(data interface{}) ([]byte, error) { 10 | switch t := data.(type) { 11 | case string: 12 | return []byte(t), nil 13 | case *string: 14 | return []byte(*t), nil 15 | case []byte: 16 | return t, nil 17 | case *[]byte: 18 | return *t, nil 19 | default: 20 | return nil, fmt.Errorf("%T can not be directly converted to []byte", t) 21 | } 22 | } 23 | 24 | func (c *StringCoder) Decoder(data []byte, v interface{}) error { 25 | switch t := v.(type) { 26 | case string: 27 | return fmt.Errorf("expect %T but %T", &t, t) 28 | case *string: 29 | *t = string(data) 30 | case []byte: 31 | return fmt.Errorf("expect %T but %T", &t, t) 32 | case *[]byte: 33 | *t = data 34 | default: 35 | return fmt.Errorf("[]byte can not be directly converted to %T", t) 36 | } 37 | 38 | return nil 39 | } 40 | 41 | func init() { 42 | Register(String, &StringCoder{}) 43 | } 44 | -------------------------------------------------------------------------------- /showcases/go-boot/cmd/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "time" 7 | 8 | goBoot "github.com/wxyyxc1992/go-boot" 9 | "github.com/wxyyxc1992/go-boot/plugins" 10 | ) 11 | 12 | const timeout = 60 * 6 * time.Second 13 | 14 | func main() { 15 | server := goBoot.NewServer( 16 | goBoot.Config{ 17 | Timeout: timeout, 18 | PluginForPacketSender: []goBoot.PacketPlugin{ 19 | &plugins.Encryption{}, 20 | &plugins.Debug{Sender: true}, 21 | }, 22 | PluginForPacketReceiver: []goBoot.PacketPlugin{ 23 | &plugins.Decryption{}, 24 | &plugins.Debug{Sender: false}, 25 | }, 26 | }) 27 | 28 | router := goBoot.NewRouter() 29 | router.NSRouter("/v1", 30 | router.NSRoute( 31 | "/healthy", 32 | goBoot.HandlerFunc(func(ctx goBoot.Context) { 33 | fmt.Println(ctx.GetRequestProperty("sid")) 34 | ctx.Success(map[string]interface{}{"keepalive": true}) 35 | }), 36 | ), 37 | ) 38 | 39 | server.BindRouter(router) 40 | log.Fatal(server.RunTCP("tcp", "127.0.0.1:8080")) 41 | } 42 | -------------------------------------------------------------------------------- /showcases/minitask/src/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "time" 7 | ) 8 | 9 | var DEBUG_LEVEL = 2 10 | var LOG_FILE = os.Args[4] + "log_" + GetTime() + ".log" 11 | 12 | /** 13 | * Logs message in a file 14 | * 15 | * @param string message Message content 16 | * @param int level Level of the message 1, 2 , 3 etc 17 | * @author Waqar Alamgir 18 | */ 19 | func Log(message string, level int) { 20 | 21 | if level <= DEBUG_LEVEL { 22 | f, err := os.OpenFile(LOG_FILE , os.O_CREATE|os.O_RDWR|os.O_APPEND, 0660) 23 | if err != nil { 24 | panic(err) 25 | } 26 | defer f.Close() 27 | f.WriteString(message + "\n") 28 | f.Sync() 29 | fmt.Println(message) 30 | } 31 | } 32 | 33 | /** 34 | * Returns current time 35 | * 36 | * @author Waqar Alamgir 37 | * @return string Current Time 38 | */ 39 | func GetTime() string { 40 | t := time.Now() 41 | // return t.Format(time.RFC3339) 42 | return t.Format("20060102150405") 43 | } -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/api/route/v1/route.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/api/middleware" 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/bootstrap" 8 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/mongo" 9 | "github.com/gin-gonic/gin" 10 | ) 11 | 12 | func Setup(env *bootstrap.Env, timeout time.Duration, db mongo.Database, routerV1 *gin.RouterGroup) { 13 | publicRouterV1 := routerV1.Group("") 14 | // All Public APIs 15 | NewSignupRouter(env, timeout, db, publicRouterV1) 16 | NewLoginRouter(env, timeout, db, publicRouterV1) 17 | NewRefreshTokenRouter(env, timeout, db, publicRouterV1) 18 | 19 | protectedRouterV1 := routerV1.Group("") 20 | // Middleware to verify AccessToken 21 | protectedRouterV1.Use(middleware.JwtAuthMiddleware(env.AccessTokenSecret)) 22 | // All Private APIs 23 | NewProfileRouter(env, timeout, db, protectedRouterV1) 24 | NewTaskRouter(env, timeout, db, protectedRouterV1) 25 | } 26 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/sqlc/tx_verify_email.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/jackc/pgx/v5/pgtype" 7 | ) 8 | 9 | type VerifyEmailTxParams struct { 10 | EmailId int64 11 | SecretCode string 12 | } 13 | 14 | type VerifyEmailTxResult struct { 15 | User User 16 | VerifyEmail VerifyEmail 17 | } 18 | 19 | func (store *SQLStore) VerifyEmailTx(ctx context.Context, arg VerifyEmailTxParams) (VerifyEmailTxResult, error) { 20 | var result VerifyEmailTxResult 21 | 22 | err := store.execTx(ctx, func(q *Queries) error { 23 | var err error 24 | 25 | result.VerifyEmail, err = q.UpdateVerifyEmail(ctx, UpdateVerifyEmailParams{ 26 | ID: arg.EmailId, 27 | SecretCode: arg.SecretCode, 28 | }) 29 | if err != nil { 30 | return err 31 | } 32 | 33 | result.User, err = q.UpdateUser(ctx, UpdateUserParams{ 34 | Username: result.VerifyEmail.Username, 35 | IsEmailVerified: pgtype.Bool{ 36 | Bool: true, 37 | Valid: true, 38 | }, 39 | }) 40 | return err 41 | }) 42 | 43 | return result, err 44 | } 45 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 Quang Pham. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /showcases/minitask/src/httpbuilder/httpbuilder.go: -------------------------------------------------------------------------------- 1 | package httpbuilder 2 | 3 | import ( 4 | urlreq "../url" 5 | logger "../logger" 6 | "strings" 7 | ) 8 | 9 | var DEBUG_LEVEL_SHORT = 1 10 | var DEBUG_LEVEL_LONG = 2 11 | 12 | /** 13 | * Generates an http request 14 | * 15 | * @author Waqar Alamgir 16 | */ 17 | func Request(data string, success chan string, failed chan string) { 18 | 19 | arr := strings.Split(data, "|") 20 | 21 | url := arr[1] 22 | method := arr[2] 23 | params := arr[3] 24 | 25 | // dispatch the request 26 | errb, resp := urlreq.Dispatch(url + params, method, 1) 27 | 28 | if errb == true { 29 | output := url + "|" + method + "|" + params + "|" + string(resp[:]) 30 | logger.Log("Success url " + url + params , DEBUG_LEVEL_LONG) 31 | // logger.Log("Output " + output , DEBUG_LEVEL_LONG) 32 | success <- output 33 | } else {logger.Log("Invalid type: " + data , DEBUG_LEVEL_LONG) 34 | logger.Log("Failed url " + url + params, DEBUG_LEVEL_LONG) 35 | failed <- data 36 | } 37 | } -------------------------------------------------------------------------------- /showcases/go-boot/cmd/server_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | import ( 5 | "fmt" 6 | 7 | "github.com/wxyyxc1992/go-boot/client" 8 | ) 9 | 10 | func TestServer(t *testing.T) { 11 | client := client.NewClient("127.0.0.1", 8080, &ReadyStateCallback{ 12 | Open: func() { 13 | fmt.Println("open connection") 14 | }, 15 | Close: func() { 16 | fmt.Println("close connection") 17 | }, 18 | Error: func(err string) { 19 | fmt.Println(err) 20 | }, 21 | }) 22 | 23 | for { 24 | if err := client.Ping(nil, RequestStatusCallback{}); err == nil { 25 | break 26 | } 27 | } 28 | 29 | client.SetRequestProperty("sid", "go") 30 | 31 | err := client.SyncSend("/v1/healthy", nil, RequestStatusCallback{ 32 | Start: func() { 33 | fmt.Println("start request") 34 | }, 35 | End: func() { 36 | fmt.Println("end request") 37 | }, 38 | Success: func(header, body []byte) { 39 | fmt.Println(string(body)) 40 | }, 41 | Error: func(code int, message string) { 42 | fmt.Println(code, message) 43 | }, 44 | }) 45 | 46 | if err != nil { 47 | t.Error(err) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /boilerplates/standards-layout/cmd/README.md: -------------------------------------------------------------------------------- 1 | # `/cmd` 2 | 3 | Main applications for this project. 4 | 5 | The directory name for each application should match the name of the executable you want to have (e.g., `/cmd/myapp`). 6 | 7 | Don't put a lot of code in the application directory. If you think the code can be imported and used in other projects, then it should live in the `/pkg` directory. If the code is not reusable or if you don't want others to reuse it, put that code in the `/internal` directory. You'll be surprised what others will do, so be explicit about your intentions! 8 | 9 | It's common to have a small `main` function that imports and invokes the code from the `/internal` and `/pkg` directories and nothing else. 10 | 11 | Examples: 12 | 13 | * https://github.com/heptio/ark/tree/master/cmd (just a really small `main` function with everything else in packages) 14 | * https://github.com/moby/moby/tree/master/cmd 15 | * https://github.com/prometheus/prometheus/tree/master/cmd 16 | * https://github.com/influxdata/influxdb/tree/master/cmd 17 | * https://github.com/kubernetes/kubernetes/tree/master/cmd 18 | 19 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/gapi/metadata.go: -------------------------------------------------------------------------------- 1 | package gapi 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc/metadata" 7 | "google.golang.org/grpc/peer" 8 | ) 9 | 10 | const ( 11 | grpcGatewayUserAgentHeader = "grpcgateway-user-agent" 12 | userAgentHeader = "user-agent" 13 | xForwardedForHeader = "x-forwarded-for" 14 | ) 15 | 16 | type Metadata struct { 17 | UserAgent string 18 | ClientIP string 19 | } 20 | 21 | func (server *Server) extractMetadata(ctx context.Context) *Metadata { 22 | mtdt := &Metadata{} 23 | 24 | if md, ok := metadata.FromIncomingContext(ctx); ok { 25 | if userAgents := md.Get(grpcGatewayUserAgentHeader); len(userAgents) > 0 { 26 | mtdt.UserAgent = userAgents[0] 27 | } 28 | 29 | if userAgents := md.Get(userAgentHeader); len(userAgents) > 0 { 30 | mtdt.UserAgent = userAgents[0] 31 | } 32 | 33 | if clientIPs := md.Get(xForwardedForHeader); len(clientIPs) > 0 { 34 | mtdt.ClientIP = clientIPs[0] 35 | } 36 | } 37 | 38 | if p, ok := peer.FromContext(ctx); ok { 39 | mtdt.ClientIP = p.Addr.String() 40 | } 41 | 42 | return mtdt 43 | } 44 | -------------------------------------------------------------------------------- /showcases/gloc/xml.go: -------------------------------------------------------------------------------- 1 | package gocloc 2 | 3 | import ( 4 | "encoding/xml" 5 | "fmt" 6 | ) 7 | 8 | type XMLTotalLanguages struct { 9 | SumFiles int32 `xml:"sum_files,attr"` 10 | Code int32 `xml:"code,attr"` 11 | Comment int32 `xml:"comment,attr"` 12 | Blank int32 `xml:"blank,attr"` 13 | } 14 | type XMLResultLanguages struct { 15 | Languages []ClocLanguage `xml:"language"` 16 | Total XMLTotalLanguages `xml:"total"` 17 | } 18 | 19 | type XMLTotalFiles struct { 20 | Code int32 `xml:"code,attr"` 21 | Comment int32 `xml:"comment,attr"` 22 | Blank int32 `xml:"blank,attr"` 23 | } 24 | type XMLResultFiles struct { 25 | Files []ClocFile `xml:"file"` 26 | Total XMLTotalFiles `xml:"total"` 27 | } 28 | 29 | type XMLResult struct { 30 | XMLName xml.Name `xml:"results"` 31 | XMLFiles *XMLResultFiles `xml:"files,omitempty"` 32 | XMLLanguages *XMLResultLanguages `xml:"languages,omitempty"` 33 | } 34 | 35 | func (x *XMLResult) Encode() { 36 | if output, err := xml.MarshalIndent(x, "", " "); err == nil { 37 | fmt.Printf(xml.Header) 38 | fmt.Println(string(output)) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/worker/logger.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/rs/zerolog" 8 | "github.com/rs/zerolog/log" 9 | ) 10 | 11 | type Logger struct{} 12 | 13 | func NewLogger() *Logger { 14 | return &Logger{} 15 | } 16 | 17 | func (logger *Logger) Print(level zerolog.Level, args ...interface{}) { 18 | log.WithLevel(level).Msg(fmt.Sprint(args...)) 19 | } 20 | 21 | func (logger *Logger) Printf(ctx context.Context, format string, v ...interface{}) { 22 | log.WithLevel(zerolog.DebugLevel).Msgf(format, v...) 23 | } 24 | 25 | func (logger *Logger) Debug(args ...interface{}) { 26 | logger.Print(zerolog.DebugLevel, args...) 27 | } 28 | 29 | func (logger *Logger) Info(args ...interface{}) { 30 | logger.Print(zerolog.InfoLevel, args...) 31 | } 32 | 33 | func (logger *Logger) Warn(args ...interface{}) { 34 | logger.Print(zerolog.WarnLevel, args...) 35 | } 36 | 37 | func (logger *Logger) Error(args ...interface{}) { 38 | logger.Print(zerolog.ErrorLevel, args...) 39 | } 40 | 41 | func (logger *Logger) Fatal(args ...interface{}) { 42 | logger.Print(zerolog.FatalLevel, args...) 43 | } 44 | -------------------------------------------------------------------------------- /showcases/db/redis/cmd/pclient/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "time" 7 | 8 | redis "gopkg.in/redis.v4" 9 | ) 10 | 11 | func main() { 12 | client := redis.NewClient(&redis.Options{ 13 | Addr: "localhost:6379", 14 | Password: "", // no password set 15 | DB: 0, // use default DB 16 | }) 17 | 18 | _, err := client.Ping().Result() 19 | if err != nil { 20 | log.Fatalf("Failed to ping Redis: %v", err) 21 | } 22 | 23 | pubsub, err := client.Subscribe("pubsub-key") 24 | if err != nil { 25 | log.Fatalf("Failed to get task from queue: %v\n", err) 26 | } 27 | 28 | for { 29 | msgi, err := pubsub.ReceiveTimeout(5 * time.Second) 30 | if err != nil { 31 | break 32 | } 33 | 34 | switch msg := msgi.(type) { 35 | case *redis.Subscription: 36 | fmt.Println("subscribed to", msg.Channel) 37 | time.Sleep(time.Second * 10) 38 | case *redis.Message: 39 | fmt.Println("received", msg.Payload, "from", msg.Channel) 40 | default: 41 | panic(fmt.Errorf("unknown message: %#v", msgi)) 42 | } 43 | } 44 | 45 | // log.Printf("Working on '%s' task...\n", task[1]) 46 | } 47 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/gapi/server.go: -------------------------------------------------------------------------------- 1 | package gapi 2 | 3 | import ( 4 | "fmt" 5 | 6 | db "github.com/techschool/simplebank/db/sqlc" 7 | "github.com/techschool/simplebank/pb" 8 | "github.com/techschool/simplebank/token" 9 | "github.com/techschool/simplebank/util" 10 | "github.com/techschool/simplebank/worker" 11 | ) 12 | 13 | // Server serves gRPC requests for our banking service. 14 | type Server struct { 15 | pb.UnimplementedSimpleBankServer 16 | config util.Config 17 | store db.Store 18 | tokenMaker token.Maker 19 | taskDistributor worker.TaskDistributor 20 | } 21 | 22 | // NewServer creates a new gRPC server. 23 | func NewServer(config util.Config, store db.Store, taskDistributor worker.TaskDistributor) (*Server, error) { 24 | tokenMaker, err := token.NewPasetoMaker(config.TokenSymmetricKey) 25 | if err != nil { 26 | return nil, fmt.Errorf("cannot create token maker: %w", err) 27 | } 28 | 29 | server := &Server{ 30 | config: config, 31 | store: store, 32 | tokenMaker: tokenMaker, 33 | taskDistributor: taskDistributor, 34 | } 35 | 36 | return server, nil 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 wx-chevalier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/mongo/mocks/SingleResult.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v2.16.0. DO NOT EDIT. 2 | 3 | package mocks 4 | 5 | import mock "github.com/stretchr/testify/mock" 6 | 7 | // SingleResult is an autogenerated mock type for the SingleResult type 8 | type SingleResult struct { 9 | mock.Mock 10 | } 11 | 12 | // Decode provides a mock function with given fields: _a0 13 | func (_m *SingleResult) Decode(_a0 interface{}) error { 14 | ret := _m.Called(_a0) 15 | 16 | var r0 error 17 | if rf, ok := ret.Get(0).(func(interface{}) error); ok { 18 | r0 = rf(_a0) 19 | } else { 20 | r0 = ret.Error(0) 21 | } 22 | 23 | return r0 24 | } 25 | 26 | type mockConstructorTestingTNewSingleResult interface { 27 | mock.TestingT 28 | Cleanup(func()) 29 | } 30 | 31 | // NewSingleResult creates a new instance of SingleResult. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. 32 | func NewSingleResult(t mockConstructorTestingTNewSingleResult) *SingleResult { 33 | mock := &SingleResult{} 34 | mock.Mock.Test(t) 35 | 36 | t.Cleanup(func() { mock.AssertExpectations(t) }) 37 | 38 | return mock 39 | } 40 | -------------------------------------------------------------------------------- /showcases/minitask/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Waqar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /showcases/go-boot/session/session.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/wxyyxc1992/go-boot" 7 | ) 8 | 9 | // Session的在线状态 10 | const ( 11 | OFF_LINE = "off" 12 | ON_LINE = "on" 13 | BUSY_LINE = "busy" 14 | ) 15 | 16 | var ( 17 | defaultSession = make(map[string]Session) 18 | mutex sync.RWMutex 19 | ) 20 | 21 | type ( 22 | // socket信息、在线状态 23 | Session struct { 24 | Status string 25 | Ctx linker.Context 26 | Ext map[string]interface{} 27 | } 28 | ) 29 | 30 | func Get(key string) Session { 31 | mutex.RLock() 32 | defer mutex.RUnlock() 33 | 34 | return defaultSession[key] 35 | } 36 | 37 | func Set(key string, session Session) { 38 | mutex.Lock() 39 | defer mutex.Unlock() 40 | 41 | defaultSession[key] = session 42 | } 43 | 44 | func IsExist(key string) bool { 45 | mutex.RLock() 46 | defer mutex.RUnlock() 47 | 48 | if _, ok := defaultSession[key]; ok { 49 | return true 50 | } 51 | 52 | return false 53 | } 54 | 55 | func Delete(key string) { 56 | mutex.Lock() 57 | defer mutex.Unlock() 58 | delete(defaultSession, key) 59 | } 60 | 61 | func Default() map[string]Session { 62 | return defaultSession 63 | } 64 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 wangzitian0 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /showcases/db/dbinterface/create_test.go: -------------------------------------------------------------------------------- 1 | package dbinterface 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | _ "github.com/go-sql-driver/mysql" 8 | "github.com/golang/mock/gomock" 9 | ) 10 | 11 | func TestCreate(t *testing.T) { 12 | 13 | tests := []struct { 14 | name string 15 | ExecErr1 bool 16 | ExecErr2 bool 17 | wantErr bool 18 | }{ 19 | {"base-case", false, false, false}, 20 | {"1st exec error", true, false, true}, 21 | {"2nd exec error", false, true, true}, 22 | } 23 | for _, tt := range tests { 24 | t.Run(tt.name, func(t *testing.T) { 25 | ctrl := gomock.NewController(t) 26 | defer ctrl.Finish() 27 | 28 | mockDB := NewMockDB(ctrl) 29 | m := mockDB.EXPECT().Exec(gomock.Any()) 30 | if tt.ExecErr1 { 31 | m.Return(nil, errors.New("failed")) 32 | } else { 33 | m.Return(nil, nil) 34 | } 35 | m2 := mockDB.EXPECT().Exec(gomock.Any()).AnyTimes() 36 | if tt.ExecErr2 { 37 | m2.Return(nil, errors.New("failed")) 38 | } else { 39 | m2.Return(nil, nil) 40 | } 41 | if err := Create(mockDB); (err != nil) != tt.wantErr { 42 | t.Errorf("Create() error = %v, wantErr %v", err, tt.wantErr) 43 | } 44 | }) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/proto/google/api/annotations.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/api/http.proto"; 20 | import "google/protobuf/descriptor.proto"; 21 | 22 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "AnnotationsProto"; 25 | option java_package = "com.google.api"; 26 | option objc_class_prefix = "GAPI"; 27 | 28 | extend google.protobuf.MethodOptions { 29 | // See `HttpRule`. 30 | HttpRule http = 72295728; 31 | } 32 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/api/middleware/jwt_auth_middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "net/http" 5 | "strings" 6 | 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 8 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/internal/tokenutil" 9 | "github.com/gin-gonic/gin" 10 | ) 11 | 12 | func JwtAuthMiddleware(secret string) gin.HandlerFunc { 13 | return func(c *gin.Context) { 14 | authHeader := c.Request.Header.Get("Authorization") 15 | t := strings.Split(authHeader, " ") 16 | if len(t) == 2 { 17 | authToken := t[1] 18 | authorized, err := tokenutil.IsAuthorized(authToken, secret) 19 | if authorized { 20 | userID, err := tokenutil.ExtractIDFromToken(authToken, secret) 21 | if err != nil { 22 | c.JSON(http.StatusUnauthorized, domain.ErrorResponse{Message: err.Error()}) 23 | c.Abort() 24 | return 25 | } 26 | c.Set("x-user-id", userID) 27 | c.Next() 28 | return 29 | } 30 | c.JSON(http.StatusUnauthorized, domain.ErrorResponse{Message: err.Error()}) 31 | c.Abort() 32 | return 33 | } 34 | c.JSON(http.StatusUnauthorized, domain.ErrorResponse{Message: "Not authorized"}) 35 | c.Abort() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /showcases/db/redis/cmd/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/labstack/echo" 8 | 9 | "github.com/mycodesmells/golang-examples/redis/logger" 10 | pagehit "github.com/mycodesmells/golang-examples/redis/pagehit-2" 11 | "github.com/mycodesmells/golang-examples/redis/sessions" 12 | ) 13 | 14 | func main() { 15 | sessionsStore := sessions.NewRedisStore() 16 | hitStore := pagehit.NewRedisStore() 17 | 18 | e := echo.New() 19 | e.Use(sessions.Middleware(sessionsStore)) 20 | e.Use(pagehit.Middleware(hitStore)) 21 | 22 | e.GET("/", func(ectx echo.Context) error { 23 | log := logger.FromContext(ectx) 24 | 25 | sessionID := ectx.Get("sessionID").(string) 26 | s, err := sessionsStore.Get(sessionID) 27 | if err != nil { 28 | log.Errorf("err: %v", err) 29 | } 30 | 31 | log.Infof("Visits: %d", s.VisitCount) 32 | response := fmt.Sprintf("Hello World #%d\n", s.VisitCount) 33 | 34 | s.VisitCount = s.VisitCount + 1 35 | err = sessionsStore.Set(sessionID, s) 36 | if err != nil { 37 | log.Errorf("err: %v", err) 38 | } 39 | 40 | return ectx.String(http.StatusOK, response) 41 | }) 42 | e.GET("/stats", pagehit.Handler(hitStore)) 43 | 44 | e.Start(":5000") 45 | } 46 | -------------------------------------------------------------------------------- /showcases/db/firebase/client_test.go: -------------------------------------------------------------------------------- 1 | package firebase 2 | 3 | import "testing" 4 | 5 | func Test_firebaseClient_Get(t *testing.T) { 6 | 7 | tests := []struct { 8 | name string 9 | wantErr bool 10 | }{ 11 | {"base-case", false}, 12 | } 13 | for _, tt := range tests { 14 | t.Run(tt.name, func(t *testing.T) { 15 | f, err := Authenticate() 16 | if err != nil { 17 | t.Error(err) 18 | } 19 | _, err = f.Get() 20 | if (err != nil) != tt.wantErr { 21 | t.Errorf("firebaseClient.Get() error = %v, wantErr %v", err, tt.wantErr) 22 | return 23 | } 24 | }) 25 | } 26 | } 27 | 28 | func Test_firebaseClient_Set(t *testing.T) { 29 | type args struct { 30 | key string 31 | value interface{} 32 | } 33 | tests := []struct { 34 | name string 35 | args args 36 | wantErr bool 37 | }{ 38 | {"base-case", args{"test", "case"}, false}, 39 | } 40 | for _, tt := range tests { 41 | t.Run(tt.name, func(t *testing.T) { 42 | f, err := Authenticate() 43 | if err != nil { 44 | t.Error(err) 45 | } 46 | if err := f.Set(tt.args.key, tt.args.value); (err != nil) != tt.wantErr { 47 | t.Errorf("firebaseClient.Set() error = %v, wantErr %v", err, tt.wantErr) 48 | } 49 | }) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /showcases/db/database/query_test.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | "testing" 7 | "time" 8 | 9 | sqlmock "github.com/DATA-DOG/go-sqlmock" 10 | _ "github.com/go-sql-driver/mysql" 11 | ) 12 | 13 | func TestQuery(t *testing.T) { 14 | db, mock, err := sqlmock.New() 15 | if err != nil { 16 | t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) 17 | } 18 | type args struct { 19 | db *sql.DB 20 | } 21 | tests := []struct { 22 | name string 23 | args args 24 | queryTime interface{} 25 | queryErr bool 26 | wantErr bool 27 | }{ 28 | {"base-case", args{db}, time.Now(), false, false}, 29 | {"bad row", args{db}, 123, false, true}, 30 | {"query error", args{db}, time.Now(), true, true}, 31 | } 32 | for _, tt := range tests { 33 | t.Run(tt.name, func(t *testing.T) { 34 | m := mock.ExpectQuery("SELECT").WillReturnRows(sqlmock.NewRows([]string{"name", "created"}). 35 | AddRow("test", tt.queryTime)) 36 | 37 | if tt.queryErr { 38 | m.WillReturnError(errors.New("failed")) 39 | } 40 | if err := Query(tt.args.db); (err != nil) != tt.wantErr { 41 | t.Errorf("Query() error = %v, wantErr %v", err, tt.wantErr) 42 | } 43 | }) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /showcases/db/dbinterface/query_test.go: -------------------------------------------------------------------------------- 1 | package dbinterface 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | "testing" 7 | "time" 8 | 9 | sqlmock "github.com/DATA-DOG/go-sqlmock" 10 | _ "github.com/go-sql-driver/mysql" 11 | ) 12 | 13 | func TestQuery(t *testing.T) { 14 | db, mock, err := sqlmock.New() 15 | if err != nil { 16 | t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) 17 | } 18 | type args struct { 19 | db *sql.DB 20 | } 21 | tests := []struct { 22 | name string 23 | args args 24 | queryTime interface{} 25 | queryErr bool 26 | wantErr bool 27 | }{ 28 | {"base-case", args{db}, time.Now(), false, false}, 29 | {"bad row", args{db}, 123, false, true}, 30 | {"query error", args{db}, time.Now(), true, true}, 31 | } 32 | for _, tt := range tests { 33 | t.Run(tt.name, func(t *testing.T) { 34 | m := mock.ExpectQuery("SELECT").WillReturnRows(sqlmock.NewRows([]string{"name", "created"}). 35 | AddRow("test", tt.queryTime)) 36 | 37 | if tt.queryErr { 38 | m.WillReturnError(errors.New("failed")) 39 | } 40 | if err := Query(tt.args.db); (err != nil) != tt.wantErr { 41 | t.Errorf("Query() error = %v, wantErr %v", err, tt.wantErr) 42 | } 43 | }) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/usecase/login_usecase.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 8 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/internal/tokenutil" 9 | ) 10 | 11 | type loginUsecase struct { 12 | userRepository domain.UserRepository 13 | contextTimeout time.Duration 14 | } 15 | 16 | func NewLoginUsecase(userRepository domain.UserRepository, timeout time.Duration) domain.LoginUsecase { 17 | return &loginUsecase{ 18 | userRepository: userRepository, 19 | contextTimeout: timeout, 20 | } 21 | } 22 | 23 | func (lu *loginUsecase) GetUserByEmail(c context.Context, email string) (domain.User, error) { 24 | ctx, cancel := context.WithTimeout(c, lu.contextTimeout) 25 | defer cancel() 26 | return lu.userRepository.GetByEmail(ctx, email) 27 | } 28 | 29 | func (lu *loginUsecase) CreateAccessToken(user *domain.User, secret string, expiry int) (accessToken string, err error) { 30 | return tokenutil.CreateAccessToken(user, secret, expiry) 31 | } 32 | 33 | func (lu *loginUsecase) CreateRefreshToken(user *domain.User, secret string, expiry int) (refreshToken string, err error) { 34 | return tokenutil.CreateRefreshToken(user, secret, expiry) 35 | } 36 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/gapi/main_test.go: -------------------------------------------------------------------------------- 1 | package gapi 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "testing" 7 | "time" 8 | 9 | "github.com/stretchr/testify/require" 10 | db "github.com/techschool/simplebank/db/sqlc" 11 | "github.com/techschool/simplebank/token" 12 | "github.com/techschool/simplebank/util" 13 | "github.com/techschool/simplebank/worker" 14 | "google.golang.org/grpc/metadata" 15 | ) 16 | 17 | func newTestServer(t *testing.T, store db.Store, taskDistributor worker.TaskDistributor) *Server { 18 | config := util.Config{ 19 | TokenSymmetricKey: util.RandomString(32), 20 | AccessTokenDuration: time.Minute, 21 | } 22 | 23 | server, err := NewServer(config, store, taskDistributor) 24 | require.NoError(t, err) 25 | 26 | return server 27 | } 28 | 29 | func newContextWithBearerToken(t *testing.T, tokenMaker token.Maker, username string, role string, duration time.Duration) context.Context { 30 | accessToken, _, err := tokenMaker.CreateToken(username, role, duration) 31 | require.NoError(t, err) 32 | 33 | bearerToken := fmt.Sprintf("%s %s", authorizationBearer, accessToken) 34 | md := metadata.MD{ 35 | authorizationHeader: []string{ 36 | bearerToken, 37 | }, 38 | } 39 | 40 | return metadata.NewIncomingContext(context.Background(), md) 41 | } 42 | -------------------------------------------------------------------------------- /showcases/db/database/create_test.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | "testing" 7 | 8 | sqlmock "github.com/DATA-DOG/go-sqlmock" 9 | ) 10 | 11 | func TestCreate(t *testing.T) { 12 | db, mock, err := sqlmock.New() 13 | if err != nil { 14 | t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) 15 | } 16 | 17 | type args struct { 18 | db *sql.DB 19 | } 20 | type rets struct { 21 | error1 error 22 | error2 error 23 | } 24 | tests := []struct { 25 | name string 26 | args args 27 | rets rets 28 | wantErr bool 29 | }{ 30 | {"All good", args{db}, rets{nil, nil}, false}, 31 | {"Create error", args{db}, rets{errors.New("failed"), nil}, true}, 32 | {"Insert error", args{db}, rets{nil, errors.New("failed")}, true}, 33 | } 34 | for _, tt := range tests { 35 | t.Run(tt.name, func(t *testing.T) { 36 | mock.ExpectExec("CREATE TABLE").WillReturnError(tt.rets.error1).WillReturnResult(sqlmock.NewResult(0, 0)) 37 | mock.ExpectExec("INSERT INTO").WillReturnError(tt.rets.error2).WillReturnResult(sqlmock.NewResult(0, 0)) 38 | if err := Create(tt.args.db); (err != nil) != tt.wantErr { 39 | t.Errorf("Create() error = %v, wantErr %v", err, tt.wantErr) 40 | } 41 | }) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/bootstrap/database.go: -------------------------------------------------------------------------------- 1 | package bootstrap 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/mongo" 10 | ) 11 | 12 | func NewMongoDatabase(env *Env) mongo.Client { 13 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 14 | defer cancel() 15 | 16 | dbHost := env.DBHost 17 | dbPort := env.DBPort 18 | dbUser := env.DBUser 19 | dbPass := env.DBPass 20 | 21 | mongodbURI := fmt.Sprintf("mongodb://%s:%s@%s:%s", dbUser, dbPass, dbHost, dbPort) 22 | 23 | if dbUser == "" || dbPass == "" { 24 | mongodbURI = fmt.Sprintf("mongodb://%s:%s", dbHost, dbPort) 25 | } 26 | 27 | client, err := mongo.NewClient(mongodbURI) 28 | if err != nil { 29 | log.Fatal(err) 30 | } 31 | 32 | err = client.Connect(ctx) 33 | if err != nil { 34 | log.Fatal(err) 35 | } 36 | 37 | err = client.Ping(ctx) 38 | if err != nil { 39 | log.Fatal(err) 40 | } 41 | 42 | return client 43 | } 44 | 45 | func CloseMongoDBConnection(client mongo.Client) { 46 | if client == nil { 47 | return 48 | } 49 | 50 | err := client.Disconnect(context.TODO()) 51 | if err != nil { 52 | log.Fatal(err) 53 | } 54 | 55 | log.Println("Connection to MongoDB closed.") 56 | } 57 | -------------------------------------------------------------------------------- /showcases/go-http-proxy-cli/client/bp_client.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "log" 5 | 6 | model "dev.wx/model" 7 | 8 | iReq "github.com/imroc/req" 9 | ) 10 | 11 | const ( 12 | defaultBpServerHost string = "172.16.7.249:8080" 13 | ) 14 | 15 | type BpClient struct { 16 | bpServerHost string 17 | } 18 | 19 | func NewBpClient(host string) (*BpClient, error) { 20 | 21 | bpClient := &BpClient{} 22 | 23 | bpClient.bpServerHost = host 24 | 25 | if host == "" { 26 | bpClient.bpServerHost = defaultBpServerHost 27 | } 28 | 29 | return bpClient, nil 30 | } 31 | 32 | /* 创建为新的任务 **/ 33 | func (bpClient *BpClient) CreateTask(deviceInfo, bppParaInfo *model.File, fileList []*model.File) (*iReq.Resp, error) { 34 | 35 | body := make(map[string]interface{}) 36 | body["deviceInfo"] = *deviceInfo 37 | body["bppParaInfo"] = *bppParaInfo 38 | body["fileList"] = fileList 39 | 40 | bodyJson := iReq.BodyJSON(body) 41 | 42 | log.Println(deviceInfo) 43 | 44 | r, err := iReq.Post("http://"+bpClient.bpServerHost+"/createTask", bodyJson) 45 | 46 | if err != nil { 47 | log.Fatal(err) 48 | } 49 | 50 | var foo interface{} 51 | // response => struct/map 52 | r.ToJSON(&foo) 53 | 54 | // print info (try it, you may surprise) 55 | log.Printf("%+v", r) 56 | 57 | return r, err 58 | } 59 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/common/database.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "fmt" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/sqlite" 7 | "os" 8 | ) 9 | 10 | type Database struct { 11 | *gorm.DB 12 | } 13 | 14 | var DB *gorm.DB 15 | 16 | // Opening a database and save the reference to `Database` struct. 17 | func Init() *gorm.DB { 18 | db, err := gorm.Open("sqlite3", "./../gorm.db") 19 | if err != nil { 20 | fmt.Println("db err: (Init) ", err) 21 | } 22 | db.DB().SetMaxIdleConns(10) 23 | //db.LogMode(true) 24 | DB = db 25 | return DB 26 | } 27 | 28 | // This function will create a temporarily database for running testing cases 29 | func TestDBInit() *gorm.DB { 30 | test_db, err := gorm.Open("sqlite3", "./../gorm_test.db") 31 | if err != nil { 32 | fmt.Println("db err: (TestDBInit) ", err) 33 | } 34 | test_db.DB().SetMaxIdleConns(3) 35 | test_db.LogMode(true) 36 | DB = test_db 37 | return DB 38 | } 39 | 40 | // Delete the database after running testing cases. 41 | func TestDBFree(test_db *gorm.DB) error { 42 | test_db.Close() 43 | err := os.Remove("./../gorm_test.db") 44 | return err 45 | } 46 | 47 | // Using this function to get a connection, you can create your connection pool here. 48 | func GetDB() *gorm.DB { 49 | return DB 50 | } 51 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/util/random.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | const alphabet = "abcdefghijklmnopqrstuvwxyz" 11 | 12 | func init() { 13 | rand.Seed(time.Now().UnixNano()) 14 | } 15 | 16 | // RandomInt generates a random integer between min and max 17 | func RandomInt(min, max int64) int64 { 18 | return min + rand.Int63n(max-min+1) 19 | } 20 | 21 | // RandomString generates a random string of length n 22 | func RandomString(n int) string { 23 | var sb strings.Builder 24 | k := len(alphabet) 25 | 26 | for i := 0; i < n; i++ { 27 | c := alphabet[rand.Intn(k)] 28 | sb.WriteByte(c) 29 | } 30 | 31 | return sb.String() 32 | } 33 | 34 | // RandomOwner generates a random owner name 35 | func RandomOwner() string { 36 | return RandomString(6) 37 | } 38 | 39 | // RandomMoney generates a random amount of money 40 | func RandomMoney() int64 { 41 | return RandomInt(0, 1000) 42 | } 43 | 44 | // RandomCurrency generates a random currency code 45 | func RandomCurrency() string { 46 | currencies := []string{USD, EUR, CAD} 47 | n := len(currencies) 48 | return currencies[rand.Intn(n)] 49 | } 50 | 51 | // RandomEmail generates a random email 52 | func RandomEmail() string { 53 | return fmt.Sprintf("%s@email.com", RandomString(6)) 54 | } 55 | -------------------------------------------------------------------------------- /showcases/minitask/src/executer/executer.go: -------------------------------------------------------------------------------- 1 | package executer 2 | 3 | import ( 4 | httpbuilder "../httpbuilder" 5 | commandrunner "../commandrunner" 6 | logger "./../logger" 7 | "strings" 8 | ) 9 | 10 | var DEBUG_LEVEL_SHORT = 1 11 | var DEBUG_LEVEL_LONG = 2 12 | 13 | /** 14 | * Decides and execute weather we need to run command or make an http request 15 | * 16 | * @author Waqar Alamgir 17 | */ 18 | func Execute(data string, success chan string, failed chan string) { 19 | 20 | arr := strings.Split(data, "|") 21 | 22 | // If 4 items in array 23 | if len(arr) == 4 { 24 | jobType := arr[0] 25 | 26 | logger.Log("JobType: " + jobType, DEBUG_LEVEL_LONG) 27 | 28 | // Job type is URL, then send a http request 29 | if jobType == "URL" { 30 | // Dispatch the request 31 | httpbuilder.Request(data, success, failed) 32 | } else if jobType == "CMD" { 33 | // Run the command on the server 34 | commandrunner.Run(data, success, failed) 35 | } else { 36 | // Job type is invalid 37 | logger.Log("Invalid jobType: " + jobType, DEBUG_LEVEL_LONG) 38 | } 39 | 40 | } else { 41 | logger.Log("Invalid input: " + data, DEBUG_LEVEL_LONG) 42 | } 43 | } -------------------------------------------------------------------------------- /showcases/2024~simplebank/.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Run unit tests 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | test: 12 | name: Test 13 | runs-on: ubuntu-latest 14 | 15 | services: 16 | postgres: 17 | image: postgres:14-alpine 18 | env: 19 | POSTGRES_USER: root 20 | POSTGRES_PASSWORD: secret 21 | POSTGRES_DB: simple_bank 22 | ports: 23 | - 5432:5432 24 | options: >- 25 | --health-cmd pg_isready 26 | --health-interval 10s 27 | --health-timeout 5s 28 | --health-retries 5 29 | 30 | steps: 31 | 32 | - name: Set up Go 1.x 33 | uses: actions/setup-go@v2 34 | with: 35 | go-version: ^1.22 36 | id: go 37 | 38 | - name: Check out code into the Go module directory 39 | uses: actions/checkout@v2 40 | 41 | - name: Install golang-migrate 42 | run: | 43 | curl -L https://github.com/golang-migrate/migrate/releases/download/v4.14.1/migrate.linux-amd64.tar.gz | tar xvz 44 | sudo mv migrate.linux-amd64 /usr/bin/migrate 45 | which migrate 46 | 47 | - name: Run migrations 48 | run: make migrateup 49 | 50 | - name: Test 51 | run: make test 52 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/token/payload.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | 7 | "github.com/google/uuid" 8 | ) 9 | 10 | // Different types of error returned by the VerifyToken function 11 | var ( 12 | ErrInvalidToken = errors.New("token is invalid") 13 | ErrExpiredToken = errors.New("token has expired") 14 | ) 15 | 16 | // Payload contains the payload data of the token 17 | type Payload struct { 18 | ID uuid.UUID `json:"id"` 19 | Username string `json:"username"` 20 | Role string `json:"role"` 21 | IssuedAt time.Time `json:"issued_at"` 22 | ExpiredAt time.Time `json:"expired_at"` 23 | } 24 | 25 | // NewPayload creates a new token payload with a specific username and duration 26 | func NewPayload(username string, role string, duration time.Duration) (*Payload, error) { 27 | tokenID, err := uuid.NewRandom() 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | payload := &Payload{ 33 | ID: tokenID, 34 | Username: username, 35 | Role: role, 36 | IssuedAt: time.Now(), 37 | ExpiredAt: time.Now().Add(duration), 38 | } 39 | return payload, nil 40 | } 41 | 42 | // Valid checks if the token payload is valid or not 43 | func (payload *Payload) Valid() error { 44 | if time.Now().After(payload.ExpiredAt) { 45 | return ErrExpiredToken 46 | } 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /showcases/go-boot/packet.go: -------------------------------------------------------------------------------- 1 | package go_boot 2 | 3 | import ( 4 | "github.com/wxyyxc1992/go-boot/utils/convert" 5 | ) 6 | 7 | type ( 8 | Packet struct { 9 | Operator uint32 10 | Sequence int64 11 | HeaderLength uint32 12 | BodyLength uint32 13 | Header []byte 14 | Body []byte 15 | } 16 | 17 | // Packet plugin, for example debug,gzip,encrypt,decrypt 18 | PacketPlugin interface { 19 | Handle(header, body []byte) (h, b []byte) 20 | } 21 | ) 22 | 23 | func NewPacket(operator uint32, sequence int64, header, body []byte, plugins []PacketPlugin) (Packet, error) { 24 | for _, plugin := range plugins { 25 | header, body = plugin.Handle(header, body) 26 | } 27 | 28 | return Packet{ 29 | Operator: operator, 30 | Sequence: sequence, 31 | HeaderLength: uint32(len(header)), 32 | BodyLength: uint32(len(body)), 33 | Header: header, 34 | Body: body, 35 | }, nil 36 | } 37 | 38 | // 得到序列化后的Packet 39 | func (p Packet) Bytes() (buf []byte) { 40 | buf = append(buf, convert.Uint32ToBytes(p.Operator)...) 41 | buf = append(buf, convert.Int64ToBytes(p.Sequence)...) 42 | buf = append(buf, convert.Uint32ToBytes(p.HeaderLength)...) 43 | buf = append(buf, convert.Uint32ToBytes(p.BodyLength)...) 44 | buf = append(buf, p.Header...) 45 | buf = append(buf, p.Body...) 46 | 47 | return buf 48 | } 49 | -------------------------------------------------------------------------------- /showcases/go-boot/cmd/callback.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type ( 4 | RequestStatusCallback struct { 5 | Start func() 6 | End func() 7 | Success func(header, body []byte) 8 | Error func(code int, message string) 9 | } 10 | 11 | ReadyStateCallback struct { 12 | Open func() 13 | Close func() 14 | Error func(err string) 15 | } 16 | 17 | HandlerFunc func(header, body []byte) 18 | ) 19 | 20 | func (r RequestStatusCallback) OnStart() { 21 | if r.Start != nil { 22 | r.Start() 23 | } 24 | } 25 | 26 | func (r RequestStatusCallback) OnSuccess(header, body []byte) { 27 | if r.Success != nil { 28 | r.Success(header, body) 29 | } 30 | } 31 | 32 | func (r RequestStatusCallback) OnError(code int, message string) { 33 | if r.Error != nil { 34 | r.Error(code, message) 35 | } 36 | } 37 | 38 | func (r RequestStatusCallback) OnEnd() { 39 | if r.End != nil { 40 | r.End() 41 | } 42 | } 43 | 44 | // 接口型函数,实现linker.Handler接口 45 | func (f HandlerFunc) Handle(header, body []byte) { 46 | f(header, body) 47 | } 48 | 49 | func (c *ReadyStateCallback) OnOpen() { 50 | if c.Open != nil { 51 | c.Open() 52 | } 53 | } 54 | 55 | func (c *ReadyStateCallback) OnClose() { 56 | if c.Close != nil { 57 | c.Close() 58 | } 59 | } 60 | 61 | func (c *ReadyStateCallback) OnError(err string) { 62 | if c.Error != nil { 63 | c.Error(err) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/api/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/L04DB4L4NC3R/jobs-mhrd/api/views" 9 | pkg "github.com/L04DB4L4NC3R/jobs-mhrd/pkg" 10 | jwtmiddleware "github.com/auth0/go-jwt-middleware" 11 | "github.com/dgrijalva/jwt-go" 12 | "github.com/spf13/viper" 13 | ) 14 | 15 | func Validate(h http.Handler) http.Handler { 16 | jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{ 17 | ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { 18 | return []byte(viper.GetString("jwt_secret")), nil 19 | }, 20 | SigningMethod: jwt.SigningMethodHS256, 21 | }) 22 | 23 | return jwtMiddleware.Handler(h) 24 | } 25 | 26 | func ValidateAndGetClaims(ctx context.Context, role string) (map[string]interface{}, error) { 27 | 28 | token, ok := ctx.Value("user").(*jwt.Token) 29 | if !ok { 30 | log.Println(token) 31 | return nil, views.ErrInvalidToken 32 | } 33 | 34 | claims, ok := token.Claims.(jwt.MapClaims) 35 | 36 | if !ok { 37 | log.Println(claims) 38 | return nil, views.ErrInvalidToken 39 | } 40 | 41 | if claims.Valid() != nil { 42 | return nil, views.ErrInvalidToken 43 | } 44 | 45 | if claims["role"].(string) != role { 46 | log.Println(claims["role"]) 47 | return nil, pkg.ErrUnauthorized 48 | } 49 | return claims, nil 50 | } 51 | -------------------------------------------------------------------------------- /showcases/db/redis/sessions/redis.go: -------------------------------------------------------------------------------- 1 | package sessions 2 | 3 | import ( 4 | "encoding/json" 5 | "log" 6 | 7 | "github.com/go-redis/redis" 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | type redisStore struct { 12 | client *redis.Client 13 | } 14 | 15 | func NewRedisStore() Store { 16 | client := redis.NewClient(&redis.Options{ 17 | Addr: "localhost:6379", 18 | Password: "", // no password set 19 | DB: 0, // use default DB 20 | }) 21 | 22 | _, err := client.Ping().Result() 23 | if err != nil { 24 | log.Fatalf("Failed to ping Redis: %v", err) 25 | } 26 | 27 | return &redisStore{ 28 | client: client, 29 | } 30 | } 31 | 32 | func (r redisStore) Get(id string) (Session, error) { 33 | var session Session 34 | 35 | bs, err := r.client.Get(id).Bytes() 36 | if err != nil { 37 | return session, errors.Wrap(err, "failed to get session from redis") 38 | } 39 | 40 | if err := json.Unmarshal(bs, &session); err != nil { 41 | return session, errors.Wrap(err, "failed to unmarshall session data") 42 | } 43 | 44 | return session, nil 45 | } 46 | 47 | func (r redisStore) Set(id string, session Session) error { 48 | bs, err := json.Marshal(session) 49 | if err != nil { 50 | return errors.Wrap(err, "failed to save session to redis") 51 | } 52 | 53 | if err := r.client.Set(id, bs, 0).Err(); err != nil { 54 | return errors.Wrap(err, "failed to save session to redis") 55 | } 56 | 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/bootstrap/env.go: -------------------------------------------------------------------------------- 1 | package bootstrap 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/spf13/viper" 7 | ) 8 | 9 | type Env struct { 10 | AppEnv string `mapstructure:"APP_ENV"` 11 | ServerAddress string `mapstructure:"SERVER_ADDRESS"` 12 | ContextTimeout int `mapstructure:"CONTEXT_TIMEOUT"` 13 | DBHost string `mapstructure:"DB_HOST"` 14 | DBPort string `mapstructure:"DB_PORT"` 15 | DBUser string `mapstructure:"DB_USER"` 16 | DBPass string `mapstructure:"DB_PASS"` 17 | DBName string `mapstructure:"DB_NAME"` 18 | AccessTokenExpiryHour int `mapstructure:"ACCESS_TOKEN_EXPIRY_HOUR"` 19 | RefreshTokenExpiryHour int `mapstructure:"REFRESH_TOKEN_EXPIRY_HOUR"` 20 | AccessTokenSecret string `mapstructure:"ACCESS_TOKEN_SECRET"` 21 | RefreshTokenSecret string `mapstructure:"REFRESH_TOKEN_SECRET"` 22 | } 23 | 24 | func NewEnv() *Env { 25 | env := Env{} 26 | viper.SetConfigFile(".env") 27 | 28 | err := viper.ReadInConfig() 29 | if err != nil { 30 | log.Fatal("Can't find the file .env : ", err) 31 | } 32 | 33 | err = viper.Unmarshal(&env) 34 | if err != nil { 35 | log.Fatal("Environment can't be loaded: ", err) 36 | } 37 | 38 | if env.AppEnv == "development" { 39 | log.Println("The App is running in development env") 40 | } 41 | 42 | return &env 43 | } 44 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/repository/task_repository.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/mongo" 8 | "go.mongodb.org/mongo-driver/bson" 9 | "go.mongodb.org/mongo-driver/bson/primitive" 10 | ) 11 | 12 | type taskRepository struct { 13 | database mongo.Database 14 | collection string 15 | } 16 | 17 | func NewTaskRepository(db mongo.Database, collection string) domain.TaskRepository { 18 | return &taskRepository{ 19 | database: db, 20 | collection: collection, 21 | } 22 | } 23 | 24 | func (tr *taskRepository) Create(c context.Context, task *domain.Task) error { 25 | collection := tr.database.Collection(tr.collection) 26 | 27 | _, err := collection.InsertOne(c, task) 28 | 29 | return err 30 | } 31 | 32 | func (tr *taskRepository) FetchByUserID(c context.Context, userID string) ([]domain.Task, error) { 33 | collection := tr.database.Collection(tr.collection) 34 | 35 | var tasks []domain.Task 36 | 37 | idHex, err := primitive.ObjectIDFromHex(userID) 38 | if err != nil { 39 | return tasks, err 40 | } 41 | 42 | cursor, err := collection.Find(c, bson.M{"userID": idHex}) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | err = cursor.All(c, &tasks) 48 | if tasks == nil { 49 | return []domain.Task{}, err 50 | } 51 | 52 | return tasks, err 53 | } 54 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/db/migration/000001_init_schema.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE "accounts" ( 2 | "id" bigserial PRIMARY KEY, 3 | "owner" varchar NOT NULL, 4 | "balance" bigint NOT NULL, 5 | "currency" varchar NOT NULL, 6 | "created_at" timestamptz NOT NULL DEFAULT (now()) 7 | ); 8 | 9 | CREATE TABLE "entries" ( 10 | "id" bigserial PRIMARY KEY, 11 | "account_id" bigint NOT NULL, 12 | "amount" bigint NOT NULL, 13 | "created_at" timestamptz NOT NULL DEFAULT (now()) 14 | ); 15 | 16 | CREATE TABLE "transfers" ( 17 | "id" bigserial PRIMARY KEY, 18 | "from_account_id" bigint NOT NULL, 19 | "to_account_id" bigint NOT NULL, 20 | "amount" bigint NOT NULL, 21 | "created_at" timestamptz NOT NULL DEFAULT (now()) 22 | ); 23 | 24 | ALTER TABLE "entries" ADD FOREIGN KEY ("account_id") REFERENCES "accounts" ("id"); 25 | 26 | ALTER TABLE "transfers" ADD FOREIGN KEY ("from_account_id") REFERENCES "accounts" ("id"); 27 | 28 | ALTER TABLE "transfers" ADD FOREIGN KEY ("to_account_id") REFERENCES "accounts" ("id"); 29 | 30 | CREATE INDEX ON "accounts" ("owner"); 31 | 32 | CREATE INDEX ON "entries" ("account_id"); 33 | 34 | CREATE INDEX ON "transfers" ("from_account_id"); 35 | 36 | CREATE INDEX ON "transfers" ("to_account_id"); 37 | 38 | CREATE INDEX ON "transfers" ("from_account_id", "to_account_id"); 39 | 40 | COMMENT ON COLUMN "entries"."amount" IS 'can be negative or positive'; 41 | 42 | COMMENT ON COLUMN "transfers"."amount" IS 'must be positive'; 43 | -------------------------------------------------------------------------------- /showcases/go-http-proxy-cli/cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | client "dev.wx/client" 9 | model "dev.wx/model" 10 | "github.com/urfave/cli/v2" 11 | ) 12 | 13 | var ( 14 | bpClient, _ = client.NewBpClient("") 15 | ) 16 | 17 | func main() { 18 | app := &cli.App{ 19 | Name: "go-http-proxy-cli", 20 | Usage: "Proxy wrapper with Golang.", 21 | Commands: []*cli.Command{ 22 | { 23 | Name: "greet", 24 | Aliases: []string{"g"}, 25 | Usage: "Say greetings", 26 | Action: func(c *cli.Context) error { 27 | fmt.Println("Say greetingss") 28 | return nil 29 | }, 30 | }, 31 | { 32 | Name: "bpc", 33 | Aliases: []string{"b"}, 34 | Usage: "Send msg to bpc", 35 | Action: func(c *cli.Context) error { 36 | _, err := bpClient.CreateTask( 37 | model.NewFile("1", "INI", "remote", "http://172.16.7.208:8000/ini/SLA_600.ini", "084b3157cae7198b1ce3c5871beb8760"), 38 | model.NewFile("2", "BPP", "remote", "http://172.16.7.208:8000/bpp/%E8%80%81%E6%AC%BE3300-%E6%AD%A3%E9%9B%85600-0902.bpp", "0f77314f93832ae3c7d088dbe28c00b9"), 39 | []*model.File{ 40 | model.NewFile("3", "CLI", "remote", "http://172.16.7.208:8000/cli/eStageMergedPart_s.cli", "c41c5b6a11aa56c2357c022ae151275a"), 41 | }) 42 | 43 | return err 44 | }, 45 | }, 46 | }, 47 | } 48 | 49 | err := app.Run(os.Args) 50 | if err != nil { 51 | log.Fatal(err) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/gapi/rpc_verify_email.go: -------------------------------------------------------------------------------- 1 | package gapi 2 | 3 | import ( 4 | "context" 5 | 6 | db "github.com/techschool/simplebank/db/sqlc" 7 | "github.com/techschool/simplebank/pb" 8 | "github.com/techschool/simplebank/val" 9 | "google.golang.org/genproto/googleapis/rpc/errdetails" 10 | "google.golang.org/grpc/codes" 11 | "google.golang.org/grpc/status" 12 | ) 13 | 14 | func (server *Server) VerifyEmail(ctx context.Context, req *pb.VerifyEmailRequest) (*pb.VerifyEmailResponse, error) { 15 | violations := validateVerifyEmailRequest(req) 16 | if violations != nil { 17 | return nil, invalidArgumentError(violations) 18 | } 19 | 20 | txResult, err := server.store.VerifyEmailTx(ctx, db.VerifyEmailTxParams{ 21 | EmailId: req.GetEmailId(), 22 | SecretCode: req.GetSecretCode(), 23 | }) 24 | if err != nil { 25 | return nil, status.Errorf(codes.Internal, "failed to verify email") 26 | } 27 | 28 | rsp := &pb.VerifyEmailResponse{ 29 | IsVerified: txResult.User.IsEmailVerified, 30 | } 31 | return rsp, nil 32 | } 33 | 34 | func validateVerifyEmailRequest(req *pb.VerifyEmailRequest) (violations []*errdetails.BadRequest_FieldViolation) { 35 | if err := val.ValidateEmailId(req.GetEmailId()); err != nil { 36 | violations = append(violations, fieldViolation("email_id", err)) 37 | } 38 | 39 | if err := val.ValidateSecretCode(req.GetSecretCode()); err != nil { 40 | violations = append(violations, fieldViolation("secret_code", err)) 41 | } 42 | 43 | return violations 44 | } 45 | -------------------------------------------------------------------------------- /showcases/go-boot/utils/convert/convert_test.go: -------------------------------------------------------------------------------- 1 | package convert 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/wxyyxc1992/go-boot" 8 | ) 9 | 10 | func TestConvert(t *testing.T) { 11 | var a uint32 = 199211 12 | bytes := linker.Uint32ToBytes(a) 13 | var b uint32 = linker.BytesToUint32(bytes) 14 | if a != b { 15 | t.Error("convert error") 16 | } 17 | 18 | a = 0xffffffff 19 | b = linker.BytesToUint32(linker.Uint32ToBytes(a)) 20 | if a != b { 21 | t.Error("convert error") 22 | } 23 | 24 | var c uint16 = 0xfefe 25 | bytes2 := linker.Uint16ToBytes(c) 26 | var d uint16 = linker.BytesToUint16(bytes2) 27 | if c != d { 28 | t.Error("convert error") 29 | } 30 | 31 | c = 65535 32 | d = linker.BytesToUint16(linker.Uint16ToBytes(c)) 33 | if c != d { 34 | t.Error("convert error") 35 | } 36 | 37 | var e int32 = 98765 38 | bytes3 := linker.Int32ToBytes(e) 39 | var f int32 = linker.BytesToInt32(bytes3) 40 | if e != f { 41 | t.Error("convert error") 42 | } 43 | 44 | var g int16 = 0x7FFF 45 | bytes4 := linker.Int16ToBytes(g) 46 | var h int16 = linker.BytesToInt16(bytes4) 47 | if g != h { 48 | t.Error("convert error") 49 | } 50 | 51 | var i int16 = 32767 52 | j := linker.BytesToInt16(linker.Int16ToBytes(i)) 53 | if i != j { 54 | t.Error("convert error") 55 | } 56 | 57 | var m int64 = time.Now().UnixNano() 58 | bytes5 := linker.Int64ToBytes(m) 59 | var n int64 = linker.BytesToInt64(bytes5) 60 | if m != n { 61 | t.Error("convert error") 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /showcases/minitask/src/commandrunner/commandrunner.go: -------------------------------------------------------------------------------- 1 | package commandrunner 2 | 3 | import ( 4 | logger "../logger" 5 | "os/exec" 6 | "strings" 7 | "runtime" 8 | "fmt" 9 | ) 10 | 11 | var DEBUG_LEVEL_SHORT = 1 12 | var DEBUG_LEVEL_LONG = 2 13 | 14 | /** 15 | * Execute command on server 16 | * 17 | * @author Waqar Alamgir 18 | */ 19 | func Run(data string, success chan string, failed chan string) { 20 | 21 | arr := strings.Split(data, "|") 22 | 23 | commandPath := arr[1] 24 | param := arr[2] 25 | params := arr[3] 26 | 27 | fmt.Println("OS: " + runtime.GOOS) 28 | 29 | // Excute the command 30 | if runtime.GOOS == "windows" { 31 | out, _ := exec.Command("cmd", "/c", commandPath + " " + params).Output() 32 | s := string(out) 33 | s = strings.Replace(s, "\r"," ",-1) 34 | s = strings.Replace(s, "\n"," ",-1) 35 | s = strings.Replace(s, " "," ",-1) 36 | output := commandPath + "|" + param + "|" + params + "|" + s 37 | logger.Log("Success command " + commandPath + params , DEBUG_LEVEL_LONG) 38 | success <- output 39 | } else { 40 | out, _ := exec.Command("sh", "-c", commandPath + " " + params).Output() 41 | s := string(out) 42 | s = strings.Replace(s, "\r"," ",-1) 43 | s = strings.Replace(s, "\n"," ",-1) 44 | s = strings.Replace(s, " "," ",-1) 45 | output := commandPath + "|" + param + "|" + params + "|" + s 46 | logger.Log("Success command " + commandPath + params , DEBUG_LEVEL_LONG) 47 | success <- output 48 | } 49 | } -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/usecase/signup_usecase.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 8 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/internal/tokenutil" 9 | ) 10 | 11 | type signupUsecase struct { 12 | userRepository domain.UserRepository 13 | contextTimeout time.Duration 14 | } 15 | 16 | func NewSignupUsecase(userRepository domain.UserRepository, timeout time.Duration) domain.SignupUsecase { 17 | return &signupUsecase{ 18 | userRepository: userRepository, 19 | contextTimeout: timeout, 20 | } 21 | } 22 | 23 | func (su *signupUsecase) Create(c context.Context, user *domain.User) error { 24 | ctx, cancel := context.WithTimeout(c, su.contextTimeout) 25 | defer cancel() 26 | return su.userRepository.Create(ctx, user) 27 | } 28 | 29 | func (su *signupUsecase) GetUserByEmail(c context.Context, email string) (domain.User, error) { 30 | ctx, cancel := context.WithTimeout(c, su.contextTimeout) 31 | defer cancel() 32 | return su.userRepository.GetByEmail(ctx, email) 33 | } 34 | 35 | func (su *signupUsecase) CreateAccessToken(user *domain.User, secret string, expiry int) (accessToken string, err error) { 36 | return tokenutil.CreateAccessToken(user, secret, expiry) 37 | } 38 | 39 | func (su *signupUsecase) CreateRefreshToken(user *domain.User, secret string, expiry int) (refreshToken string, err error) { 40 | return tokenutil.CreateRefreshToken(user, secret, expiry) 41 | } 42 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/usecase/refresh_token_usecase.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 8 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/internal/tokenutil" 9 | ) 10 | 11 | type refreshTokenUsecase struct { 12 | userRepository domain.UserRepository 13 | contextTimeout time.Duration 14 | } 15 | 16 | func NewRefreshTokenUsecase(userRepository domain.UserRepository, timeout time.Duration) domain.RefreshTokenUsecase { 17 | return &refreshTokenUsecase{ 18 | userRepository: userRepository, 19 | contextTimeout: timeout, 20 | } 21 | } 22 | 23 | func (rtu *refreshTokenUsecase) GetUserByID(c context.Context, email string) (domain.User, error) { 24 | ctx, cancel := context.WithTimeout(c, rtu.contextTimeout) 25 | defer cancel() 26 | return rtu.userRepository.GetByID(ctx, email) 27 | } 28 | 29 | func (rtu *refreshTokenUsecase) CreateAccessToken(user *domain.User, secret string, expiry int) (accessToken string, err error) { 30 | return tokenutil.CreateAccessToken(user, secret, expiry) 31 | } 32 | 33 | func (rtu *refreshTokenUsecase) CreateRefreshToken(user *domain.User, secret string, expiry int) (refreshToken string, err error) { 34 | return tokenutil.CreateRefreshToken(user, secret, expiry) 35 | } 36 | 37 | func (rtu *refreshTokenUsecase) ExtractIDFromToken(requestToken string, secret string) (string, error) { 38 | return tokenutil.ExtractIDFromToken(requestToken, secret) 39 | } 40 | -------------------------------------------------------------------------------- /showcases/db/database/exec_test.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | sqlmock "github.com/DATA-DOG/go-sqlmock" 8 | _ "github.com/go-sql-driver/mysql" 9 | ) 10 | 11 | func TestExec(t *testing.T) { 12 | 13 | tests := []struct { 14 | name string 15 | createErr bool 16 | queryErr bool 17 | wantErr bool 18 | }{ 19 | {"base-case", false, false, false}, 20 | {"create error", true, false, true}, 21 | {"query error", false, true, true}, 22 | } 23 | for _, tt := range tests { 24 | t.Run(tt.name, func(t *testing.T) { 25 | db, mock, err := sqlmock.New() 26 | if err != nil { 27 | t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) 28 | } 29 | defer db.Close() 30 | 31 | mock.ExpectExec("CREATE TABLE").WillReturnResult(sqlmock.NewResult(0, 0)) 32 | c := mock.ExpectExec("INSERT INTO").WillReturnResult(sqlmock.NewResult(0, 0)) 33 | if tt.createErr { 34 | c.WillReturnError(errors.New("failed")) 35 | } 36 | if !tt.createErr { 37 | m := mock.ExpectQuery("SELECT").WillReturnRows(sqlmock.NewRows([]string{"name", "created"})) 38 | if tt.queryErr { 39 | m.WillReturnError(errors.New("failed")) 40 | } 41 | } 42 | if err := Exec(db); (err != nil) != tt.wantErr { 43 | t.Errorf("Exec() error = %v, wantErr %v", err, tt.wantErr) 44 | } 45 | if err := mock.ExpectationsWereMet(); err != nil { 46 | t.Errorf("there were unfulfilled expections: %s", err) 47 | } 48 | }) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/api/controller/task_controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 7 | "github.com/gin-gonic/gin" 8 | "go.mongodb.org/mongo-driver/bson/primitive" 9 | ) 10 | 11 | type TaskController struct { 12 | TaskUsecase domain.TaskUsecase 13 | } 14 | 15 | func (tc *TaskController) Create(c *gin.Context) { 16 | var task domain.Task 17 | 18 | err := c.ShouldBind(&task) 19 | if err != nil { 20 | c.JSON(http.StatusBadRequest, domain.ErrorResponse{Message: err.Error()}) 21 | return 22 | } 23 | 24 | userID := c.GetString("x-user-id") 25 | task.ID = primitive.NewObjectID() 26 | 27 | task.UserID, err = primitive.ObjectIDFromHex(userID) 28 | if err != nil { 29 | c.JSON(http.StatusBadRequest, domain.ErrorResponse{Message: err.Error()}) 30 | return 31 | } 32 | 33 | err = tc.TaskUsecase.Create(c, &task) 34 | if err != nil { 35 | c.JSON(http.StatusInternalServerError, domain.ErrorResponse{Message: err.Error()}) 36 | return 37 | } 38 | 39 | c.JSON(http.StatusOK, domain.SuccessResponse{ 40 | Message: "Task created successfully", 41 | }) 42 | } 43 | 44 | func (u *TaskController) Fetch(c *gin.Context) { 45 | userID := c.GetString("x-user-id") 46 | 47 | tasks, err := u.TaskUsecase.FetchByUserID(c, userID) 48 | if err != nil { 49 | c.JSON(http.StatusInternalServerError, domain.ErrorResponse{Message: err.Error()}) 50 | return 51 | } 52 | 53 | c.JSON(http.StatusOK, tasks) 54 | } 55 | -------------------------------------------------------------------------------- /showcases/db/dbinterface/exec_test.go: -------------------------------------------------------------------------------- 1 | package dbinterface 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | sqlmock "github.com/DATA-DOG/go-sqlmock" 8 | _ "github.com/go-sql-driver/mysql" 9 | ) 10 | 11 | func TestExec(t *testing.T) { 12 | 13 | tests := []struct { 14 | name string 15 | createErr bool 16 | queryErr bool 17 | wantErr bool 18 | }{ 19 | {"base-case", false, false, false}, 20 | {"create error", true, false, true}, 21 | {"query error", false, true, true}, 22 | } 23 | for _, tt := range tests { 24 | t.Run(tt.name, func(t *testing.T) { 25 | db, mock, err := sqlmock.New() 26 | if err != nil { 27 | t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) 28 | } 29 | defer db.Close() 30 | 31 | mock.ExpectExec("CREATE TABLE").WillReturnResult(sqlmock.NewResult(0, 0)) 32 | c := mock.ExpectExec("INSERT INTO").WillReturnResult(sqlmock.NewResult(0, 0)) 33 | if tt.createErr { 34 | c.WillReturnError(errors.New("failed")) 35 | } 36 | if !tt.createErr { 37 | m := mock.ExpectQuery("SELECT").WillReturnRows(sqlmock.NewRows([]string{"name", "created"})) 38 | if tt.queryErr { 39 | m.WillReturnError(errors.New("failed")) 40 | } 41 | } 42 | if err := Exec(db); (err != nil) != tt.wantErr { 43 | t.Errorf("Exec() error = %v, wantErr %v", err, tt.wantErr) 44 | } 45 | if err := mock.ExpectationsWereMet(); err != nil { 46 | t.Errorf("there were unfulfilled expections: %s", err) 47 | } 48 | }) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/token/paseto_maker_test.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/stretchr/testify/require" 8 | "github.com/techschool/simplebank/util" 9 | ) 10 | 11 | func TestPasetoMaker(t *testing.T) { 12 | maker, err := NewPasetoMaker(util.RandomString(32)) 13 | require.NoError(t, err) 14 | 15 | username := util.RandomOwner() 16 | role := util.DepositorRole 17 | duration := time.Minute 18 | 19 | issuedAt := time.Now() 20 | expiredAt := issuedAt.Add(duration) 21 | 22 | token, payload, err := maker.CreateToken(username, role, duration) 23 | require.NoError(t, err) 24 | require.NotEmpty(t, token) 25 | require.NotEmpty(t, payload) 26 | 27 | payload, err = maker.VerifyToken(token) 28 | require.NoError(t, err) 29 | require.NotEmpty(t, token) 30 | 31 | require.NotZero(t, payload.ID) 32 | require.Equal(t, username, payload.Username) 33 | require.Equal(t, role, payload.Role) 34 | require.WithinDuration(t, issuedAt, payload.IssuedAt, time.Second) 35 | require.WithinDuration(t, expiredAt, payload.ExpiredAt, time.Second) 36 | } 37 | 38 | func TestExpiredPasetoToken(t *testing.T) { 39 | maker, err := NewPasetoMaker(util.RandomString(32)) 40 | require.NoError(t, err) 41 | 42 | token, payload, err := maker.CreateToken(util.RandomOwner(), util.DepositorRole, -time.Minute) 43 | require.NoError(t, err) 44 | require.NotEmpty(t, token) 45 | require.NotEmpty(t, payload) 46 | 47 | payload, err = maker.VerifyToken(token) 48 | require.Error(t, err) 49 | require.EqualError(t, err, ErrExpiredToken.Error()) 50 | require.Nil(t, payload) 51 | } 52 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/util/config.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/spf13/viper" 7 | ) 8 | 9 | // Config stores all configuration of the application. 10 | // The values are read by viper from a config file or environment variable. 11 | type Config struct { 12 | Environment string `mapstructure:"ENVIRONMENT"` 13 | DBSource string `mapstructure:"DB_SOURCE"` 14 | MigrationURL string `mapstructure:"MIGRATION_URL"` 15 | RedisAddress string `mapstructure:"REDIS_ADDRESS"` 16 | HTTPServerAddress string `mapstructure:"HTTP_SERVER_ADDRESS"` 17 | GRPCServerAddress string `mapstructure:"GRPC_SERVER_ADDRESS"` 18 | TokenSymmetricKey string `mapstructure:"TOKEN_SYMMETRIC_KEY"` 19 | AccessTokenDuration time.Duration `mapstructure:"ACCESS_TOKEN_DURATION"` 20 | RefreshTokenDuration time.Duration `mapstructure:"REFRESH_TOKEN_DURATION"` 21 | EmailSenderName string `mapstructure:"EMAIL_SENDER_NAME"` 22 | EmailSenderAddress string `mapstructure:"EMAIL_SENDER_ADDRESS"` 23 | EmailSenderPassword string `mapstructure:"EMAIL_SENDER_PASSWORD"` 24 | } 25 | 26 | // LoadConfig reads configuration from file or environment variables. 27 | func LoadConfig(path string) (config Config, err error) { 28 | viper.AddConfigPath(path) 29 | viper.SetConfigName("app") 30 | viper.SetConfigType("env") 31 | 32 | viper.AutomaticEnv() 33 | 34 | err = viper.ReadInConfig() 35 | if err != nil { 36 | return 37 | } 38 | 39 | err = viper.Unmarshal(&config) 40 | return 41 | } 42 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/mail/sender.go: -------------------------------------------------------------------------------- 1 | package mail 2 | 3 | import ( 4 | "fmt" 5 | "net/smtp" 6 | 7 | "github.com/jordan-wright/email" 8 | ) 9 | 10 | const ( 11 | smtpAuthAddress = "smtp.gmail.com" 12 | smtpServerAddress = "smtp.gmail.com:587" 13 | ) 14 | 15 | type EmailSender interface { 16 | SendEmail( 17 | subject string, 18 | content string, 19 | to []string, 20 | cc []string, 21 | bcc []string, 22 | attachFiles []string, 23 | ) error 24 | } 25 | 26 | type GmailSender struct { 27 | name string 28 | fromEmailAddress string 29 | fromEmailPassword string 30 | } 31 | 32 | func NewGmailSender(name string, fromEmailAddress string, fromEmailPassword string) EmailSender { 33 | return &GmailSender{ 34 | name: name, 35 | fromEmailAddress: fromEmailAddress, 36 | fromEmailPassword: fromEmailPassword, 37 | } 38 | } 39 | 40 | func (sender *GmailSender) SendEmail( 41 | subject string, 42 | content string, 43 | to []string, 44 | cc []string, 45 | bcc []string, 46 | attachFiles []string, 47 | ) error { 48 | e := email.NewEmail() 49 | e.From = fmt.Sprintf("%s <%s>", sender.name, sender.fromEmailAddress) 50 | e.Subject = subject 51 | e.HTML = []byte(content) 52 | e.To = to 53 | e.Cc = cc 54 | e.Bcc = bcc 55 | 56 | for _, f := range attachFiles { 57 | _, err := e.AttachFile(f) 58 | if err != nil { 59 | return fmt.Errorf("failed to attach file %s: %w", f, err) 60 | } 61 | } 62 | 63 | smtpAuth := smtp.PlainAuth("", sender.fromEmailAddress, sender.fromEmailPassword, smtpAuthAddress) 64 | return e.Send(smtpServerAddress, smtpAuth) 65 | } 66 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/gapi/authorization.go: -------------------------------------------------------------------------------- 1 | package gapi 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/techschool/simplebank/token" 9 | "google.golang.org/grpc/metadata" 10 | ) 11 | 12 | const ( 13 | authorizationHeader = "authorization" 14 | authorizationBearer = "bearer" 15 | ) 16 | 17 | func (server *Server) authorizeUser(ctx context.Context, accessibleRoles []string) (*token.Payload, error) { 18 | md, ok := metadata.FromIncomingContext(ctx) 19 | if !ok { 20 | return nil, fmt.Errorf("missing metadata") 21 | } 22 | 23 | values := md.Get(authorizationHeader) 24 | if len(values) == 0 { 25 | return nil, fmt.Errorf("missing authorization header") 26 | } 27 | 28 | authHeader := values[0] 29 | fields := strings.Fields(authHeader) 30 | if len(fields) < 2 { 31 | return nil, fmt.Errorf("invalid authorization header format") 32 | } 33 | 34 | authType := strings.ToLower(fields[0]) 35 | if authType != authorizationBearer { 36 | return nil, fmt.Errorf("unsupported authorization type: %s", authType) 37 | } 38 | 39 | accessToken := fields[1] 40 | payload, err := server.tokenMaker.VerifyToken(accessToken) 41 | if err != nil { 42 | return nil, fmt.Errorf("invalid access token: %s", err) 43 | } 44 | 45 | if !hasPermission(payload.Role, accessibleRoles) { 46 | return nil, fmt.Errorf("permission denied") 47 | } 48 | 49 | return payload, nil 50 | } 51 | 52 | func hasPermission(userRole string, accessibleRoles []string) bool { 53 | for _, role := range accessibleRoles { 54 | if userRole == role { 55 | return true 56 | } 57 | } 58 | return false 59 | } 60 | -------------------------------------------------------------------------------- /boilerplates/go-clean-architecture/go.mod: -------------------------------------------------------------------------------- 1 | // +heroku install ./api/main.go 2 | module github.com/L04DB4L4NC3R/jobs-mhrd 3 | 4 | go 1.13 5 | 6 | require ( 7 | github.com/auth0/go-jwt-middleware v0.0.0-20190805220309-36081240882b 8 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 9 | github.com/fatih/color v1.7.0 // indirect 10 | github.com/go-siris/siris v7.4.0+incompatible // indirect 11 | github.com/gorilla/handlers v1.4.2 12 | github.com/jinzhu/gorm v1.9.11 13 | github.com/labstack/echo v3.3.10+incompatible // indirect 14 | github.com/labstack/gommon v0.3.0 // indirect 15 | github.com/magiconair/properties v1.8.1 // indirect 16 | github.com/mattn/go-colorable v0.1.4 // indirect 17 | github.com/mattn/go-isatty v0.0.10 // indirect 18 | github.com/oxequa/interact v0.0.0-20171114182912-f8fb5795b5d7 // indirect 19 | github.com/oxequa/realize v2.0.2+incompatible // indirect 20 | github.com/pelletier/go-toml v1.6.0 // indirect 21 | github.com/rs/cors v1.7.0 22 | github.com/satori/go.uuid v1.2.0 // indirect 23 | github.com/sirupsen/logrus v1.2.0 24 | github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect 25 | github.com/spf13/afero v1.2.2 // indirect 26 | github.com/spf13/jwalterweatherman v1.1.0 // indirect 27 | github.com/spf13/pflag v1.0.5 // indirect 28 | github.com/spf13/viper v1.4.0 29 | github.com/urfave/negroni v1.0.0 // indirect 30 | github.com/valyala/fasttemplate v1.1.0 // indirect 31 | golang.org/x/sys v0.0.0-20191027211539-f8518d3b3627 // indirect 32 | golang.org/x/text v0.3.2 // indirect 33 | gopkg.in/urfave/cli.v2 v2.0.0-20190806201727-b62605953717 // indirect 34 | ) 35 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/token/paseto_maker.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/aead/chacha20poly1305" 8 | "github.com/o1egl/paseto" 9 | ) 10 | 11 | // PasetoMaker is a PASETO token maker 12 | type PasetoMaker struct { 13 | paseto *paseto.V2 14 | symmetricKey []byte 15 | } 16 | 17 | // NewPasetoMaker creates a new PasetoMaker 18 | func NewPasetoMaker(symmetricKey string) (Maker, error) { 19 | if len(symmetricKey) != chacha20poly1305.KeySize { 20 | return nil, fmt.Errorf("invalid key size: must be exactly %d characters", chacha20poly1305.KeySize) 21 | } 22 | 23 | maker := &PasetoMaker{ 24 | paseto: paseto.NewV2(), 25 | symmetricKey: []byte(symmetricKey), 26 | } 27 | 28 | return maker, nil 29 | } 30 | 31 | // CreateToken creates a new token for a specific username and duration 32 | func (maker *PasetoMaker) CreateToken(username string, role string, duration time.Duration) (string, *Payload, error) { 33 | payload, err := NewPayload(username, role, duration) 34 | if err != nil { 35 | return "", payload, err 36 | } 37 | 38 | token, err := maker.paseto.Encrypt(maker.symmetricKey, payload, nil) 39 | return token, payload, err 40 | } 41 | 42 | // VerifyToken checks if the token is valid or not 43 | func (maker *PasetoMaker) VerifyToken(token string) (*Payload, error) { 44 | payload := &Payload{} 45 | 46 | err := maker.paseto.Decrypt(token, maker.symmetricKey, payload, nil) 47 | if err != nil { 48 | return nil, ErrInvalidToken 49 | } 50 | 51 | err = payload.Valid() 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | return payload, nil 57 | } 58 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gothinkster/golang-gin-realworld-example-app 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/denisenkom/go-mssqldb v0.9.0 // indirect 7 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 8 | github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect 9 | github.com/gin-contrib/sse v0.1.0 // indirect 10 | github.com/gin-gonic/gin v1.8.1 11 | github.com/go-playground/validator/v10 v10.11.0 // indirect 12 | github.com/go-sql-driver/mysql v1.5.0 // indirect 13 | github.com/goccy/go-json v0.9.11 // indirect 14 | github.com/golang/protobuf v1.5.2 // indirect 15 | github.com/gosimple/slug v1.12.0 16 | github.com/jinzhu/gorm v1.9.16 17 | github.com/jinzhu/inflection v1.0.0 // indirect 18 | github.com/jinzhu/now v1.1.2 // indirect 19 | github.com/lib/pq v1.10.0 // indirect 20 | github.com/mattn/go-isatty v0.0.16 // indirect 21 | github.com/mattn/go-sqlite3 v1.14.15 // indirect 22 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 23 | github.com/pelletier/go-toml/v2 v2.0.3 // indirect 24 | github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect 25 | github.com/stretchr/testify v1.8.0 26 | golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 27 | golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c // indirect 28 | golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 // indirect 29 | google.golang.org/protobuf v1.28.1 // indirect 30 | gopkg.in/go-playground/assert.v1 v1.2.1 // indirect 31 | gopkg.in/go-playground/validator.v8 v8.18.2 32 | gopkg.in/yaml.v2 v2.4.0 // indirect 33 | ) 34 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/domain/mocks/ProfileUsecase.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v2.16.0. DO NOT EDIT. 2 | 3 | package mocks 4 | 5 | import ( 6 | context "context" 7 | 8 | domain "github.com/amitshekhariitbhu/go-backend-clean-architecture/domain" 9 | mock "github.com/stretchr/testify/mock" 10 | ) 11 | 12 | // ProfileUsecase is an autogenerated mock type for the ProfileUsecase type 13 | type ProfileUsecase struct { 14 | mock.Mock 15 | } 16 | 17 | // GetProfileByID provides a mock function with given fields: c, userID 18 | func (_m *ProfileUsecase) GetProfileByID(c context.Context, userID string) (*domain.Profile, error) { 19 | ret := _m.Called(c, userID) 20 | 21 | var r0 *domain.Profile 22 | if rf, ok := ret.Get(0).(func(context.Context, string) *domain.Profile); ok { 23 | r0 = rf(c, userID) 24 | } else { 25 | if ret.Get(0) != nil { 26 | r0 = ret.Get(0).(*domain.Profile) 27 | } 28 | } 29 | 30 | var r1 error 31 | if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { 32 | r1 = rf(c, userID) 33 | } else { 34 | r1 = ret.Error(1) 35 | } 36 | 37 | return r0, r1 38 | } 39 | 40 | type mockConstructorTestingTNewProfileUsecase interface { 41 | mock.TestingT 42 | Cleanup(func()) 43 | } 44 | 45 | // NewProfileUsecase creates a new instance of ProfileUsecase. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. 46 | func NewProfileUsecase(t mockConstructorTestingTNewProfileUsecase) *ProfileUsecase { 47 | mock := &ProfileUsecase{} 48 | mock.Mock.Test(t) 49 | 50 | t.Cleanup(func() { mock.AssertExpectations(t) }) 51 | 52 | return mock 53 | } 54 | -------------------------------------------------------------------------------- /boilerplates/go-backend-clean-architecture/mongo/mocks/Database.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v2.16.0. DO NOT EDIT. 2 | 3 | package mocks 4 | 5 | import ( 6 | mongo "github.com/amitshekhariitbhu/go-backend-clean-architecture/mongo" 7 | mock "github.com/stretchr/testify/mock" 8 | ) 9 | 10 | // Database is an autogenerated mock type for the Database type 11 | type Database struct { 12 | mock.Mock 13 | } 14 | 15 | // Client provides a mock function with given fields: 16 | func (_m *Database) Client() mongo.Client { 17 | ret := _m.Called() 18 | 19 | var r0 mongo.Client 20 | if rf, ok := ret.Get(0).(func() mongo.Client); ok { 21 | r0 = rf() 22 | } else { 23 | if ret.Get(0) != nil { 24 | r0 = ret.Get(0).(mongo.Client) 25 | } 26 | } 27 | 28 | return r0 29 | } 30 | 31 | // Collection provides a mock function with given fields: _a0 32 | func (_m *Database) Collection(_a0 string) mongo.Collection { 33 | ret := _m.Called(_a0) 34 | 35 | var r0 mongo.Collection 36 | if rf, ok := ret.Get(0).(func(string) mongo.Collection); ok { 37 | r0 = rf(_a0) 38 | } else { 39 | if ret.Get(0) != nil { 40 | r0 = ret.Get(0).(mongo.Collection) 41 | } 42 | } 43 | 44 | return r0 45 | } 46 | 47 | type mockConstructorTestingTNewDatabase interface { 48 | mock.TestingT 49 | Cleanup(func()) 50 | } 51 | 52 | // NewDatabase creates a new instance of Database. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. 53 | func NewDatabase(t mockConstructorTestingTNewDatabase) *Database { 54 | mock := &Database{} 55 | mock.Mock.Test(t) 56 | 57 | t.Cleanup(func() { mock.AssertExpectations(t) }) 58 | 59 | return mock 60 | } 61 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/api/middleware.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net/http" 7 | "strings" 8 | 9 | "github.com/gin-gonic/gin" 10 | "github.com/techschool/simplebank/token" 11 | ) 12 | 13 | const ( 14 | authorizationHeaderKey = "authorization" 15 | authorizationTypeBearer = "bearer" 16 | authorizationPayloadKey = "authorization_payload" 17 | ) 18 | 19 | // AuthMiddleware creates a gin middleware for authorization 20 | func authMiddleware(tokenMaker token.Maker) gin.HandlerFunc { 21 | return func(ctx *gin.Context) { 22 | authorizationHeader := ctx.GetHeader(authorizationHeaderKey) 23 | 24 | if len(authorizationHeader) == 0 { 25 | err := errors.New("authorization header is not provided") 26 | ctx.AbortWithStatusJSON(http.StatusUnauthorized, errorResponse(err)) 27 | return 28 | } 29 | 30 | fields := strings.Fields(authorizationHeader) 31 | if len(fields) < 2 { 32 | err := errors.New("invalid authorization header format") 33 | ctx.AbortWithStatusJSON(http.StatusUnauthorized, errorResponse(err)) 34 | return 35 | } 36 | 37 | authorizationType := strings.ToLower(fields[0]) 38 | if authorizationType != authorizationTypeBearer { 39 | err := fmt.Errorf("unsupported authorization type %s", authorizationType) 40 | ctx.AbortWithStatusJSON(http.StatusUnauthorized, errorResponse(err)) 41 | return 42 | } 43 | 44 | accessToken := fields[1] 45 | payload, err := tokenMaker.VerifyToken(accessToken) 46 | if err != nil { 47 | ctx.AbortWithStatusJSON(http.StatusUnauthorized, errorResponse(err)) 48 | return 49 | } 50 | 51 | ctx.Set(authorizationPayloadKey, payload) 52 | ctx.Next() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /showcases/golang-gin-realworld-example-app/users/serializers.go: -------------------------------------------------------------------------------- 1 | package users 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | 6 | "github.com/gothinkster/golang-gin-realworld-example-app/common" 7 | ) 8 | 9 | type ProfileSerializer struct { 10 | C *gin.Context 11 | UserModel 12 | } 13 | 14 | // Declare your response schema here 15 | type ProfileResponse struct { 16 | ID uint `json:"-"` 17 | Username string `json:"username"` 18 | Bio string `json:"bio"` 19 | Image *string `json:"image"` 20 | Following bool `json:"following"` 21 | } 22 | 23 | // Put your response logic including wrap the userModel here. 24 | func (self *ProfileSerializer) Response() ProfileResponse { 25 | myUserModel := self.C.MustGet("my_user_model").(UserModel) 26 | profile := ProfileResponse{ 27 | ID: self.ID, 28 | Username: self.Username, 29 | Bio: self.Bio, 30 | Image: self.Image, 31 | Following: myUserModel.isFollowing(self.UserModel), 32 | } 33 | return profile 34 | } 35 | 36 | type UserSerializer struct { 37 | c *gin.Context 38 | } 39 | 40 | type UserResponse struct { 41 | Username string `json:"username"` 42 | Email string `json:"email"` 43 | Bio string `json:"bio"` 44 | Image *string `json:"image"` 45 | Token string `json:"token"` 46 | } 47 | 48 | func (self *UserSerializer) Response() UserResponse { 49 | myUserModel := self.c.MustGet("my_user_model").(UserModel) 50 | user := UserResponse{ 51 | Username: myUserModel.Username, 52 | Email: myUserModel.Email, 53 | Bio: myUserModel.Bio, 54 | Image: myUserModel.Image, 55 | Token: common.GenToken(myUserModel.ID), 56 | } 57 | return user 58 | } 59 | -------------------------------------------------------------------------------- /showcases/go-boot/utils/encrypt/aes.go: -------------------------------------------------------------------------------- 1 | package encrypt 2 | 3 | import ( 4 | "bytes" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | ) 8 | 9 | // AES是对称加密算法 10 | // AES-128。key长度:16, 24, 32 bytes 对应 AES-128, AES-192, AES-256 11 | // 记住每次加密解密前都要设置iv. 12 | 13 | // 该包默认的密匙 14 | const defaultAesKey = "b8ca9aa66def05ff3f24919274bb4a66" 15 | 16 | func Encrypt(plaintext []byte) ([]byte, error) { 17 | key := []byte(defaultAesKey) 18 | block, err := aes.NewCipher(key) 19 | if err != nil { 20 | return nil, err 21 | } 22 | 23 | blockSize := block.BlockSize() 24 | plaintext = PKCS5Padding(plaintext, blockSize) 25 | 26 | blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) 27 | ciphertext := make([]byte, len(plaintext)) 28 | 29 | blockMode.CryptBlocks(ciphertext, plaintext) 30 | return ciphertext, nil 31 | } 32 | 33 | func Decrypt(ciphertext []byte) ([]byte, error) { 34 | key := []byte(defaultAesKey) 35 | block, err := aes.NewCipher(key) 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | blockSize := block.BlockSize() 41 | blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) 42 | plaintext := make([]byte, len(ciphertext)) 43 | 44 | blockMode.CryptBlocks(plaintext, ciphertext) 45 | plaintext = PKCS5UnPadding(plaintext) 46 | return plaintext, nil 47 | } 48 | 49 | func PKCS5Padding(plaintext []byte, blockSize int) []byte { 50 | padding := blockSize - len(plaintext)%blockSize 51 | padtext := bytes.Repeat([]byte{byte(padding)}, padding) 52 | return append(plaintext, padtext...) 53 | } 54 | 55 | func PKCS5UnPadding(plaintext []byte) []byte { 56 | length := len(plaintext) 57 | // 去掉最后一个字节 unpadding 次 58 | unpadding := int(plaintext[length-1]) 59 | return plaintext[:(length - unpadding)] 60 | } 61 | -------------------------------------------------------------------------------- /showcases/go-boot/server.go: -------------------------------------------------------------------------------- 1 | package go_boot 2 | 3 | import ( 4 | "io" 5 | "log" 6 | 7 | "github.com/wxyyxc1992/go-boot/utils/codec" 8 | ) 9 | 10 | const ( 11 | MaxPayload = 1024 * 1024 12 | ) 13 | 14 | const ( 15 | OperatorHeartbeat = iota 16 | OperatorMax = 1024 17 | ) 18 | 19 | type ( 20 | Handler interface { 21 | Handle(Context) 22 | } 23 | HandlerFunc func(Context) 24 | ErrorHandler func(error) 25 | Server struct { 26 | config Config 27 | router *Router 28 | errorHandler ErrorHandler 29 | constructHandler Handler 30 | destructHandler Handler 31 | pingHandler Handler 32 | } 33 | ) 34 | 35 | func NewServer(config Config) *Server { 36 | if config.ContentType == "" { 37 | config.ContentType = codec.JSON 38 | } 39 | 40 | if config.MaxPayload == 0 { 41 | config.MaxPayload = MaxPayload 42 | } 43 | 44 | return &Server{ 45 | config: config, 46 | errorHandler: func(err error) { 47 | if err != io.EOF { 48 | log.Println(err.Error()) 49 | } 50 | }, 51 | } 52 | } 53 | 54 | // 设置默认错误处理方法 55 | func (s *Server) OnError(errorHandler ErrorHandler) { 56 | s.errorHandler = errorHandler 57 | } 58 | 59 | // 客户端链接断开以后执行回收操作 60 | func (s *Server) OnClose(handler Handler) { 61 | s.destructHandler = handler 62 | } 63 | 64 | // 客户端建立连接以后初始化操作 65 | func (s *Server) OnOpen(handler Handler) { 66 | s.constructHandler = handler 67 | } 68 | 69 | // 设置心跳包的handler,需要客户端发送心跳包才能够触发 70 | // 客户端发送心跳包,服务端未调用此方法时只起到建立长连接的作用 71 | func (s *Server) OnPing(handler Handler) { 72 | s.pingHandler = handler 73 | } 74 | 75 | // 绑定路由 76 | func (s *Server) BindRouter(r *Router) { 77 | s.router = r 78 | } 79 | 80 | func (f HandlerFunc) Handle(ctx Context) { 81 | f(ctx) 82 | } 83 | -------------------------------------------------------------------------------- /showcases/2024~simplebank/val/validator.go: -------------------------------------------------------------------------------- 1 | package val 2 | 3 | import ( 4 | "fmt" 5 | "net/mail" 6 | "regexp" 7 | ) 8 | 9 | var ( 10 | isValidUsername = regexp.MustCompile(`^[a-z0-9_]+$`).MatchString 11 | isValidFullName = regexp.MustCompile(`^[a-zA-Z\s]+$`).MatchString 12 | ) 13 | 14 | func ValidateString(value string, minLength int, maxLength int) error { 15 | n := len(value) 16 | if n < minLength || n > maxLength { 17 | return fmt.Errorf("must contain from %d-%d characters", minLength, maxLength) 18 | } 19 | return nil 20 | } 21 | 22 | func ValidateUsername(value string) error { 23 | if err := ValidateString(value, 3, 100); err != nil { 24 | return err 25 | } 26 | if !isValidUsername(value) { 27 | return fmt.Errorf("must contain only lowercase letters, digits, or underscore") 28 | } 29 | return nil 30 | } 31 | 32 | func ValidateFullName(value string) error { 33 | if err := ValidateString(value, 3, 100); err != nil { 34 | return err 35 | } 36 | if !isValidFullName(value) { 37 | return fmt.Errorf("must contain only letters or spaces") 38 | } 39 | return nil 40 | } 41 | 42 | func ValidatePassword(value string) error { 43 | return ValidateString(value, 6, 100) 44 | } 45 | 46 | func ValidateEmail(value string) error { 47 | if err := ValidateString(value, 3, 200); err != nil { 48 | return err 49 | } 50 | if _, err := mail.ParseAddress(value); err != nil { 51 | return fmt.Errorf("is not a valid email address") 52 | } 53 | return nil 54 | } 55 | 56 | func ValidateEmailId(value int64) error { 57 | if value <= 0 { 58 | return fmt.Errorf("must be a positive integer") 59 | } 60 | return nil 61 | } 62 | 63 | func ValidateSecretCode(value string) error { 64 | return ValidateString(value, 32, 128) 65 | } 66 | -------------------------------------------------------------------------------- /showcases/go-boot/router.go: -------------------------------------------------------------------------------- 1 | package go_boot 2 | 3 | import ( 4 | "hash/crc32" 5 | "strconv" 6 | ) 7 | 8 | type ( 9 | Router struct { 10 | prefix string 11 | handlerContainer map[uint32]Handler 12 | routerMiddleware map[uint32][]Middleware 13 | middleware []Middleware 14 | } 15 | 16 | LinkRouter func(*Router) 17 | ) 18 | 19 | func NewRouter() *Router { 20 | return &Router{ 21 | handlerContainer: make(map[uint32]Handler), 22 | routerMiddleware: make(map[uint32][]Middleware), 23 | } 24 | } 25 | 26 | // 获取带命名空间router 27 | func (r *Router) NSRouter(prefix string, params ...LinkRouter) *Router { 28 | r.prefix = prefix 29 | for _, p := range params { 30 | p(r) 31 | } 32 | 33 | return r 34 | } 35 | 36 | // 命名空间路由注册路由和中间件 37 | func (r *Router) NSRoute(pattern string, handler Handler, middleware ...Middleware) LinkRouter { 38 | return func(r *Router) { 39 | if r.prefix != "" { 40 | pattern = r.prefix + pattern 41 | } 42 | 43 | r.Route(pattern, handler, middleware...) 44 | } 45 | } 46 | 47 | // 注册路由,路由中间件 48 | func (r *Router) Route(pattern string, handler Handler, middleware ...Middleware) *Router { 49 | operator := crc32.ChecksumIEEE([]byte(pattern)) 50 | if operator <= OperatorMax { 51 | panic("Unavailable operator, the value of crc32 need less than " + strconv.Itoa(OperatorMax)) 52 | } 53 | 54 | r.routerMiddleware[operator] = append(r.routerMiddleware[operator], middleware...) 55 | 56 | if _, ok := r.handlerContainer[operator]; !ok { 57 | r.handlerContainer[operator] = handler 58 | } 59 | 60 | return r 61 | } 62 | 63 | // 添加请求需要进行处理的中间件 64 | func (r *Router) Use(middleware ...Middleware) *Router { 65 | r.middleware = append(r.middleware, middleware...) 66 | 67 | return r 68 | } 69 | --------------------------------------------------------------------------------