├── golang-async-logging-library ├── .dockerignore ├── go.mod ├── Dockerfile ├── .gitattributes ├── README.md ├── .gitignore ├── cmd │ └── main.go └── module3_test.go ├── gostandard_libs ├── filemaker_demo │ ├── filetotest.txt │ ├── go.mod │ └── main.go ├── args_demo │ ├── go.mod │ └── main.go ├── flag_demo │ ├── go.mod │ └── main.go ├── fmt_demo │ ├── go.mod │ └── main.go ├── bufio_demo │ ├── go.mod │ └── main.go ├── custom_type │ ├── go.mod │ ├── createtype.go │ ├── customtype.go │ ├── typesruntime.go │ ├── functions.go │ └── media │ │ └── media.go ├── loger_demo │ ├── go.mod │ ├── log.txt │ ├── newlog.txt │ ├── newloger.go │ └── main.go ├── print_demo │ ├── go.mod │ └── main.go ├── trace_demo │ ├── go.mod │ └── main.go ├── others_demo │ ├── slice.go │ └── primitives.go └── time_demo │ └── main.go ├── testinggolang ├── go.mod ├── main_test.go ├── messages │ ├── message.go │ └── message_test.go └── README.md ├── microservices ├── product-api │ ├── README.md │ ├── go.mod │ ├── go.sum │ ├── main.go │ ├── data │ │ └── products.go │ └── handlers │ │ └── handlers.go ├── product-api-withswagger │ ├── handlers │ │ ├── utils.go │ │ ├── post.go │ │ ├── put.go │ │ ├── delete.go │ │ ├── middleware.go │ │ ├── products.go │ │ ├── get.go │ │ └── docs.go │ ├── .vscode │ │ └── settings.json │ ├── swagger.bat │ ├── make.bat │ ├── data │ │ ├── json.go │ │ ├── product_test.go │ │ ├── validation.go │ │ └── products.go │ ├── Makefile │ ├── README.md │ ├── go.mod │ └── main.go ├── .vscode │ └── settings.json ├── product-api-gorilla │ ├── swagger.bat │ ├── make.bat │ ├── data │ │ ├── product_test.go │ │ └── products.go │ ├── Makefile │ ├── swagger.yaml │ ├── handlers │ │ ├── docs.go │ │ └── handlers.go │ ├── go.mod │ ├── README.md │ └── main.go └── product-api-withswagger-client │ ├── client.bat │ ├── main_test.go │ ├── go.mod │ ├── models │ └── generic_error.go │ └── client │ └── products │ ├── delete_product_responses.go │ ├── list_products_responses.go │ └── list_single_product_responses.go ├── pluralsight_projects ├── golang-advanced-branching │ ├── .dockerignore │ ├── go.mod │ ├── Dockerfile │ ├── .gitattributes │ ├── feedback.json │ └── .gitignore ├── golang-personal-budget-cli │ ├── go.mod │ ├── module1 │ │ └── budget_1.go │ ├── Dockerfile │ ├── README.md │ ├── main.go │ └── module2 │ │ └── budget_2.go └── golang-fifa-world-cup-web-service │ ├── go.mod │ ├── .vscode │ └── settings.json │ ├── Dockerfile │ ├── server.go │ ├── handlers │ ├── handlers_test_helpers.go │ ├── 03_dispatch_handler_test.go │ ├── handlers.go │ └── 02_post_handler_test.go │ ├── Makefile │ ├── README.md │ └── data │ └── winners.json ├── grpcdemo ├── Makefile ├── cert │ ├── client-ext.cnf │ ├── server-ext.cnf │ └── generate_cert.sh ├── .vscode │ └── settings.json ├── client │ ├── Penguins.jpg │ ├── go.mod │ └── Dockerfile ├── server │ ├── go.mod │ ├── Dockerfile │ └── data.go ├── pb │ └── messages.proto └── README.md ├── pingpong ├── README.md ├── go.mod └── main.go ├── distributedappdocker ├── .dockerignore ├── go.mod ├── teacherportal │ ├── templates.go │ ├── students.gohtml │ └── student.gohtml ├── Dockerfile.logservice ├── registry │ └── registration.go ├── Dockerfile.gradingservice ├── Dockerfile.registryservice ├── Dockerfile.teacherportalservice ├── log │ ├── client.go │ └── server.go ├── cmd │ ├── registryservice │ │ └── main.go │ ├── logservice │ │ └── main.go │ ├── gradingservice │ │ └── main.go │ └── teacherportalservice │ │ └── main.go ├── grades │ ├── grades.go │ ├── mockdata.go │ └── server.go ├── Readme.md └── service │ └── service.go ├── functions ├── go.mod └── simplemaths │ ├── expressions.go │ └── scemanticversion.go ├── webservice ├── go.mod ├── controllers │ ├── front.go │ └── user.go ├── main.go └── models │ └── user.go ├── distributedapp ├── go.mod ├── teacherportal │ ├── templates.go │ ├── students.gohtml │ └── student.gohtml ├── Readme.md ├── registry │ └── registration.go ├── cmd │ ├── registryservice │ │ └── main.go │ ├── logservice │ │ └── main.go │ ├── gradingservice │ │ └── main.go │ └── teacherportalservice │ │ └── main.go ├── log │ ├── client.go │ └── server.go ├── grades │ ├── grades.go │ ├── mockdata.go │ └── server.go └── service │ └── service.go ├── concurrentprogram ├── go.mod ├── ChannelDemo │ └── main.go └── books │ └── book.go ├── customdatatypes ├── datatypes1 │ ├── go.mod │ ├── main.go │ └── organisation │ │ └── person.go ├── datatypes2 │ ├── go.mod │ ├── main.go │ └── organisation │ │ └── person.go ├── datatypes3 │ ├── go.mod │ ├── main.go │ └── organisation │ │ └── person.go ├── datatypes4 │ ├── go.mod │ ├── main.go │ └── organisation │ │ └── person.go └── datatypes5 │ ├── go.mod │ ├── main.go │ └── organisation │ └── person.go ├── ginframeworkdemo ├── Readme.md ├── requestdemo │ ├── public │ │ ├── app.css │ │ ├── index.html │ │ └── employee.html │ └── go.mod ├── vacationtracker │ ├── public │ │ ├── app.css │ │ ├── index.html │ │ └── employee.html │ ├── cmd │ │ └── vacationtrack │ │ │ └── main_test.go │ ├── templates │ │ ├── index.tmpl │ │ └── employee.tmpl │ ├── go.mod │ └── employee │ │ ├── employee.go │ │ └── data.go └── responsedemo │ ├── index.html │ ├── go.mod │ └── main.go ├── .vscode └── settings.json ├── .gitignore ├── LICENSE └── README.md /golang-async-logging-library/.dockerignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /gostandard_libs/filemaker_demo/filetotest.txt: -------------------------------------------------------------------------------- 1 | Hello 2 | hi -------------------------------------------------------------------------------- /testinggolang/go.mod: -------------------------------------------------------------------------------- 1 | module gotesting 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /golang-async-logging-library/go.mod: -------------------------------------------------------------------------------- 1 | module alog 2 | 3 | go 1.14 4 | -------------------------------------------------------------------------------- /microservices/product-api/README.md: -------------------------------------------------------------------------------- 1 | ### Product API Standard Library -------------------------------------------------------------------------------- /pluralsight_projects/golang-advanced-branching/.dockerignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /grpcdemo/Makefile: -------------------------------------------------------------------------------- 1 | cert: 2 | cd cert; ./generate_cert.sh;cd .. 3 | .PHONY: cert -------------------------------------------------------------------------------- /microservices/product-api-withswagger/handlers/utils.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | -------------------------------------------------------------------------------- /pingpong/README.md: -------------------------------------------------------------------------------- 1 | ### A ping pong application using Goroutine and Channels. -------------------------------------------------------------------------------- /distributedappdocker/.dockerignore: -------------------------------------------------------------------------------- 1 | #Removing exe file copy built locally. 2 | *.exe 3 | *.md -------------------------------------------------------------------------------- /functions/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/functions 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /pingpong/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/pingpong 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /webservice/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/webservice 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /microservices/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "makefile.extensionOutputFolder": "./.vscode" 3 | } -------------------------------------------------------------------------------- /pluralsight_projects/golang-advanced-branching/go.mod: -------------------------------------------------------------------------------- 1 | module vehicle-rating 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-personal-budget-cli/go.mod: -------------------------------------------------------------------------------- 1 | module personal-budget 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /distributedapp/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/distributedapp 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /grpcdemo/cert/client-ext.cnf: -------------------------------------------------------------------------------- 1 | subjectAltName=DNS:*.gogrpcclient.com,IP:0.0.0.0,IP:172.0.0.1,DNS:localhost -------------------------------------------------------------------------------- /grpcdemo/cert/server-ext.cnf: -------------------------------------------------------------------------------- 1 | subjectAltName=DNS:*.gogrpcserver.com,IP:0.0.0.0,IP:127.0.0.1,DNS:localhost -------------------------------------------------------------------------------- /concurrentprogram/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/concurrentprogram 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /distributedappdocker/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/distributedapp 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /grpcdemo/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "go.formatTool": "goimports", 3 | "editor.formatOnSave": true 4 | } -------------------------------------------------------------------------------- /grpcdemo/client/Penguins.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erankitcs/golang_learning/HEAD/grpcdemo/client/Penguins.jpg -------------------------------------------------------------------------------- /gostandard_libs/args_demo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/gostandard_libs/args_demo 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /gostandard_libs/flag_demo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/gostandard_libs/flag_demo 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /gostandard_libs/fmt_demo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/gostandard_libs/fmt_demo 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "makefile.extensionOutputFolder": "./.vscode" 3 | } -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/go.mod: -------------------------------------------------------------------------------- 1 | module golang-fifa-world-cup-web-service 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /customdatatypes/datatypes1/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/customdatatypes/datatypes1 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /customdatatypes/datatypes2/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/customdatatypes/datatypes2 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /customdatatypes/datatypes3/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/customdatatypes/datatypes3 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /customdatatypes/datatypes4/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/customdatatypes/datatypes4 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /customdatatypes/datatypes5/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/customdatatypes/datatypes5 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /gostandard_libs/bufio_demo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/gostandard_libs/bufio_demo 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /gostandard_libs/custom_type/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/gostandard_libs/custom_type 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /gostandard_libs/loger_demo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/gostandard_libs/loger_demo 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /gostandard_libs/print_demo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/gostandard_libs/print_demo 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /gostandard_libs/trace_demo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/gostandard_libs/trace_demo 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /microservices/product-api/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/microservices/product-api 2 | 3 | go 1.17 4 | 5 | -------------------------------------------------------------------------------- /gostandard_libs/filemaker_demo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/gostandard_libs/filemaker_demo 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /ginframeworkdemo/Readme.md: -------------------------------------------------------------------------------- 1 | ## Working with Gin Framework 2 | 3 | ### Installing Gin 4 | ``` 5 | go get -u github.com/gin-gonic/gin 6 | ``` -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "makefile.extensionOutputFolder": "./.vscode" 3 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "go.toolsEnvVars": { 3 | "GOROOT": "C:\\Program Files\\Go" 4 | }, 5 | "go.alternateTools": { 6 | } 7 | } -------------------------------------------------------------------------------- /microservices/product-api-gorilla/swagger.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo. 3 | docker run --rm -it --env GOPATH=/go -v %CD%:/go/src -w /go/src quay.io/goswagger/swagger generate spec -o ./swagger.yaml --scan-models -------------------------------------------------------------------------------- /microservices/product-api-withswagger/swagger.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo. 3 | docker run --rm -it --env GOPATH=/go -v %CD%:/go/src -w /go/src quay.io/goswagger/swagger generate spec -o ./swagger.yaml --scan-models -------------------------------------------------------------------------------- /gostandard_libs/others_demo/slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func main() { 9 | 10 | v := reflect.TypeOf(123) 11 | fmt.Println(reflect.SliceOf(v)) 12 | } 13 | -------------------------------------------------------------------------------- /microservices/product-api-gorilla/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO off 2 | WHERE /q swagger 3 | IF %ERRORLEVEL% NEQ 0 go get -u github.com/go-swagger/go-swagger/cmd/swagger 4 | 5 | swagger generate spec -o ./swagger.yaml --scan-models -------------------------------------------------------------------------------- /microservices/product-api-withswagger/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO off 2 | WHERE /q swagger 3 | IF %ERRORLEVEL% NEQ 0 go get -u github.com/go-swagger/go-swagger/cmd/swagger 4 | 5 | swagger generate spec -o ./swagger.yaml --scan-models -------------------------------------------------------------------------------- /testinggolang/main_test.go: -------------------------------------------------------------------------------- 1 | package main_test 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestAddition(t *testing.T) { 8 | got := 2 + 3 9 | expected := 4 10 | if got != expected { 11 | t.Errorf("Did not get expected result.") 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testinggolang/messages/message.go: -------------------------------------------------------------------------------- 1 | package messages 2 | 3 | import "fmt" 4 | 5 | func Greet(name string) string { 6 | return fmt.Sprintf("Hello, %v!", name) 7 | } 8 | 9 | func depart(name string) string { 10 | return fmt.Sprintf("Goodbye, %v", name) 11 | } 12 | -------------------------------------------------------------------------------- /gostandard_libs/loger_demo/log.txt: -------------------------------------------------------------------------------- 1 | INFO: 2022/04/09 17:51:50 main.go:37: this is an information message! 2 | WARNING: 2022/04/09 17:51:50 main.go:40: this is a warning 3 | ERROR: 2022/04/09 17:51:50 main.go:43: this is an error 4 | FATAL: 2022/04/09 17:51:50 main.go:46: we crashed 5 | -------------------------------------------------------------------------------- /ginframeworkdemo/requestdemo/public/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | width: 600px; 3 | } 4 | table { 5 | border-collapse: collapse; 6 | } 7 | 8 | tr > :is(th, td) { 9 | border: 1px solid black; 10 | padding: 5px; 11 | } 12 | 13 | tr > :is(th, td):not(:first-child) { 14 | text-align: center; 15 | } -------------------------------------------------------------------------------- /ginframeworkdemo/vacationtracker/public/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | width: 600px; 3 | } 4 | table { 5 | border-collapse: collapse; 6 | } 7 | 8 | tr > :is(th, td) { 9 | border: 1px solid black; 10 | padding: 5px; 11 | } 12 | 13 | tr > :is(th, td):not(:first-child) { 14 | text-align: center; 15 | } -------------------------------------------------------------------------------- /pluralsight_projects/golang-personal-budget-cli/module1/budget_1.go: -------------------------------------------------------------------------------- 1 | package module1 2 | 3 | // Budget stores budget information 4 | type Budget struct { 5 | Max float32 6 | Items []Item 7 | } 8 | 9 | // Item stores item information 10 | type Item struct { 11 | Description string 12 | Price float32 13 | } 14 | -------------------------------------------------------------------------------- /golang-async-logging-library/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.14.0 2 | 3 | ENV CGO_ENABLED 0 4 | 5 | WORKDIR /src/app 6 | 7 | RUN addgroup --system projects && adduser --system projects --ingroup projects 8 | 9 | RUN chown -R projects:projects /src/app 10 | 11 | USER projects 12 | 13 | COPY . . 14 | 15 | RUN go install -v ./... 16 | -------------------------------------------------------------------------------- /microservices/product-api-gorilla/data/product_test.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import "testing" 4 | 5 | func TestProductValidate(t *testing.T) { 6 | p := &Product{ 7 | Name: "Tea", 8 | Price: 1.00, 9 | SKU: "sss-vggvgv-vttv", 10 | } 11 | err := p.Validate() 12 | if err != nil { 13 | t.Fatal(err) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gostandard_libs/loger_demo/newlog.txt: -------------------------------------------------------------------------------- 1 | INFO: 07:58:18.785601 D:/Tech/GoLang/golang_learning/gostandard_libs/loger_demo/newloger.go:30: This is info 2 | WARNING: 2022/04/09 17:58:18 newloger.go:31: This is warning. 3 | ERROR: 2022/04/09 17:58:18 newloger.go:32: This is error 4 | FATAL: 2022/04/09 17:58:18 newloger.go:33: This is fetal error. 5 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger-client/client.bat: -------------------------------------------------------------------------------- 1 | @ECHO off 2 | WHERE /q swagger 3 | IF %ERRORLEVEL% NEQ 0 go get -u github.com/go-swagger/go-swagger/cmd/swagger 4 | go mod init github.com/erankitcs/golang_learning/microservices/productapiclient 5 | swagger generate client -f ./../product-api-withswagger/swagger.yaml -A productapi 6 | go mod tidy -------------------------------------------------------------------------------- /pluralsight_projects/golang-advanced-branching/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.13.0 2 | 3 | ENV CGO_ENABLED 0 4 | 5 | WORKDIR /src/app 6 | 7 | RUN addgroup --system projects && adduser --system projects --ingroup projects 8 | 9 | RUN chown -R projects:projects /src/app 10 | 11 | USER projects 12 | 13 | COPY . . 14 | 15 | RUN go install -v ./... 16 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-personal-budget-cli/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.13 2 | 3 | ENV CGO_ENABLED 0 4 | 5 | WORKDIR /src/app 6 | 7 | RUN addgroup --system projects && adduser --system projects --ingroup projects 8 | 9 | RUN chown -R projects:projects /src/app 10 | 11 | USER projects 12 | 13 | COPY . . 14 | 15 | RUN go install -v ./... 16 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.13 2 | 3 | ENV CGO_ENABLED 0 4 | 5 | WORKDIR /src/app 6 | 7 | RUN addgroup --system projects && adduser --system projects --ingroup projects 8 | 9 | RUN chown -R projects:projects /src/app 10 | 11 | USER projects 12 | 13 | COPY . . 14 | 15 | RUN go install -v ./... 16 | -------------------------------------------------------------------------------- /golang-async-logging-library/.gitattributes: -------------------------------------------------------------------------------- 1 | # From https://help.github.com/en/articles/configuring-git-to-handle-line-endings 2 | # Set the default behavior, in case people don't have core.autocrlf set. 3 | * text=auto 4 | 5 | # Explicitly declare text files you want to always be normalized and converted 6 | # to native line endings on checkout. 7 | *.go text 8 | 9 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/data/json.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | ) 7 | 8 | func ToJSON(i interface{}, w io.Writer) error { 9 | e := json.NewEncoder(w) 10 | return e.Encode(i) 11 | } 12 | 13 | func FromJSON(i interface{}, r io.Reader) error { 14 | e := json.NewDecoder(r) 15 | return e.Decode(i) 16 | } 17 | -------------------------------------------------------------------------------- /.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 | *.log 17 | *.pem 18 | *.key 19 | *.srl -------------------------------------------------------------------------------- /microservices/product-api-withswagger/data/product_test.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestProductMissingNameReturnsErr(t *testing.T) { 10 | p := &Product{ 11 | Price: 1.00, 12 | } 13 | //err := p.Validate() 14 | v := NewValidation() 15 | err := v.Validate(p) 16 | assert.Len(t, err, 1) 17 | } 18 | -------------------------------------------------------------------------------- /webservice/controllers/front.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | "net/http" 7 | ) 8 | 9 | func RegisterControllers() { 10 | uc := newUserController() 11 | http.Handle("/users", *uc) 12 | http.Handle("/users/", *uc) 13 | } 14 | 15 | func encodeResponseAsJSON(data interface{}, w io.Writer) { 16 | enc := json.NewEncoder(w) 17 | enc.Encode(data) 18 | } 19 | -------------------------------------------------------------------------------- /webservice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/erankitcs/golang_learning/webservice/controllers" 7 | ) 8 | 9 | func main() { 10 | // u := models.User{ 11 | // ID: 2, 12 | // FirstName: "Ankit", 13 | // LastName: "Singh", 14 | // } 15 | // fmt.Println(u) 16 | controllers.RegisterControllers() 17 | http.ListenAndServe(":3000", nil) 18 | } 19 | -------------------------------------------------------------------------------- /gostandard_libs/bufio_demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "runtime" 8 | ) 9 | 10 | func main() { 11 | reader := bufio.NewReader(os.Stdin) 12 | fmt.Println("Wahts your name ?") 13 | text, _ := reader.ReadString('\n') 14 | fmt.Printf("Hello %v", text) 15 | fmt.Printf("We are using Go %v running in %v", runtime.Version(), runtime.GOOS) 16 | 17 | } 18 | -------------------------------------------------------------------------------- /distributedapp/teacherportal/templates.go: -------------------------------------------------------------------------------- 1 | package teacherportal 2 | 3 | import "html/template" 4 | 5 | var rootTemplate *template.Template 6 | 7 | func ImportTemplates() error { 8 | var err error 9 | rootTemplate, err = template.ParseFiles( 10 | "teacherportal/students.gohtml", 11 | "teacherportal/student.gohtml", 12 | ) 13 | if err != nil { 14 | return err 15 | } 16 | 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /distributedappdocker/teacherportal/templates.go: -------------------------------------------------------------------------------- 1 | package teacherportal 2 | 3 | import "html/template" 4 | 5 | var rootTemplate *template.Template 6 | 7 | func ImportTemplates() error { 8 | var err error 9 | rootTemplate, err = template.ParseFiles( 10 | "teacherportal/students.gohtml", 11 | "teacherportal/student.gohtml", 12 | ) 13 | if err != nil { 14 | return err 15 | } 16 | 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /microservices/product-api-gorilla/Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL := swagger 2 | 3 | install_swagger: 4 | go get -u github.com/go-swagger/go-swagger/cmd/swagger 5 | 6 | swagger: 7 | @echo Ensure you have the swagger CLI or this command will fail. 8 | @echo You can install the swagger CLI with: go get -u github.com/go-swagger/go-swagger/cmd/swagger 9 | @echo .... 10 | 11 | swagger generate spec -o ./swagger.yaml --scan-models -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "golang-fifa-world-cup-web-service/data" 5 | "golang-fifa-world-cup-web-service/handlers" 6 | "net/http" 7 | ) 8 | 9 | func main() { 10 | data.PrintUsage() 11 | 12 | http.HandleFunc("/", handlers.RootHandler) 13 | http.HandleFunc("/winners", handlers.WinnersHandler) 14 | http.ListenAndServe(":8000", nil) 15 | } 16 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL := swagger 2 | 3 | install_swagger: 4 | go get -u github.com/go-swagger/go-swagger/cmd/swagger 5 | 6 | swagger: 7 | @echo Ensure you have the swagger CLI or this command will fail. 8 | @echo You can install the swagger CLI with: go get -u github.com/go-swagger/go-swagger/cmd/swagger 9 | @echo .... 10 | 11 | swagger generate spec -o ./swagger.yaml --scan-models -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/handlers/handlers_test_helpers.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "golang-fifa-world-cup-web-service/data" 5 | "path" 6 | "path/filepath" 7 | ) 8 | 9 | // reloads JSON into memory to ensure 10 | // proper winner count during tests. 11 | func setup() { 12 | p, _ := filepath.Abs("./../data/") 13 | fullpath := path.Join(p, "winners.json") 14 | data.LoadFromJSON(fullpath) 15 | } 16 | -------------------------------------------------------------------------------- /ginframeworkdemo/responsedemo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Book list 8 | 9 | 10 | A Tale Of Two Cities
11 | Great Expectations 12 | 13 | -------------------------------------------------------------------------------- /microservices/product-api/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/nicholasjackson/env v0.6.0 h1:6xdio52m7cKRtgZPER6NFeBZxicR88rx5a+5Jl4/qus= 3 | github.com/nicholasjackson/env v0.6.0/go.mod h1:/GtSb9a/BDUCLpcnpauN0d/Bw5ekSI1vLC1b9Lw0Vyk= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 6 | -------------------------------------------------------------------------------- /gostandard_libs/flag_demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | bitsStr := flag.String("arch", "x86", "CPU Arch") 10 | flag.Parse() 11 | 12 | switch *bitsStr { 13 | case "x86": 14 | { 15 | fmt.Println("running in 32 bit mode") 16 | } 17 | case "AMD64": 18 | { 19 | fmt.Println("Running in 64 bit mode") 20 | } 21 | case "IA64": 22 | { 23 | fmt.Println("Remember IA64?") 24 | } 25 | 26 | } 27 | fmt.Println("Ran our process!") 28 | } 29 | -------------------------------------------------------------------------------- /microservices/product-api-gorilla/swagger.yaml: -------------------------------------------------------------------------------- 1 | basePath: / 2 | consumes: 3 | - application/json 4 | host: localhost 5 | info: 6 | contact: 7 | email: er.ankit.cs@gmail.com 8 | description: The purpose of this API is to provide list of products, add new product 9 | and update the existing product. 10 | license: 11 | name: MIT 12 | url: http://opensource.org/licenses/MIT 13 | title: API. 14 | version: 0.0.1 15 | paths: {} 16 | produces: 17 | - application/json 18 | schemes: 19 | - http 20 | swagger: "2.0" 21 | -------------------------------------------------------------------------------- /grpcdemo/client/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/grpcdemo/client 2 | 3 | go 1.17 4 | 5 | require ( 6 | google.golang.org/grpc v1.47.0 7 | google.golang.org/protobuf v1.28.0 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.2 // indirect 12 | golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect 13 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect 14 | golang.org/x/text v0.3.3 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /grpcdemo/server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/grpcdemo/server 2 | 3 | go 1.17 4 | 5 | require ( 6 | google.golang.org/grpc v1.47.0 7 | google.golang.org/protobuf v1.28.0 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.2 // indirect 12 | golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect 13 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect 14 | golang.org/x/text v0.3.3 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /customdatatypes/datatypes1/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/erankitcs/golang_learning/customdatatypes/datatypes1/organisation" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("Custom Type Demo 1") 11 | p := organisation.NewPerson("Ankit", "Singh") 12 | err := p.SetTwitterHandler("@ankit63") 13 | if err != nil { 14 | fmt.Printf("An error occurred while setting handler %s", err.Error()) 15 | } 16 | 17 | fmt.Println(p.FullName()) 18 | fmt.Println(p.TwitterHandler()) 19 | fmt.Println(p.ID()) 20 | 21 | } 22 | -------------------------------------------------------------------------------- /microservices/product-api-gorilla/handlers/docs.go: -------------------------------------------------------------------------------- 1 | // Package Product API. 2 | // 3 | // The purpose of this API is to provide list of products, add new product and update the existing product. 4 | // Schemes: http 5 | // Host: localhost 6 | // BasePath: / 7 | // Version: 0.0.1 8 | // License: MIT http://opensource.org/licenses/MIT 9 | // Contact: er.ankit.cs@gmail.com 10 | // Consumes: 11 | // - application/json 12 | // 13 | // Produces: 14 | // - application/json 15 | // swagger:meta 16 | package handlers 17 | -------------------------------------------------------------------------------- /ginframeworkdemo/vacationtracker/cmd/vacationtrack/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | func TestAPIEmployees(t *testing.T) { 12 | rec := httptest.NewRecorder() 13 | req := httptest.NewRequest(http.MethodGet, "/api/employees/", nil) 14 | 15 | r := gin.Default() 16 | registerRoutes(r) 17 | 18 | r.ServeHTTP(rec, req) 19 | 20 | res := rec.Result() 21 | 22 | if res.StatusCode != http.StatusOK { 23 | t.Fail() 24 | } 25 | t.Log(rec.Body.String()) 26 | } 27 | -------------------------------------------------------------------------------- /distributedapp/Readme.md: -------------------------------------------------------------------------------- 1 | ## Distributed Application in Golang ( A Teacher Portal) 2 | 3 | 1. Build and Start Registry service 4 | ``` 5 | go build cmd\registryservice 6 | .\registryservice.exe 7 | 8 | ``` 9 | 10 | 2. Build and Start Loggin service 11 | ``` 12 | go build cmd\logservice 13 | .\logservice.exe 14 | 15 | ``` 16 | 17 | 3. Build and Start Grading service 18 | ``` 19 | go build cmd\gradingservice 20 | .\gradingservice.exe 21 | 22 | ``` 23 | 24 | 4. Build and Start Teacher Portal 25 | ``` 26 | go build cmd\teacherportalservice 27 | .\teacherportalservice.exe 28 | 29 | ``` 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-advanced-branching/.gitattributes: -------------------------------------------------------------------------------- 1 | # From https://help.github.com/en/articles/configuring-git-to-handle-line-endings 2 | # Set the default behavior, in case people don't have core.autocrlf set. 3 | * text=auto 4 | 5 | # Explicitly declare text files you want to always be normalized and converted 6 | # to native line endings on checkout. 7 | *.c text 8 | *.h text 9 | 10 | # Declare files that will always have CRLF line endings on checkout. 11 | *.sln text eol=crlf 12 | 13 | # Denote all files that are truly binary and should not be modified. 14 | *.png binary 15 | *.jpg binary 16 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/handlers/post.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/erankitcs/golang_learning/microservices/product-api-withswagger/data" 7 | ) 8 | 9 | // swagger:route POST /products products createProduct 10 | // Create a new product. 11 | // responses: 12 | // 200: productsResponse 13 | // 422: errorValidation 14 | // 400: errorResponse 15 | func (p *Products) Create(rw http.ResponseWriter, r *http.Request) { 16 | prod := r.Context().Value(KeyProduct{}).(*data.Product) 17 | p.l.Printf("[DEBUG] Inserting product: %#v\n", prod) 18 | data.AddProduct(prod) 19 | } 20 | -------------------------------------------------------------------------------- /microservices/product-api-gorilla/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/microservices/product-api-gorilla 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/go-playground/locales v0.14.0 // indirect 7 | github.com/go-playground/universal-translator v0.18.0 // indirect 8 | github.com/go-playground/validator/v10 v10.11.0 // indirect 9 | github.com/gorilla/mux v1.8.0 // indirect 10 | github.com/leodido/go-urn v1.2.1 // indirect 11 | golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect 12 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect 13 | golang.org/x/text v0.3.7 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger-client/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/erankitcs/golang_learning/microservices/productapiclient/client" 7 | "github.com/erankitcs/golang_learning/microservices/productapiclient/client/products" 8 | ) 9 | 10 | func TestProductAPIClient(t *testing.T) { 11 | cfg := client.DefaultTransportConfig().WithHost("localhost:9090") 12 | c := client.NewHTTPClientWithConfig(nil, cfg) 13 | param := products.NewListProductsParams() 14 | prods, err := c.Products.ListProducts(param) 15 | if err != nil { 16 | t.Fatal(err.Error()) 17 | } 18 | t.Log(prods.Payload) 19 | } 20 | -------------------------------------------------------------------------------- /customdatatypes/datatypes2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/erankitcs/golang_learning/customdatatypes/datatypes2/organisation" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("Custom Type Demo 1") 11 | p := organisation.NewPerson("Ankit", "Singh") 12 | err := p.SetTwitterHandler("@ankit63") 13 | fmt.Printf("%T\n", organisation.TwitterHandler("test")) 14 | if err != nil { 15 | fmt.Printf("An error occurred while setting handler %s", err.Error()) 16 | } 17 | 18 | fmt.Println(p.TwitterHandler()) 19 | fmt.Println(p.TwitterHandler().RedirectURL()) 20 | fmt.Println(p.FullName()) 21 | fmt.Println(p.ID()) 22 | 23 | } 24 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/Makefile: -------------------------------------------------------------------------------- 1 | GOCMD=go 2 | GOTEST=$(GOCMD) test 3 | GORUN=${GOCMD} run 4 | 5 | all: test 6 | 7 | start: 8 | ${GORUN} server.go 9 | test: 10 | $(GOTEST) -v ./handlers/* 11 | test-1: 12 | $(GOTEST) -v ./handlers/handlers.go \ 13 | ./handlers/handlers_test_helpers.go \ 14 | ./handlers/01_get_handler_test.go 15 | 16 | test-2: 17 | $(GOTEST) -v ./handlers/handlers.go \ 18 | ./handlers/handlers_test_helpers.go \ 19 | ./handlers/02_post_handler_test.go 20 | 21 | test-3: 22 | $(GOTEST) -v ./handlers/handlers.go \ 23 | ./handlers/handlers_test_helpers.go \ 24 | ./handlers/03_dispatch_handler_test.go -------------------------------------------------------------------------------- /distributedapp/registry/registration.go: -------------------------------------------------------------------------------- 1 | package registry 2 | 3 | type Registration struct { 4 | ServiceName ServiceName 5 | ServiceURL string 6 | RequiredServices []ServiceName 7 | ServiceUpdateURL string 8 | HeartbeatURL string 9 | } 10 | 11 | type ServiceName string 12 | 13 | const ( 14 | LogService = ServiceName("LogService") 15 | GradingService = ServiceName("GradingService") 16 | TeacherPortalService = ServiceName("TeacherPortalService") 17 | ) 18 | 19 | type patchEntry struct { 20 | Name ServiceName 21 | URL string 22 | } 23 | 24 | type patch struct { 25 | Added []patchEntry 26 | Removed []patchEntry 27 | } 28 | -------------------------------------------------------------------------------- /distributedappdocker/Dockerfile.logservice: -------------------------------------------------------------------------------- 1 | FROM golang:1.17-alpine as build 2 | 3 | # Set necessary environmet variables needed for our image 4 | ENV GO111MODULE=on \ 5 | CGO_ENABLED=0 \ 6 | GOOS=linux \ 7 | GOARCH=amd64 8 | 9 | # Move to working directory /build 10 | WORKDIR /build 11 | 12 | ADD . /build/ 13 | 14 | RUN go mod tidy 15 | # Move to registry service directory 16 | WORKDIR /build/cmd/logservice 17 | 18 | RUN mkdir -p /dist 19 | 20 | RUN go build -o /dist . 21 | 22 | ## 23 | ## Deploy 24 | ## 25 | 26 | FROM alpine:latest 27 | 28 | WORKDIR /app 29 | 30 | COPY --from=build /dist . 31 | 32 | EXPOSE 4000 33 | 34 | CMD [ "./logservice" ] -------------------------------------------------------------------------------- /distributedappdocker/registry/registration.go: -------------------------------------------------------------------------------- 1 | package registry 2 | 3 | type Registration struct { 4 | ServiceName ServiceName 5 | ServiceURL string 6 | RequiredServices []ServiceName 7 | ServiceUpdateURL string 8 | HeartbeatURL string 9 | } 10 | 11 | type ServiceName string 12 | 13 | const ( 14 | LogService = ServiceName("LogService") 15 | GradingService = ServiceName("GradingService") 16 | TeacherPortalService = ServiceName("TeacherPortalService") 17 | ) 18 | 19 | type patchEntry struct { 20 | Name ServiceName 21 | URL string 22 | } 23 | 24 | type patch struct { 25 | Added []patchEntry 26 | Removed []patchEntry 27 | } 28 | -------------------------------------------------------------------------------- /distributedappdocker/Dockerfile.gradingservice: -------------------------------------------------------------------------------- 1 | FROM golang:1.17-alpine as build 2 | 3 | # Set necessary environmet variables needed for our image 4 | ENV GO111MODULE=on \ 5 | CGO_ENABLED=0 \ 6 | GOOS=linux \ 7 | GOARCH=amd64 8 | 9 | # Move to working directory /build 10 | WORKDIR /build 11 | 12 | ADD . /build/ 13 | 14 | RUN go mod tidy 15 | # Move to registry service directory 16 | WORKDIR /build/cmd/gradingservice 17 | 18 | RUN mkdir -p /dist 19 | 20 | RUN go build -o /dist . 21 | 22 | ## 23 | ## Deploy 24 | ## 25 | 26 | FROM alpine:latest 27 | 28 | WORKDIR /app 29 | 30 | COPY --from=build /dist . 31 | 32 | EXPOSE 4000 33 | 34 | CMD [ "./gradingservice" ] -------------------------------------------------------------------------------- /distributedappdocker/Dockerfile.registryservice: -------------------------------------------------------------------------------- 1 | FROM golang:1.17-alpine as build 2 | 3 | # Set necessary environmet variables needed for our image 4 | ENV GO111MODULE=on \ 5 | CGO_ENABLED=0 \ 6 | GOOS=linux \ 7 | GOARCH=amd64 8 | 9 | # Move to working directory /build 10 | WORKDIR /build 11 | 12 | ADD . /build/ 13 | 14 | RUN go mod tidy 15 | # Move to registry service directory 16 | WORKDIR /build/cmd/registryservice 17 | 18 | RUN mkdir -p /dist 19 | 20 | RUN go build -o /dist . 21 | 22 | ## 23 | ## Deploy 24 | ## 25 | 26 | FROM alpine:latest 27 | 28 | WORKDIR /app 29 | 30 | COPY --from=build /dist . 31 | 32 | EXPOSE 3000 33 | 34 | CMD [ "./registryservice" ] -------------------------------------------------------------------------------- /gostandard_libs/time_demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | 10 | t := time.Now() 11 | year := t.Year() 12 | month := t.Month() 13 | day := t.Day() 14 | 15 | fmt.Printf("Today is %d/%d/%d", month, day, year) 16 | 17 | time.Sleep(1 * time.Second) 18 | elapsed := time.Since(t) 19 | fmt.Printf("\nElasped time is %s \n", elapsed) 20 | 21 | // Reference time: 22 | // Mon Jan 2 15:04:05 MST 2006 23 | fmt.Printf("Current Time %v \n", t.Format("15:04:05")) 24 | fmt.Printf("Current Date %v \n", t.Format("Monday 02, Jan-2006")) 25 | fmt.Printf("Today is %v \n", t.Format("Monday 02, Jan-2006 at 15:04:05")) 26 | } 27 | -------------------------------------------------------------------------------- /gostandard_libs/others_demo/primitives.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func main() { 9 | var amount int32 10 | 11 | amount = 32 12 | typename := reflect.TypeOf(amount).Name() 13 | fmt.Printf("The name of the type is %v \n", typename) 14 | fmt.Printf("The type is %v\n", reflect.TypeOf(amount)) 15 | fmt.Printf("The kind is %v\n", reflect.TypeOf(amount).Kind()) 16 | fmt.Printf("The value is %v\n", reflect.ValueOf(amount)) 17 | 18 | newValue := GetReflectedValue(reflect.TypeOf(amount)) 19 | fmt.Print(newValue) 20 | //test := reflect.New(newValue) 21 | } 22 | 23 | func GetReflectedValue(t reflect.Type) reflect.Value { 24 | return reflect.Zero(t) 25 | } 26 | -------------------------------------------------------------------------------- /grpcdemo/server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.17-alpine as build 2 | 3 | # Set necessary environmet variables needed for our image 4 | ENV GO111MODULE=on \ 5 | CGO_ENABLED=0 \ 6 | GOOS=linux \ 7 | GOARCH=amd64 8 | 9 | # Move to working directory /build 10 | 11 | ADD . /build/ 12 | WORKDIR /build 13 | ADD server /build/ 14 | 15 | WORKDIR /build/server 16 | RUN go mod tidy 17 | 18 | RUN mkdir -p /dist 19 | 20 | RUN go build -o /dist . 21 | 22 | ## 23 | ## Deploy 24 | ## 25 | 26 | FROM alpine:latest 27 | ENV tls="" 28 | WORKDIR /cert 29 | ADD cert . 30 | WORKDIR /app 31 | COPY --from=build /dist . 32 | 33 | EXPOSE 9000 34 | RUN echo "Running GRPC Server with mTLS as $mtls" 35 | CMD ./server -"$tls" -------------------------------------------------------------------------------- /pluralsight_projects/golang-personal-budget-cli/README.md: -------------------------------------------------------------------------------- 1 | ## Golang Personal Budget CLI 2 | 3 | Demo app for the Golang Personal Budget CLI Project. 4 | 5 | ## Running tests 6 | 7 | A proper Go environment is required in order to run this project. 8 | Once setup, tests can be run with the following command: 9 | 10 | `go test -v ./module1/ ./module2/` 11 | 12 | ### Running with Docker 13 | 14 | To build the image from the Dockerfile, run: 15 | 16 | `docker build -t project-budget-app .` 17 | 18 | To start an interactive shell, run: 19 | 20 | `docker run -it --rm --name run-budget project-budget-app` 21 | 22 | From inside the shell, run the tests with: 23 | 24 | `go test -v ./module1/ ./module2/` 25 | 26 | -------------------------------------------------------------------------------- /distributedappdocker/Dockerfile.teacherportalservice: -------------------------------------------------------------------------------- 1 | FROM golang:1.17-alpine as build 2 | 3 | # Set necessary environmet variables needed for our image 4 | ENV GO111MODULE=on \ 5 | CGO_ENABLED=0 \ 6 | GOOS=linux \ 7 | GOARCH=amd64 8 | 9 | # Move to working directory /build 10 | WORKDIR /build 11 | 12 | ADD . /build/ 13 | 14 | RUN go mod tidy 15 | # Move to service directory 16 | WORKDIR /build/cmd/teacherportalservice 17 | 18 | RUN mkdir -p /dist 19 | 20 | RUN go build -o /dist . 21 | 22 | ## 23 | ## Deploy 24 | ## 25 | 26 | FROM alpine:latest 27 | 28 | WORKDIR /app 29 | 30 | COPY --from=build /dist . 31 | 32 | COPY teacherportal/*.gohtml teacherportal/ 33 | 34 | EXPOSE 5000 35 | 36 | CMD [ "./teacherportalservice" ] -------------------------------------------------------------------------------- /functions/simplemaths/expressions.go: -------------------------------------------------------------------------------- 1 | package simplemaths 2 | 3 | import "errors" 4 | 5 | // Variadic function...slice of type as inputs. It can be only last parameter. 6 | func Sum(values ...float64) float64 { 7 | total := 0.0 8 | for _, value := range values { 9 | total += value 10 | } 11 | return total 12 | } 13 | 14 | func Add(p1, p2 float64) float64 { 15 | return p1 + p2 16 | } 17 | 18 | func Subtract(p1, p2 float64) float64 { 19 | return p1 - p2 20 | } 21 | 22 | func Multiply(p1, p2 float64) float64 { 23 | return p1 * p2 24 | } 25 | 26 | // Naming return value. 27 | func Devide(p1, p2 float64) (answer float64, err error) { 28 | if p2 == 0 { 29 | err = errors.New("cant devide by 0") 30 | } 31 | answer = p1 / p2 32 | return 33 | } 34 | -------------------------------------------------------------------------------- /gostandard_libs/custom_type/createtype.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | type employee struct { 9 | empId int 10 | firstName string 11 | lastName string 12 | } 13 | 14 | func main() { 15 | emps := make([]employee, 3) 16 | emps = append(emps, employee{1, "Ankit", "Singh"}) 17 | emps = append(emps, employee{2, "Nikhil", "Karkara"}) 18 | emps = append(emps, employee{3, "Anuj", "Agr"}) 19 | 20 | eType := reflect.TypeOf(emps) 21 | fmt.Printf("Emp Type %s \n", eType) 22 | newEmpList := reflect.MakeSlice(eType, 0, 0) 23 | newEmpList = reflect.Append(newEmpList, reflect.ValueOf(employee{4, "NewEmp", "here"})) 24 | fmt.Printf("First List %v \n", emps) 25 | fmt.Printf("New List %v \n", newEmpList) 26 | 27 | } 28 | -------------------------------------------------------------------------------- /microservices/product-api-gorilla/README.md: -------------------------------------------------------------------------------- 1 | ### Product API Gorilla Toolkit 2 | 3 | ### Usage 4 | 5 | 1. Get Products API- 6 | ``` 7 | http://localhost:9090/ 8 | ``` 9 | 2. Add a Product 10 | ``` 11 | http://localhost:9090/ 12 | Body- 13 | {"id":3,"name":"tea","description":"A Tea","price":111.21,"sku":"ssdff-sfff-sfff"} 14 | ``` 15 | 3. Update a Product 16 | ``` 17 | http://localhost:9090/3 18 | Body- 19 | {"id":3,"name":"tea","description":"A Tea of new type","price":122.21,"sku":"ssdff-sfff-sfff"} 20 | ``` 21 | 22 | ### Swagger Documentation 23 | - With Docker on Windows. 24 | ``` 25 | docker pull quay.io/goswagger/swagger 26 | ./swagger.bat 27 | ``` 28 | - Without Docker on Windows. 29 | ``` 30 | ./make.bat 31 | ``` 32 | - Without Docker on Linux/Mac. 33 | ``` 34 | ./make.bat 35 | ``` -------------------------------------------------------------------------------- /microservices/product-api-withswagger/README.md: -------------------------------------------------------------------------------- 1 | ### Product API Gorilla Toolkit 2 | 3 | ### Usage 4 | 5 | 1. Get Products API- 6 | ``` 7 | http://localhost:9090/ 8 | ``` 9 | 2. Add a Product 10 | ``` 11 | http://localhost:9090/ 12 | Body- 13 | {"id":3,"name":"tea","description":"A Tea","price":111.21,"sku":"ssdff-sfff-sfff"} 14 | ``` 15 | 3. Update a Product 16 | ``` 17 | http://localhost:9090/3 18 | Body- 19 | {"id":3,"name":"tea","description":"A Tea of new type","price":122.21,"sku":"ssdff-sfff-sfff"} 20 | ``` 21 | 22 | ### Swagger Documentation 23 | - With Docker on Windows. 24 | ``` 25 | docker pull quay.io/goswagger/swagger 26 | ./swagger.bat 27 | ``` 28 | - Without Docker on Windows. 29 | ``` 30 | ./make.bat 31 | ``` 32 | - Without Docker on Linux/Mac. 33 | ``` 34 | ./make.bat 35 | ``` -------------------------------------------------------------------------------- /pingpong/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func pinger(ping <-chan string, pong chan<- string) { 9 | for m := range ping { 10 | printAndDelay(m) 11 | pong <- "PlayerA- pong" 12 | } 13 | } 14 | 15 | func ponger(pong <-chan string, ping chan<- string) { 16 | for m := range pong { 17 | printAndDelay(m) 18 | ping <- "PlayerB- ping" 19 | } 20 | } 21 | 22 | func printAndDelay(msg string) { 23 | fmt.Println(msg) 24 | time.Sleep(time.Second) 25 | } 26 | 27 | func main() { 28 | fmt.Println("Starting pingpong game.") 29 | ping := make(chan string) 30 | pong := make(chan string) 31 | 32 | // Creating two player 33 | go pinger(ping, pong) 34 | go ponger(pong, ping) 35 | 36 | // starting the game. 37 | ping <- "ping" 38 | 39 | for { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /customdatatypes/datatypes3/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/erankitcs/golang_learning/customdatatypes/datatypes3/organisation" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("Custom Type Demo 3") 11 | p := organisation.NewPerson("Ankit", "Singh", organisation.NewEuropeanUnionIdentifier("123-45-33", "UK")) 12 | err := p.SetTwitterHandler("@ankit63") 13 | fmt.Printf("%T\n", organisation.TwitterHandler("test")) 14 | if err != nil { 15 | fmt.Printf("An error occurred while setting handler %s", err.Error()) 16 | } 17 | p.First = "NewName" 18 | println(p.First) 19 | println(p.Name.First) 20 | fmt.Println(p.TwitterHandler()) 21 | fmt.Println(p.TwitterHandler().RedirectURL()) 22 | fmt.Println(p.FullName()) 23 | fmt.Println(p.ID()) 24 | println(p.Country()) 25 | 26 | } 27 | -------------------------------------------------------------------------------- /distributedapp/cmd/registryservice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | 9 | "github.com/erankitcs/golang_learning/distributedapp/registry" 10 | ) 11 | 12 | func main() { 13 | registry.SetupRegistryService() 14 | http.Handle("/services", ®istry.RegistryService{}) 15 | ctx, cancle := context.WithCancel(context.Background()) 16 | defer cancle() 17 | var srv http.Server 18 | srv.Addr = registry.ServerPort 19 | 20 | go func() { 21 | log.Println(srv.ListenAndServe()) 22 | cancle() 23 | }() 24 | 25 | go func() { 26 | fmt.Println("Registry Service Started. Press any key to stop.") 27 | var s string 28 | fmt.Scanln(&s) 29 | srv.Shutdown(ctx) 30 | cancle() 31 | }() 32 | <-ctx.Done() 33 | fmt.Println("Shutting down registry service.") 34 | 35 | } 36 | -------------------------------------------------------------------------------- /grpcdemo/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.17-alpine as build 2 | 3 | # Set necessary environmet variables needed for our image 4 | ENV GO111MODULE=on \ 5 | CGO_ENABLED=0 \ 6 | GOOS=linux \ 7 | GOARCH=amd64 8 | 9 | # Move to working directory /build 10 | 11 | ADD . /build/ 12 | WORKDIR /build 13 | ADD client /build/ 14 | 15 | WORKDIR /build/client 16 | RUN go mod tidy 17 | 18 | RUN mkdir -p /dist 19 | 20 | RUN go build -o /dist . 21 | 22 | ## 23 | ## Deploy 24 | ## 25 | 26 | FROM alpine:latest 27 | ENV tls=tls 28 | ENV opt=1 29 | ENV serverhost="" 30 | ENV serverport=9000 31 | 32 | WORKDIR /cert 33 | ADD cert . 34 | WORKDIR /app 35 | COPY --from=build /dist . 36 | RUN echo "Running GRPC client with option $opt , tls as $tls and mTLS as $mtls" 37 | CMD ./client -o $opt -$tls -serverhost $serverhost -serverport $serverport -------------------------------------------------------------------------------- /grpcdemo/server/data.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/erankitcs/golang_learning/grpcdemo/server/pb/messages" 5 | ) 6 | 7 | var employees = []messages.Employee{ 8 | { 9 | Id: 1, 10 | BadgeNumber: 2080, 11 | FirstName: "Grace", 12 | LastName: "Decker", 13 | VacationAccrualRate: 2, 14 | VacationAccrued: 30, 15 | }, 16 | { 17 | Id: 2, 18 | BadgeNumber: 7538, 19 | FirstName: "Amity", 20 | LastName: "Fuller", 21 | VacationAccrualRate: 2.3, 22 | VacationAccrued: 23.4, 23 | }, 24 | { 25 | Id: 3, 26 | BadgeNumber: 5144, 27 | FirstName: "Keaton", 28 | LastName: "Willis", 29 | VacationAccrualRate: 3, 30 | VacationAccrued: 31.7, 31 | }, 32 | } 33 | -------------------------------------------------------------------------------- /gostandard_libs/trace_demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "math/rand" 7 | "os" 8 | "runtime/trace" 9 | "time" 10 | ) 11 | 12 | func main() { 13 | f, err := os.Create("trace.out") 14 | if err != nil { 15 | log.Fatalf("failed to create trace output file: %v", err) 16 | } 17 | defer func() { 18 | if err := f.Close(); err != nil { 19 | log.Fatalf("failed to close trace file: %v", err) 20 | } 21 | }() 22 | 23 | if err := trace.Start(f); err != nil { 24 | log.Fatalf("failed to start trace: %v", err) 25 | } 26 | defer trace.Stop() 27 | 28 | AddRandomNumbers() 29 | } 30 | 31 | func AddRandomNumbers() { 32 | 33 | firstNumber := rand.Intn(100) 34 | secondNumber := rand.Intn(100) 35 | 36 | time.Sleep(2 * time.Second) 37 | 38 | var result = firstNumber * secondNumber 39 | 40 | fmt.Printf("Result of 2 numbers is %d\n", result) 41 | } 42 | -------------------------------------------------------------------------------- /golang-async-logging-library/README.md: -------------------------------------------------------------------------------- 1 | To use the test runner: 2 | 3 | * navigate into the ./cmd directory 4 | * if run with the defaults (`go run .`), the application will run in asynchronous mode and write it's output directly to the shell 5 | * the `-out` flag allows a destination file to be specified 6 | * the `-async` flag determines if the logger will asynchronously or not. It is async by default, which will not work properly in the application's initial condition. 7 | 8 | To run the tests 9 | 10 | * use the `go test` command from the command line 11 | * to focus on a specific test, use the `-run` flag followed by a pattern that matches the test name 12 | * e.g. `go test -run MessageChannel` will run the first test of the first module 13 | * all tests for a given module can be run by passing the module identifier to the `-run` command 14 | * e.g. `go test -v -run Module1` 15 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/handlers/put.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/erankitcs/golang_learning/microservices/product-api-withswagger/data" 7 | ) 8 | 9 | // swagger:route PUT /products products updateProduct 10 | // Update a products details 11 | // 12 | // responses: 13 | // 201: noContentResponse 14 | // 404: errorResponse 15 | // 422: errorValidation 16 | func (p *Products) Update(rw http.ResponseWriter, r *http.Request) { 17 | prod := r.Context().Value(KeyProduct{}).(*data.Product) 18 | p.l.Printf("[DEBUG] Updating product for id: %#v\n", prod.ID) 19 | err := data.UpdateProduct(prod) 20 | if err == data.ErrorProductNotFound { 21 | p.l.Println("[ERROR] product not found", err) 22 | 23 | rw.WriteHeader(http.StatusNotFound) 24 | data.ToJSON(&GenericError{Message: "Product not found in database"}, rw) 25 | return 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /distributedapp/log/client.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | stlog "log" 7 | "net/http" 8 | 9 | "github.com/erankitcs/golang_learning/distributedapp/registry" 10 | ) 11 | 12 | func SetClientLogger(serviceURL string, clientService registry.ServiceName) { 13 | stlog.SetPrefix(fmt.Sprintf("[%v] - ", clientService)) 14 | stlog.SetFlags(0) 15 | stlog.SetOutput(&clientLogger{url: serviceURL}) 16 | } 17 | 18 | type clientLogger struct { 19 | url string 20 | } 21 | 22 | func (cl clientLogger) Write(data []byte) (int, error) { 23 | b := bytes.NewBuffer([]byte(data)) 24 | res, err := http.Post(cl.url+"/log", "text/plan", b) 25 | if err != nil { 26 | return 0, err 27 | } 28 | if res.StatusCode != http.StatusOK { 29 | return 0, fmt.Errorf("Failed to send the log message."+ 30 | "Service responded with code: %v", res.StatusCode) 31 | } 32 | return len(data), nil 33 | } 34 | -------------------------------------------------------------------------------- /distributedappdocker/log/client.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | stlog "log" 7 | "net/http" 8 | 9 | "github.com/erankitcs/golang_learning/distributedapp/registry" 10 | ) 11 | 12 | func SetClientLogger(serviceURL string, clientService registry.ServiceName) { 13 | stlog.SetPrefix(fmt.Sprintf("[%v] - ", clientService)) 14 | stlog.SetFlags(0) 15 | stlog.SetOutput(&clientLogger{url: serviceURL}) 16 | } 17 | 18 | type clientLogger struct { 19 | url string 20 | } 21 | 22 | func (cl clientLogger) Write(data []byte) (int, error) { 23 | b := bytes.NewBuffer([]byte(data)) 24 | res, err := http.Post(cl.url+"/log", "text/plan", b) 25 | if err != nil { 26 | return 0, err 27 | } 28 | if res.StatusCode != http.StatusOK { 29 | return 0, fmt.Errorf("Failed to send the log message."+ 30 | "Service responded with code: %v", res.StatusCode) 31 | } 32 | return len(data), nil 33 | } 34 | -------------------------------------------------------------------------------- /distributedappdocker/cmd/registryservice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | 9 | "github.com/erankitcs/golang_learning/distributedapp/registry" 10 | ) 11 | 12 | func main() { 13 | registry.SetupRegistryService() 14 | http.Handle("/services", ®istry.RegistryService{}) 15 | ctx, cancle := context.WithCancel(context.Background()) 16 | defer cancle() 17 | var srv http.Server 18 | srv.Addr = registry.ServerPort 19 | 20 | go func() { 21 | log.Println(srv.ListenAndServe()) 22 | cancle() 23 | }() 24 | 25 | go func() { 26 | fmt.Println("Registry Service Started. Press key- s key to stop.") 27 | var s string 28 | fmt.Scanln(&s) 29 | if s == "s" { 30 | fmt.Println("Stop requested by user") 31 | srv.Shutdown(ctx) 32 | cancle() 33 | 34 | } 35 | }() 36 | <-ctx.Done() 37 | fmt.Println("Shutting down registry service.") 38 | 39 | } 40 | -------------------------------------------------------------------------------- /distributedapp/teacherportal/students.gohtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Students 7 | 8 | 9 |

Grade Book

10 | {{if len .}} 11 | 12 | 13 | 14 | 15 | 16 | {{range .}} 17 | 18 | 21 | 24 | 25 | {{end}} 26 |
NameAverage [%]
19 | {{.LastName}}, {{.FirstName}} 20 | 22 | {{printf "%.1f%%" .Average}} 23 |
27 | {{else}} 28 | No students found 29 | {{end}} 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /distributedappdocker/teacherportal/students.gohtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Students 7 | 8 | 9 |

Grade Book

10 | {{if len .}} 11 | 12 | 13 | 14 | 15 | 16 | {{range .}} 17 | 18 | 21 | 24 | 25 | {{end}} 26 |
NameAverage [%]
19 | {{.LastName}}, {{.FirstName}} 20 | 22 | {{printf "%.1f%%" .Average}} 23 |
27 | {{else}} 28 | No students found 29 | {{end}} 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ginframeworkdemo/vacationtracker/templates/index.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Employee Vacation Tracker 8 | 9 | 10 | 11 |

Employee Vacation Tracker

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {{ range . }} 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {{ end }} 29 |
IDLast NameFirst NameTotal PTOPTO Events
{{.ID}}{{.LastName}}{{.FirstName}}{{.TotalPTO}}{{.TimeOff | len}}
30 | 31 | -------------------------------------------------------------------------------- /gostandard_libs/loger_demo/newloger.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | ) 7 | 8 | var ( 9 | WarningLogger *log.Logger 10 | InfoLogger *log.Logger 11 | ErrorLogger *log.Logger 12 | FatalLogger *log.Logger 13 | ) 14 | 15 | func init() { 16 | 17 | file, err := os.OpenFile("newlog.txt", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666) 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | 22 | InfoLogger = log.New(file, "INFO: ", log.LUTC|log.Lmicroseconds|log.Llongfile) 23 | WarningLogger = log.New(file, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile) 24 | ErrorLogger = log.New(file, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile) 25 | FatalLogger = log.New(file, "FATAL: ", log.Ldate|log.Ltime|log.Lshortfile) 26 | } 27 | 28 | func main() { 29 | 30 | InfoLogger.Println("This is info") 31 | WarningLogger.Println("This is warning.") 32 | ErrorLogger.Println("This is error") 33 | FatalLogger.Println("This is fetal error.") 34 | } 35 | -------------------------------------------------------------------------------- /distributedapp/log/server.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "io/ioutil" 5 | stlog "log" 6 | "net/http" 7 | "os" 8 | ) 9 | 10 | var log *stlog.Logger 11 | 12 | type fileLog string 13 | 14 | func (fl fileLog) Write(data []byte) (int, error) { 15 | f, err := os.OpenFile(string(fl), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) 16 | if err != nil { 17 | return 0, err 18 | } 19 | defer f.Close() 20 | return f.Write(data) 21 | //fmt.Println(string(data)) 22 | //return 1, nil 23 | } 24 | 25 | func Run(destination string) { 26 | log = stlog.New(fileLog(destination), "", stlog.LstdFlags) 27 | } 28 | 29 | func RegisterHandler() { 30 | http.HandleFunc("/log", func(rw http.ResponseWriter, r *http.Request) { 31 | msg, err := ioutil.ReadAll(r.Body) 32 | if err != nil && len(msg) == 0 { 33 | rw.WriteHeader(http.StatusBadRequest) 34 | return 35 | } 36 | write(string(msg)) 37 | }) 38 | } 39 | 40 | func write(msg string) { 41 | log.Printf("%v\n", msg) 42 | } 43 | -------------------------------------------------------------------------------- /distributedappdocker/log/server.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "io/ioutil" 5 | stlog "log" 6 | "net/http" 7 | "os" 8 | ) 9 | 10 | var log *stlog.Logger 11 | 12 | type fileLog string 13 | 14 | func (fl fileLog) Write(data []byte) (int, error) { 15 | f, err := os.OpenFile(string(fl), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) 16 | if err != nil { 17 | return 0, err 18 | } 19 | defer f.Close() 20 | return f.Write(data) 21 | //fmt.Println(string(data)) 22 | //return 1, nil 23 | } 24 | 25 | func Run(destination string) { 26 | log = stlog.New(fileLog(destination), "", stlog.LstdFlags) 27 | } 28 | 29 | func RegisterHandler() { 30 | http.HandleFunc("/log", func(rw http.ResponseWriter, r *http.Request) { 31 | msg, err := ioutil.ReadAll(r.Body) 32 | if err != nil && len(msg) == 0 { 33 | rw.WriteHeader(http.StatusBadRequest) 34 | return 35 | } 36 | write(string(msg)) 37 | }) 38 | } 39 | 40 | func write(msg string) { 41 | log.Printf("%v\n", msg) 42 | } 43 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-advanced-branching/feedback.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "values": [ 4 | { 5 | "model":"Sonata" , 6 | "feedback": [ 7 | "This is the most pathetic support I have ever received. My product is still to be shipped and I am totally frustrated with the response time.", 8 | "This is to say thanks to the service advisor", 9 | "What a wonderful service fantastic department you have. The advisor provided the best support that I have ever received. I am very impressed and it will be a pleasure to order again from your company." 10 | ] 11 | }, 12 | { 13 | "model":"CRV" , 14 | "feedback": [ 15 | "This is a generic feedback about the CRV." 16 | ] 17 | }, 18 | { 19 | "model":"Camry" , 20 | "feedback": [ 21 | "I guess your employees do know how to provide support. I am happy and satisfied with the level of response that I got.", 22 | "The support was fine and my service issues were resolved on timely basis." 23 | ] 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /distributedapp/cmd/logservice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | stlog "log" 7 | 8 | "github.com/erankitcs/golang_learning/distributedapp/log" 9 | "github.com/erankitcs/golang_learning/distributedapp/registry" 10 | "github.com/erankitcs/golang_learning/distributedapp/service" 11 | ) 12 | 13 | func main() { 14 | log.Run("./app.log") 15 | var r registry.Registration 16 | hostname, port := "localhost", "4000" 17 | serviceURL := fmt.Sprintf("http://%v:%v", hostname, port) 18 | r.ServiceName = registry.LogService 19 | r.ServiceURL = serviceURL 20 | r.RequiredServices = make([]registry.ServiceName, 0) 21 | r.ServiceUpdateURL = r.ServiceURL + "/services" 22 | r.HeartbeatURL = r.ServiceURL + "/heartbeat" 23 | 24 | ctx, err := service.Start( 25 | context.Background(), 26 | r, 27 | hostname, 28 | port, 29 | log.RegisterHandler, 30 | ) 31 | 32 | if err != nil { 33 | stlog.Fatal(err) 34 | } 35 | <-ctx.Done() 36 | fmt.Println("Shutting down log service.") 37 | } 38 | -------------------------------------------------------------------------------- /gostandard_libs/args_demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strconv" 7 | ) 8 | 9 | func main() { 10 | // Slicing to include first read which is nothing but file name 11 | // Args are list of string be default. 12 | args := os.Args[1:] 13 | //fmt.Println(args) 14 | if len(args) == 1 && args[0] == "/help" { 15 | fmt.Println("Usage: Dinner Total ") 16 | fmt.Println("args_demo 10 5") 17 | } else { 18 | if len(args) != 2 { 19 | fmt.Println("Please enter some inputs. Type /help for more details abt input.") 20 | } else { 21 | // Business Logic here. 22 | mealTotal, _ := strconv.ParseFloat(args[0], 32) 23 | tipAmount, _ := strconv.ParseFloat(args[1], 32) 24 | fmt.Printf("Your total bill is %.2f", calculateTotal(float32(mealTotal), float32(tipAmount))) 25 | } 26 | } 27 | } 28 | 29 | func calculateTotal(mealTotal float32, tipAmount float32) float32 { 30 | totalPrice := mealTotal + (mealTotal * (tipAmount / 100)) 31 | return totalPrice 32 | } 33 | -------------------------------------------------------------------------------- /customdatatypes/datatypes1/organisation/person.go: -------------------------------------------------------------------------------- 1 | package organisation 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | type Identifiable interface { 10 | ID() string 11 | } 12 | 13 | type Person struct { 14 | firstName string 15 | lastName string 16 | twitterHandler string 17 | } 18 | 19 | func NewPerson(firstName, lastName string) Person { 20 | return Person{ 21 | firstName: firstName, 22 | lastName: lastName, 23 | } 24 | } 25 | 26 | func (p *Person) SetTwitterHandler(handler string) error { 27 | if len(handler) == 0 { 28 | p.twitterHandler = handler 29 | } else if !strings.HasPrefix(handler, "@") { 30 | return errors.New("twitter handle must start with @ in text") 31 | } 32 | p.twitterHandler = handler 33 | return nil 34 | } 35 | 36 | func (p *Person) FullName() string { 37 | return fmt.Sprintf("%s %s", p.firstName, p.lastName) 38 | } 39 | 40 | func (p *Person) ID() string { 41 | return "123" 42 | } 43 | 44 | func (p *Person) TwitterHandler() string { 45 | return p.twitterHandler 46 | } 47 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/README.md: -------------------------------------------------------------------------------- 1 | # FIFA World Cup Winners 2 | 3 | This project exposes a Web API for accessing historic data from 4 | the FIFA World Cup championship. 5 | 6 | ## Running tests 7 | 8 | A proper Go environment is required in order to run this project. 9 | Once setup, tests can be run with the following command: 10 | 11 | `go test -v ./handlers/` 12 | 13 | ## Running the server 14 | 15 | Once all tests are passing, the server can be started with 16 | the `go run server.go` command. 17 | 18 | ## Testing the API manually 19 | 20 | Start the server with `go run server.go` and then 21 | use the example commands printed to the console to 22 | test the program. 23 | 24 | ### Running with Docker 25 | 26 | To build the image from the Dockerfile, run: 27 | 28 | `docker build -t project-fifa-world-cup .` 29 | 30 | To start an interactive shell, run: 31 | 32 | `docker run -it --rm --name run-fifa project-fifa-world-cup` 33 | 34 | From inside the shell, run the tests with: 35 | 36 | `go test handlers/*` 37 | -------------------------------------------------------------------------------- /distributedapp/grades/grades.go: -------------------------------------------------------------------------------- 1 | package grades 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | type Student struct { 9 | ID int 10 | FirstName string 11 | LastName string 12 | Grades []Grade 13 | } 14 | 15 | func (s Student) Average() float32 { 16 | var gradeSum float32 17 | for _, grade := range s.Grades { 18 | gradeSum += grade.Score 19 | } 20 | return gradeSum / float32(len(s.Grades)) 21 | 22 | } 23 | 24 | type Students []Student 25 | 26 | func (s Students) GetByID(id int) (*Student, error) { 27 | for i := range s { 28 | if s[i].ID == id { 29 | return &s[i], nil 30 | } 31 | } 32 | return nil, fmt.Errorf("Student with ID: %v not found", id) 33 | 34 | } 35 | 36 | var ( 37 | students Students 38 | studentsMutex sync.Mutex 39 | ) 40 | 41 | type GradeType string 42 | 43 | const ( 44 | GradeTest = GradeType("Test") 45 | GradeHomework = GradeType("Homework") 46 | GradeQuiz = GradeType("Quiz") 47 | ) 48 | 49 | type Grade struct { 50 | Title string 51 | Type GradeType 52 | Score float32 53 | } 54 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/handlers/delete.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/erankitcs/golang_learning/microservices/product-api-withswagger/data" 7 | ) 8 | 9 | // swagger:route DELETE /products/{id} products deleteProduct 10 | // Delete a product from database 11 | // responses: 12 | // 201: noContentResponse 13 | func (p *Products) Delete(rw http.ResponseWriter, r *http.Request) { 14 | id := getProductID(r) 15 | p.l.Println("[DEBUG] deleting record id", id) 16 | err := data.DeleteProduct(id) 17 | 18 | if err == data.ErrorProductNotFound { 19 | p.l.Println("[ERROR] deleting record id does not exist") 20 | 21 | rw.WriteHeader(http.StatusNotFound) 22 | data.ToJSON(&GenericError{Message: err.Error()}, rw) 23 | return 24 | } 25 | 26 | if err != nil { 27 | p.l.Println("[ERROR] deleting record", err) 28 | 29 | rw.WriteHeader(http.StatusInternalServerError) 30 | data.ToJSON(&GenericError{Message: err.Error()}, rw) 31 | return 32 | } 33 | rw.WriteHeader(http.StatusNoContent) 34 | } 35 | -------------------------------------------------------------------------------- /distributedappdocker/grades/grades.go: -------------------------------------------------------------------------------- 1 | package grades 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | type Student struct { 9 | ID int 10 | FirstName string 11 | LastName string 12 | Grades []Grade 13 | } 14 | 15 | func (s Student) Average() float32 { 16 | var gradeSum float32 17 | for _, grade := range s.Grades { 18 | gradeSum += grade.Score 19 | } 20 | return gradeSum / float32(len(s.Grades)) 21 | 22 | } 23 | 24 | type Students []Student 25 | 26 | func (s Students) GetByID(id int) (*Student, error) { 27 | for i := range s { 28 | if s[i].ID == id { 29 | return &s[i], nil 30 | } 31 | } 32 | return nil, fmt.Errorf("Student with ID: %v not found", id) 33 | 34 | } 35 | 36 | var ( 37 | students Students 38 | studentsMutex sync.Mutex 39 | ) 40 | 41 | type GradeType string 42 | 43 | const ( 44 | GradeTest = GradeType("Test") 45 | GradeHomework = GradeType("Homework") 46 | GradeQuiz = GradeType("Quiz") 47 | ) 48 | 49 | type Grade struct { 50 | Title string 51 | Type GradeType 52 | Score float32 53 | } 54 | -------------------------------------------------------------------------------- /distributedappdocker/cmd/logservice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | stlog "log" 7 | 8 | "github.com/erankitcs/golang_learning/distributedapp/log" 9 | "github.com/erankitcs/golang_learning/distributedapp/registry" 10 | "github.com/erankitcs/golang_learning/distributedapp/service" 11 | ) 12 | 13 | func main() { 14 | log.Run("./app.log") 15 | var r registry.Registration 16 | hostname, port := "logservice", "4000" 17 | serviceURL := fmt.Sprintf("http://%v:%v", hostname, port) 18 | globalServiceURL := fmt.Sprintf("http://logservice:%v", port) 19 | r.ServiceName = registry.LogService 20 | r.ServiceURL = serviceURL 21 | r.RequiredServices = make([]registry.ServiceName, 0) 22 | r.ServiceUpdateURL = globalServiceURL + "/services" 23 | r.HeartbeatURL = globalServiceURL + "/heartbeat" 24 | 25 | ctx, err := service.Start( 26 | context.Background(), 27 | r, 28 | hostname, 29 | port, 30 | log.RegisterHandler, 31 | ) 32 | 33 | if err != nil { 34 | stlog.Fatal(err) 35 | } 36 | <-ctx.Done() 37 | fmt.Println("Shutting down log service.") 38 | } 39 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/data/winners.json: -------------------------------------------------------------------------------- 1 | { 2 | "winners": [ 3 | { "country": "France", "year": 2018 }, 4 | { "country": "Germany", "year": 2014 }, 5 | { "country": "Spain", "year": 2010 }, 6 | { "country": "Italy", "year": 2006 }, 7 | { "country": "Brazil", "year": 2002 }, 8 | { "country": "France", "year": 1998 }, 9 | { "country": "Brazil", "year": 1994 }, 10 | { "country": "West Germany", "year": 1990 }, 11 | { "country": "Argentina", "year": 1986 }, 12 | { "country": "Italy", "year": 1982 }, 13 | { "country": "Argentina", "year": 1978 }, 14 | { "country": "West Germany", "year": 1974 }, 15 | { "country": "Brazil", "year": 1970 }, 16 | { "country": "England", "year": 1966 }, 17 | { "country": "Brazil", "year": 1962 }, 18 | { "country": "Brazil", "year": 1958 }, 19 | { "country": "West Germany", "year": 1954 }, 20 | { "country": "Uruguay", "year": 1950 }, 21 | { "country": "Italy", "year": 1938 }, 22 | { "country": "Italy", "year": 1934 }, 23 | { "country": "Uruguay", "year": 1930 } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ankit K Singh 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 | -------------------------------------------------------------------------------- /ginframeworkdemo/responsedemo/go.mod: -------------------------------------------------------------------------------- 1 | module gindemo 2 | 3 | go 1.17 4 | 5 | require github.com/gin-gonic/gin v1.8.1 6 | 7 | require ( 8 | github.com/gin-contrib/sse v0.1.0 // indirect 9 | github.com/go-playground/locales v0.14.0 // indirect 10 | github.com/go-playground/universal-translator v0.18.0 // indirect 11 | github.com/go-playground/validator/v10 v10.10.0 // indirect 12 | github.com/goccy/go-json v0.9.7 // indirect 13 | github.com/json-iterator/go v1.1.12 // indirect 14 | github.com/leodido/go-urn v1.2.1 // indirect 15 | github.com/mattn/go-isatty v0.0.14 // indirect 16 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 17 | github.com/modern-go/reflect2 v1.0.2 // indirect 18 | github.com/pelletier/go-toml/v2 v2.0.1 // indirect 19 | github.com/ugorji/go/codec v1.2.7 // indirect 20 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect 21 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect 22 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect 23 | golang.org/x/text v0.3.6 // indirect 24 | google.golang.org/protobuf v1.28.0 // indirect 25 | gopkg.in/yaml.v2 v2.4.0 // indirect 26 | ) 27 | -------------------------------------------------------------------------------- /gostandard_libs/print_demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var age = 42 7 | 8 | var out, _ = fmt.Print("I am ", age, " Year old.\n") 9 | print("Bytes written - ", out) 10 | 11 | var name = "Jeremy" 12 | 13 | fmt.Printf("\nMy name is %s and I am %d years old\n", name, age) 14 | 15 | var pi float32 = 3.141592 16 | 17 | fmt.Printf("Pi is %f\n", pi) 18 | fmt.Printf("Pi is %2.2f\n", pi) 19 | 20 | test := fmt.Sprintf("|%7.2f|%7.2f|%7.2f|\n", 23.3774, 577.45, 1234.56) 21 | print(test) 22 | fmt.Printf("|%7.2f|%7.2f|%7.2f|\n", 98.999, 12.3456, 12.01) 23 | 24 | fmt.Printf("|%-7s|%-7s|%-7s|\n", "foo", "bar", "go") 25 | fmt.Printf("|%-7s|%-7s|%-7d|\n", "a", "ab", 100) 26 | 27 | type point struct { 28 | x, y int 29 | } 30 | 31 | p := point{1, 2} 32 | fmt.Printf("%v\n", p) 33 | 34 | type Person struct { 35 | firstName string 36 | lastName string 37 | age int 38 | } 39 | 40 | newPerson := Person{"Ankit", "Singh", 42} 41 | 42 | fmt.Printf("%T\n", newPerson) 43 | 44 | var isCool = true 45 | fmt.Printf("Value is %t\n", isCool) 46 | fmt.Printf("Value is %T\n", isCool) 47 | 48 | fmt.Printf("%c\n", 3) 49 | } 50 | -------------------------------------------------------------------------------- /distributedappdocker/Readme.md: -------------------------------------------------------------------------------- 1 | ### Distributed App built using Golang. 2 | 3 | #### Create a user defined network 4 | ``` 5 | docker network create teacherportal 6 | ``` 7 | 8 | #### Registry service 9 | ``` 10 | docker build -f Dockerfile.registryservice -t registryservice . 11 | docker run -p 3000:3000 --name registryservice --network=teacherportal -d registryservice 12 | ``` 13 | 14 | #### Log service 15 | ``` 16 | docker build -f Dockerfile.logservice -t logservice . 17 | docker run -p 4000:4000 --name logservice --network=teacherportal -d logservice 18 | ``` 19 | 20 | #### Grading service 21 | ``` 22 | docker build -f Dockerfile.gradingservice -t gradingservice . 23 | docker run -p 6000:6000 --name gradingservice --network=teacherportal -d gradingservice 24 | ``` 25 | 26 | #### Teacher Portal service 27 | ``` 28 | docker build -f Dockerfile.teacherportalservice -t teacherportalservice . 29 | docker run -p 5000:5000 --name teacherportalservice --network=teacherportal -d teacherportalservice 30 | ``` 31 | 32 | #### Application URL 33 | http://localhost:5000 34 | 35 | 36 | #### Useful links 37 | 1. https://marcofranssen.nl/docker-tips-and-tricks-for-your-go-projects 38 | 39 | -------------------------------------------------------------------------------- /ginframeworkdemo/requestdemo/go.mod: -------------------------------------------------------------------------------- 1 | module gindemo 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.8.1 7 | github.com/go-playground/validator/v10 v10.11.0 8 | ) 9 | 10 | require ( 11 | github.com/gin-contrib/sse v0.1.0 // indirect 12 | github.com/go-playground/locales v0.14.0 // indirect 13 | github.com/go-playground/universal-translator v0.18.0 // indirect 14 | github.com/goccy/go-json v0.9.10 // indirect 15 | github.com/json-iterator/go v1.1.12 // indirect 16 | github.com/leodido/go-urn v1.2.1 // indirect 17 | github.com/mattn/go-isatty v0.0.14 // indirect 18 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 19 | github.com/modern-go/reflect2 v1.0.2 // indirect 20 | github.com/pelletier/go-toml/v2 v2.0.2 // indirect 21 | github.com/ugorji/go/codec v1.2.7 // indirect 22 | golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect 23 | golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48 // indirect 24 | golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 // indirect 25 | golang.org/x/text v0.3.7 // indirect 26 | google.golang.org/protobuf v1.28.1 // indirect 27 | gopkg.in/yaml.v2 v2.4.0 // indirect 28 | ) 29 | -------------------------------------------------------------------------------- /ginframeworkdemo/requestdemo/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Employee Vacation Tracker 8 | 9 | 10 | 11 |

Employee Vacation Tracker

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
IDLast NameFirst NameTotal PTOPTO Events
176158JaneAllison203
160898UppalAakar200
297365AndersonJonathon300
42 | 43 | -------------------------------------------------------------------------------- /ginframeworkdemo/vacationtracker/go.mod: -------------------------------------------------------------------------------- 1 | module vacationtracker 2 | 3 | go 1.17 4 | 5 | require github.com/gin-gonic/gin v1.8.1 6 | 7 | require ( 8 | github.com/gin-contrib/sse v0.1.0 // indirect 9 | github.com/go-playground/locales v0.14.0 // indirect 10 | github.com/go-playground/universal-translator v0.18.0 // indirect 11 | github.com/go-playground/validator/v10 v10.10.0 // indirect 12 | github.com/goccy/go-json v0.9.7 // indirect 13 | github.com/json-iterator/go v1.1.12 // indirect 14 | github.com/leodido/go-urn v1.2.1 // indirect 15 | github.com/mattn/go-isatty v0.0.14 // indirect 16 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 17 | github.com/modern-go/reflect2 v1.0.2 // indirect 18 | github.com/pelletier/go-toml/v2 v2.0.1 // indirect 19 | github.com/ugorji/go/codec v1.2.7 // indirect 20 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect 21 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect 22 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect 23 | golang.org/x/text v0.3.6 // indirect 24 | google.golang.org/protobuf v1.28.0 // indirect 25 | gopkg.in/yaml.v2 v2.4.0 // indirect 26 | ) 27 | -------------------------------------------------------------------------------- /ginframeworkdemo/vacationtracker/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Employee Vacation Tracker 8 | 9 | 10 | 11 |

Employee Vacation Tracker

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
IDLast NameFirst NameTotal PTOPTO Events
176158JaneAllison203
160898UppalAakar200
297365AndersonJonathon300
42 | 43 | -------------------------------------------------------------------------------- /golang-async-logging-library/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | -------------------------------------------------------------------------------- /gostandard_libs/filemaker_demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | func main() { 11 | fmt.Println("This program creates a file.") 12 | // Getting filename from input args. 13 | args := os.Args[1:] 14 | if len(args) == 0 || args[0] == "/help" { 15 | fmt.Println("Usage : filemaker_demo.exe ") 16 | } else { 17 | fmt.Println("How would you like to see this text ??") 18 | fmt.Println("1: All caps") 19 | fmt.Println("2: Title Case") 20 | fmt.Println("3: lowercase") 21 | 22 | var option int 23 | 24 | _, err := fmt.Scanf("%d", &option) 25 | if err != nil { 26 | fmt.Println(err) 27 | } 28 | 29 | file, err := os.Open(args[0]) 30 | if err != nil { 31 | fmt.Println(err) 32 | } 33 | defer file.Close() 34 | 35 | scanner := bufio.NewScanner(file) 36 | 37 | for scanner.Scan() { 38 | switch option { 39 | case 1: 40 | fmt.Println(strings.ToUpper(scanner.Text())) 41 | case 2: 42 | fmt.Println(strings.Title(scanner.Text())) 43 | case 3: 44 | fmt.Println(strings.ToLower(scanner.Text())) 45 | } 46 | } 47 | if err := scanner.Err(); err != nil { 48 | fmt.Println(err) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-advanced-branching/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | -------------------------------------------------------------------------------- /gostandard_libs/loger_demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | ) 7 | 8 | type messageType int 9 | 10 | const ( 11 | INFO messageType = 0 + iota 12 | WARNING 13 | ERROR 14 | FATAL 15 | ) 16 | 17 | /*func main() { 18 | writeLog(INFO, "this is an information message!") 19 | writeLog(WARNING, "this is a warning") 20 | writeLog(ERROR, "this is an error") 21 | writeLog(FATAL, "we crashed") 22 | writeLog(INFO, "you'll never see this message!") 23 | 24 | }*/ 25 | 26 | func writeLog(messagetype messageType, message string) { 27 | 28 | file, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666) 29 | 30 | if err != nil { 31 | log.Fatal(err) 32 | } 33 | 34 | switch messagetype { 35 | case INFO: 36 | logger := log.New(file, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile) 37 | logger.Println(message) 38 | case WARNING: 39 | logger := log.New(file, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile) 40 | logger.Println(message) 41 | case ERROR: 42 | logger := log.New(file, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile) 43 | logger.Println(message) 44 | case FATAL: 45 | logger := log.New(file, "FATAL: ", log.Ldate|log.Ltime|log.Lshortfile) 46 | logger.Fatal(message) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /concurrentprogram/ChannelDemo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | func main() { 9 | println("Channel Demo..") 10 | wg := &sync.WaitGroup{} 11 | //ch := make(chan int) 12 | //Buffered channel 13 | ch := make(chan int, 2) 14 | wg.Add(2) 15 | /* go func(ch chan int, wg *sync.WaitGroup) { 16 | fmt.Println("Channel Reader..") 17 | fmt.Println(<-ch) 18 | fmt.Println(<-ch) 19 | wg.Done() 20 | }(ch, wg) 21 | 22 | go func(ch chan int, wg *sync.WaitGroup) { 23 | ch <- 2 24 | ch <- 5 25 | wg.Done() 26 | }(ch, wg) */ 27 | 28 | //Different channel type 29 | 30 | go func(ch <-chan int, wg *sync.WaitGroup) { 31 | fmt.Println("Channel Reader Recieve only..") 32 | //fmt.Println(<-ch) 33 | //fmt.Println(<-ch) 34 | //Better way to read from channel. 35 | //if msg, ok := <-ch; ok { 36 | // fmt.Println(msg) 37 | //} 38 | 39 | for i := range ch { 40 | fmt.Println(i) 41 | } 42 | 43 | wg.Done() 44 | }(ch, wg) 45 | 46 | go func(ch chan<- int, wg *sync.WaitGroup) { 47 | //Channel push only 48 | for i := 0; i < 10; i++ { 49 | ch <- i 50 | } 51 | //only normal channel or push only channel can close the channel. 52 | //close(ch) 53 | wg.Done() 54 | }(ch, wg) 55 | wg.Wait() 56 | } 57 | -------------------------------------------------------------------------------- /functions/simplemaths/scemanticversion.go: -------------------------------------------------------------------------------- 1 | package simplemaths 2 | 3 | import "fmt" 4 | 5 | /// Method Declarations 6 | type SemanticVersion struct { 7 | // private variables . Small letter. 8 | major, minor, patch int 9 | } 10 | 11 | func NewSemanticVersion(major, minor, patch int) SemanticVersion { 12 | return SemanticVersion{ 13 | major: major, 14 | minor: minor, 15 | patch: patch, 16 | } 17 | } 18 | 19 | //General way. 20 | func AnotherString(sv SemanticVersion) string { 21 | return fmt.Sprintf("%d.%d.%d", sv.major, sv.minor, sv.patch) 22 | } 23 | 24 | // This is a method for semantic version type. 25 | func (sv SemanticVersion) String() string { 26 | return fmt.Sprintf("%d.%d.%d", sv.major, sv.minor, sv.patch) 27 | } 28 | 29 | // Value based Reciever. You have to always create a copy of object then call again for state update. 30 | //func (sv SemanticVersion) IncrementMajor() SemanticVersion { 31 | // sv.major += 1 32 | // return sv 33 | //} 34 | 35 | // Pointer based method reciever. 36 | 37 | func (sv *SemanticVersion) IncrementMajor() { 38 | sv.major += 1 39 | } 40 | 41 | func (sv *SemanticVersion) IncrementMinor() { 42 | sv.minor += 1 43 | } 44 | 45 | func (sv *SemanticVersion) IncrementPatch() { 46 | sv.patch += 1 47 | 48 | } 49 | -------------------------------------------------------------------------------- /testinggolang/README.md: -------------------------------------------------------------------------------- 1 | #### Go Testing Commands 2 | 3 | 1. Run all test 4 | ``` 5 | go test 6 | ``` 7 | 2. Test Specific package 8 | ``` 9 | go test {pkg1} {pkg2}... 10 | ``` 11 | 3. Run tests in current and decendent directory 12 | ``` 13 | go test ./... 14 | ``` 15 | 4. Generate verbose output 16 | ``` 17 | go test -v 18 | ``` 19 | 5. Run only tests matching 20 | ``` 21 | go test -run {regexp} 22 | ``` 23 | 6. Generate Test Coverage 24 | ``` 25 | go test -cover 26 | ``` 27 | 7. Generatge test cover profile to find exact functions missing test coverage. 28 | ``` 29 | go test -coverprofile cover.out 30 | go tool cover -func cover.out 31 | go tool cover -html cover.out 32 | go test -coverprofile count.out -covermode count 33 | go tool cover -html cover.out 34 | ``` 35 | 36 | 8. Benchmark testing including other test 37 | ``` 38 | go test -bench . 39 | go test -bench . -benchtime 10s 40 | 41 | ``` 42 | 9. Profile testing - block, cover, cpu, mem, mutex 43 | ``` 44 | go test -bench . -benchmem 45 | go test -bench SHA1 -benchmem 46 | go test -trace {trace.out} 47 | go test -{type}profile {file} 48 | go test -bench Alloc -memprofile profile.out 49 | ## install choco install graphviz for graph 50 | go tool pprof profile.out 51 | type help to more info. like run svg 52 | ``` -------------------------------------------------------------------------------- /ginframeworkdemo/vacationtracker/employee/employee.go: -------------------------------------------------------------------------------- 1 | package employee 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | type Employee struct { 9 | ID int 10 | FirstName string 11 | LastName string 12 | StartDate time.Time 13 | Position string 14 | TotalPTO float32 15 | Status string 16 | TimeOff []TimeOff 17 | } 18 | 19 | type TimeOff struct { 20 | Type TimeoffType 21 | Amount float32 `form:"amount" json:"amount" binding:"required"` 22 | StartDate time.Time `form:"date" json:"date" binding:"required" time_format:"2006-01-02"` 23 | Status TimeoffStatus 24 | } 25 | 26 | type TimeoffStatus string 27 | type TimeoffType string 28 | 29 | const ( 30 | TimeoffStatusRequested TimeoffStatus = "Requested" 31 | TimeoffStatusScheduled TimeoffStatus = "Scheduled" 32 | TimeoffStatusTaken TimeoffStatus = "Taken" 33 | ) 34 | 35 | const ( 36 | TimeoffTypeHoliday TimeoffType = "Holiday" 37 | TimeoffTypePTO TimeoffType = "PTO" 38 | ) 39 | 40 | func Get(id int) (*Employee, error) { 41 | for i := range employees { 42 | if employees[i].ID == id { 43 | return &employees[i], nil 44 | } 45 | } 46 | return nil, fmt.Errorf("employee with id %v not found", id) 47 | } 48 | 49 | func GetAll() []Employee { 50 | return employees 51 | } 52 | -------------------------------------------------------------------------------- /gostandard_libs/custom_type/customtype.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/erankitcs/golang_learning/gostandard_libs/custom_type/media" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("My Fav movies") 11 | //myMov := media.Movie{} 12 | //myMov.Title = "Top Gun" 13 | //myMov.Rating = media.R 14 | //myMov.BoxOffice = 43.2 15 | //fmt.Printf("My fav movie is : %s \n", myMov.Title) 16 | //fmt.Printf("its rating is : %s \n", myMov.Rating) 17 | //fmt.Printf("It made %f in the box office. \n", myMov.BoxOffice) 18 | 19 | //myMov := media.NewMovie("Top Gun", media.R, 43.2) 20 | //fmt.Printf("My fav movie is : %s \n", myMov.GetTitle()) 21 | //fmt.Printf("its rating is : %s \n", myMov.GetRating()) 22 | //fmt.Printf("It made %f in the box office. \n", myMov.GetBoxOffice()) 23 | //myMov.SetTitle("New Top Gun") 24 | //fmt.Printf("My fav movie is : %s \n", myMov.GetTitle()) 25 | 26 | var myMov media.Catalogable = &media.Movie{} 27 | myMov.NewMovie("Top Gun", media.PG, 32.8) 28 | fmt.Printf("My fav movie is : %s \n", myMov.GetTitle()) 29 | fmt.Printf("its rating is : %s \n", myMov.GetRating()) 30 | fmt.Printf("It made %f in the box office. \n", myMov.GetBoxOffice()) 31 | myMov.SetTitle("New Top Gun") 32 | fmt.Printf("My fav movie is : %s \n", myMov.GetTitle()) 33 | } 34 | -------------------------------------------------------------------------------- /webservice/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | type User struct { 9 | ID int 10 | FirstName string 11 | LastName string 12 | } 13 | 14 | var ( 15 | users []*User 16 | nextID = 1 17 | ) 18 | 19 | func GetUsers() []*User { 20 | return users 21 | } 22 | 23 | func AddUser(u User) (User, error) { 24 | if u.ID != 0 { 25 | return User{}, errors.New("New User must not include id or it must be set to zero") 26 | } 27 | u.ID = nextID 28 | nextID++ 29 | users = append(users, &u) 30 | return u, nil 31 | } 32 | 33 | func GetUserById(id int) (User, error) { 34 | for _, u := range users { 35 | if u.ID == id { 36 | return *u, nil 37 | } 38 | } 39 | return User{}, fmt.Errorf("User Id with '%v' not found", id) 40 | } 41 | 42 | func UpdateUser(u User) (User, error) { 43 | for i, useritem := range users { 44 | if u.ID == useritem.ID { 45 | users[i] = &u 46 | return *users[i], nil 47 | } 48 | } 49 | return User{}, fmt.Errorf("User Id with '%v' not found", u.ID) 50 | 51 | } 52 | 53 | func RemoveUserById(id int) error { 54 | for i, u := range users { 55 | if u.ID == id { 56 | users = append(users[:i], users[i+1:]...) 57 | return nil 58 | } 59 | } 60 | return fmt.Errorf("User with ID '%v' not found", id) 61 | } 62 | -------------------------------------------------------------------------------- /customdatatypes/datatypes4/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/erankitcs/golang_learning/customdatatypes/datatypes4/organisation" 7 | ) 8 | 9 | type Name struct { 10 | First string 11 | Last string 12 | Middle []string 13 | } 14 | 15 | type OtherName struct { 16 | First string 17 | Last string 18 | } 19 | 20 | func (n Name) Equals(otherName Name) bool { 21 | return n.First == otherName.First && n.Last == otherName.Last && len(n.Middle) == len(otherName.Middle) 22 | } 23 | 24 | func main() { 25 | fmt.Println("Custom Type Demo 4") 26 | p := organisation.NewPerson("Ankit", "Singh", organisation.NewEuropeanUnionIdentifier("123-45-33", "UK")) 27 | err := p.SetTwitterHandler("@ankit63") 28 | fmt.Printf("%T\n", organisation.TwitterHandler("test")) 29 | if err != nil { 30 | fmt.Printf("An error occurred while setting handler %s", err.Error()) 31 | } 32 | 33 | name1 := Name{ 34 | First: "", 35 | Last: "", 36 | } 37 | 38 | if name1.Equals(Name{}) { 39 | println("We match") 40 | } 41 | 42 | p.First = "NewName" 43 | println(p.First) 44 | println(p.Name.First) 45 | fmt.Println(p.TwitterHandler()) 46 | fmt.Println(p.TwitterHandler().RedirectURL()) 47 | fmt.Println(p.FullName()) 48 | fmt.Println(p.ID()) 49 | println(p.Country()) 50 | 51 | } 52 | -------------------------------------------------------------------------------- /customdatatypes/datatypes5/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/erankitcs/golang_learning/customdatatypes/datatypes5/organisation" 7 | ) 8 | 9 | type Name struct { 10 | First string 11 | Last string 12 | Middle []string 13 | } 14 | 15 | type OtherName struct { 16 | First string 17 | Last string 18 | } 19 | 20 | func (n Name) Equals(otherName Name) bool { 21 | return n.First == otherName.First && n.Last == otherName.Last && len(n.Middle) == len(otherName.Middle) 22 | } 23 | 24 | func main() { 25 | fmt.Println("Custom Type Demo 4") 26 | p := organisation.NewPerson("Ankit", "Singh", organisation.NewEuropeanUnionIdentifier("123-445-3455", "UK")) 27 | err := p.SetTwitterHandler("@ankit63") 28 | fmt.Printf("%T\n", organisation.TwitterHandler("test")) 29 | if err != nil { 30 | fmt.Printf("An error occurred while setting handler %s", err.Error()) 31 | } 32 | 33 | name1 := Name{ 34 | First: "", 35 | Last: "", 36 | } 37 | 38 | if name1.Equals(Name{}) { 39 | println("We match") 40 | } 41 | 42 | p.First = "NewName" 43 | println(p.First) 44 | println(p.Name.First) 45 | fmt.Println(p.TwitterHandler()) 46 | fmt.Println(p.TwitterHandler().RedirectURL()) 47 | fmt.Println(p.FullName()) 48 | fmt.Println(p.ID()) 49 | println(p.Country()) 50 | 51 | } 52 | -------------------------------------------------------------------------------- /distributedapp/cmd/gradingservice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | stlog "log" 7 | 8 | "github.com/erankitcs/golang_learning/distributedapp/grades" 9 | "github.com/erankitcs/golang_learning/distributedapp/log" 10 | "github.com/erankitcs/golang_learning/distributedapp/registry" 11 | "github.com/erankitcs/golang_learning/distributedapp/service" 12 | ) 13 | 14 | func main() { 15 | var r registry.Registration 16 | hostname, port := "localhost", "6000" 17 | serviceURL := fmt.Sprintf("http://%v:%v", hostname, port) 18 | r.ServiceName = registry.GradingService 19 | r.ServiceURL = serviceURL 20 | r.RequiredServices = []registry.ServiceName{registry.LogService} 21 | r.ServiceUpdateURL = r.ServiceURL + "/services" 22 | r.HeartbeatURL = r.ServiceURL + "/heartbeat" 23 | fmt.Println(r) 24 | ctx, err := service.Start( 25 | context.Background(), 26 | r, 27 | hostname, 28 | port, 29 | grades.RegisterHandlers, 30 | ) 31 | 32 | if err != nil { 33 | stlog.Fatal(err) 34 | } 35 | if logProvider, err := registry.GetProvider(registry.LogService); err == nil { 36 | fmt.Printf("Logging service found at: %v\n", logProvider) 37 | log.SetClientLogger(logProvider, r.ServiceName) 38 | } 39 | <-ctx.Done() 40 | fmt.Println("Shutting down Grading service.") 41 | } 42 | -------------------------------------------------------------------------------- /distributedapp/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | 9 | "github.com/erankitcs/golang_learning/distributedapp/registry" 10 | ) 11 | 12 | func Start(ctx context.Context, reg registry.Registration, host, port string, 13 | registerHandlerFun func()) (context.Context, error) { 14 | registerHandlerFun() 15 | ctx = startService(ctx, reg.ServiceName, host, port) 16 | err := registry.RegisterService(reg) 17 | if err != nil { 18 | return ctx, err 19 | } 20 | return ctx, nil 21 | } 22 | 23 | func startService(ctx context.Context, serviceName registry.ServiceName, host, port string) context.Context { 24 | ctx, cancel := context.WithCancel(ctx) 25 | 26 | var srv http.Server 27 | srv.Addr = ":" + port 28 | 29 | go func() { 30 | log.Println(srv.ListenAndServe()) 31 | cancel() 32 | }() 33 | 34 | go func() { 35 | fmt.Printf("%v started. Please press any key to stop.\n", serviceName) 36 | var s string 37 | fmt.Scanln(&s) 38 | fmt.Printf("De-registering the service- %v with URL http://%v:%v \n", serviceName, host, port) 39 | err := registry.ShutdownService(fmt.Sprintf("http://%v:%v", host, port)) 40 | if err != nil { 41 | log.Println(err) 42 | } 43 | srv.Shutdown(ctx) 44 | cancel() 45 | }() 46 | return ctx 47 | } 48 | -------------------------------------------------------------------------------- /grpcdemo/pb/messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "pb/messages"; 4 | 5 | package messages; 6 | 7 | message Employee { 8 | int32 id = 1 ; 9 | int32 badgeNumber = 2; 10 | string firstName = 3 ; 11 | string lastName = 4; 12 | float vacationAccrualRate = 5; 13 | float vacationAccrued = 6; 14 | repeated Vacation vacations = 7; 15 | } 16 | 17 | message Vacation { 18 | int32 id = 1 ; 19 | int64 startDate = 2 ; 20 | float duration = 3; 21 | bool isCancelled = 4; 22 | } 23 | 24 | message GetAllRequest {} 25 | 26 | message GetByBadgeNumberRequest { 27 | int32 badgeNumber = 1 ; 28 | } 29 | 30 | message EmployeeRequest { 31 | Employee employee = 1; 32 | } 33 | 34 | message EmployeeResponse { 35 | Employee employee = 1 ; 36 | } 37 | 38 | message AddPhotoRequest { 39 | bytes data = 1 ; 40 | } 41 | 42 | message AddPhotoResponse { 43 | bool isOK = 1 ; 44 | } 45 | 46 | service EmployeeService { 47 | rpc GetByBadgeNumber (GetByBadgeNumberRequest) returns (EmployeeResponse); 48 | rpc GetAll (GetAllRequest) returns (stream EmployeeResponse); 49 | rpc Save (EmployeeRequest) returns (EmployeeResponse); 50 | rpc SaveAll(stream EmployeeRequest) returns (stream EmployeeResponse); 51 | rpc AddPhoto (stream AddPhotoRequest) returns (AddPhotoResponse); 52 | } -------------------------------------------------------------------------------- /distributedappdocker/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | 9 | "github.com/erankitcs/golang_learning/distributedapp/registry" 10 | ) 11 | 12 | func Start(ctx context.Context, reg registry.Registration, host, port string, 13 | registerHandlerFun func()) (context.Context, error) { 14 | registerHandlerFun() 15 | ctx = startService(ctx, reg.ServiceName, host, port) 16 | err := registry.RegisterService(reg) 17 | if err != nil { 18 | return ctx, err 19 | } 20 | return ctx, nil 21 | } 22 | 23 | func startService(ctx context.Context, serviceName registry.ServiceName, host, port string) context.Context { 24 | ctx, cancel := context.WithCancel(ctx) 25 | 26 | var srv http.Server 27 | srv.Addr = ":" + port 28 | 29 | go func() { 30 | log.Println(srv.ListenAndServe()) 31 | cancel() 32 | }() 33 | 34 | go func() { 35 | fmt.Printf("%v started. Please press- s key to stop.\n", serviceName) 36 | var s string 37 | fmt.Scanln(&s) 38 | if s == "s" { 39 | fmt.Printf("De-registering the service- %v with URL http://%v:%v \n", serviceName, host, port) 40 | err := registry.ShutdownService(fmt.Sprintf("http://%v:%v", host, port)) 41 | if err != nil { 42 | log.Println(err) 43 | } 44 | srv.Shutdown(ctx) 45 | cancel() 46 | } 47 | 48 | }() 49 | return ctx 50 | } 51 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger-client/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/microservices/productapiclient 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/go-openapi/errors v0.20.2 7 | github.com/go-openapi/runtime v0.24.1 8 | github.com/go-openapi/strfmt v0.21.3 9 | github.com/go-openapi/swag v0.21.1 10 | github.com/go-openapi/validate v0.22.0 11 | ) 12 | 13 | require ( 14 | github.com/PuerkitoBio/purell v1.1.1 // indirect 15 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 16 | github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect 17 | github.com/go-openapi/analysis v0.21.2 // indirect 18 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 19 | github.com/go-openapi/jsonreference v0.19.6 // indirect 20 | github.com/go-openapi/loads v0.21.1 // indirect 21 | github.com/go-openapi/spec v0.20.4 // indirect 22 | github.com/josharian/intern v1.0.0 // indirect 23 | github.com/mailru/easyjson v0.7.7 // indirect 24 | github.com/mitchellh/mapstructure v1.4.3 // indirect 25 | github.com/oklog/ulid v1.3.1 // indirect 26 | github.com/opentracing/opentracing-go v1.2.0 // indirect 27 | go.mongodb.org/mongo-driver v1.10.0 // indirect 28 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect 29 | golang.org/x/text v0.3.7 // indirect 30 | gopkg.in/yaml.v2 v2.4.0 // indirect 31 | ) 32 | -------------------------------------------------------------------------------- /customdatatypes/datatypes2/organisation/person.go: -------------------------------------------------------------------------------- 1 | package organisation 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | type Handler struct { 10 | handle string 11 | name string 12 | } 13 | 14 | type TwitterHandler string 15 | 16 | func (th TwitterHandler) RedirectURL() string { 17 | cleanHandler := strings.TrimPrefix(string(th), "@") 18 | return fmt.Sprintf("https://www.twitter.com/%s", cleanHandler) 19 | } 20 | 21 | type Identifiable interface { 22 | ID() string 23 | } 24 | 25 | type Person struct { 26 | firstName string 27 | lastName string 28 | twitterHandler TwitterHandler 29 | } 30 | 31 | func NewPerson(firstName, lastName string) Person { 32 | return Person{ 33 | firstName: firstName, 34 | lastName: lastName, 35 | } 36 | } 37 | 38 | func (p *Person) SetTwitterHandler(handler TwitterHandler) error { 39 | if len(handler) == 0 { 40 | p.twitterHandler = handler 41 | } else if !strings.HasPrefix(string(handler), "@") { 42 | return errors.New("twitter handle must start with @ in text") 43 | } 44 | p.twitterHandler = handler 45 | return nil 46 | } 47 | 48 | func (p *Person) FullName() string { 49 | return fmt.Sprintf("%s %s", p.firstName, p.lastName) 50 | } 51 | 52 | func (p *Person) ID() string { 53 | return "123" 54 | } 55 | 56 | func (p *Person) TwitterHandler() TwitterHandler { 57 | return p.twitterHandler 58 | } 59 | -------------------------------------------------------------------------------- /distributedappdocker/cmd/gradingservice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | stlog "log" 7 | 8 | "github.com/erankitcs/golang_learning/distributedapp/grades" 9 | "github.com/erankitcs/golang_learning/distributedapp/log" 10 | "github.com/erankitcs/golang_learning/distributedapp/registry" 11 | "github.com/erankitcs/golang_learning/distributedapp/service" 12 | ) 13 | 14 | func main() { 15 | var r registry.Registration 16 | hostname, port := "gradingservice", "6000" 17 | serviceURL := fmt.Sprintf("http://%v:%v", hostname, port) 18 | globalServiceURL := fmt.Sprintf("http://gradingservice:%v", port) 19 | r.ServiceName = registry.GradingService 20 | r.ServiceURL = serviceURL 21 | r.RequiredServices = []registry.ServiceName{registry.LogService} 22 | r.ServiceUpdateURL = globalServiceURL + "/services" 23 | r.HeartbeatURL = globalServiceURL + "/heartbeat" 24 | fmt.Println(r) 25 | ctx, err := service.Start( 26 | context.Background(), 27 | r, 28 | hostname, 29 | port, 30 | grades.RegisterHandlers, 31 | ) 32 | 33 | if err != nil { 34 | stlog.Fatal(err) 35 | } 36 | if logProvider, err := registry.GetProvider(registry.LogService); err == nil { 37 | fmt.Printf("Logging service found at: %v\n", logProvider) 38 | log.SetClientLogger(logProvider, r.ServiceName) 39 | } 40 | <-ctx.Done() 41 | fmt.Println("Shutting down Grading service.") 42 | } 43 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/handlers/middleware.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | 7 | "github.com/erankitcs/golang_learning/microservices/product-api-withswagger/data" 8 | ) 9 | 10 | //Middleware Validate Product 11 | func (p *Products) MiddlewareProductsValidation(next http.Handler) http.Handler { 12 | return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { 13 | 14 | prod := &data.Product{} 15 | 16 | err := data.FromJSON(prod, r.Body) 17 | if err != nil { 18 | p.l.Println("[ERROR] deserializing product", err) 19 | 20 | rw.WriteHeader(http.StatusBadRequest) 21 | data.ToJSON(&GenericError{Message: err.Error()}, rw) 22 | return 23 | } 24 | //validate the product 25 | errs := p.v.Validate(prod) 26 | 27 | if len(errs) != 0 { 28 | p.l.Println("[ERROR] Validating the product", errs) 29 | rw.WriteHeader(http.StatusUnprocessableEntity) 30 | data.ToJSON(&ValidationError{Messages: errs.Errors()}, rw) 31 | //http.Error(rw, fmt.Sprintf("Error validating the product: %s", err), http.StatusBadRequest) 32 | return 33 | } 34 | // add the product to the context 35 | ctx := context.WithValue(r.Context(), KeyProduct{}, prod) 36 | r = r.WithContext(ctx) 37 | 38 | // Call the next handler, which can be another middleware in the chain, or the final handler. 39 | next.ServeHTTP(rw, r) 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/handlers/products.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "strconv" 8 | 9 | "github.com/erankitcs/golang_learning/microservices/product-api-withswagger/data" 10 | "github.com/gorilla/mux" 11 | ) 12 | 13 | type KeyProduct struct{} 14 | 15 | type Products struct { 16 | l *log.Logger 17 | v *data.Validation 18 | } 19 | 20 | func NewProduct(l *log.Logger, v *data.Validation) *Products { 21 | return &Products{l, v} 22 | } 23 | 24 | // ErrInvalidProductPath is an error message when the product path is not valid 25 | var ErrInvalidProductPath = fmt.Errorf("invalid Path, path should be /products/[id]") 26 | 27 | // GenericError is a generic error message returned by a server 28 | type GenericError struct { 29 | Message string `json:"message"` 30 | } 31 | 32 | // ValidationError is a collection of validation error messages 33 | type ValidationError struct { 34 | Messages []string `json:"messages"` 35 | } 36 | 37 | // getProductID returns the product ID from the URL 38 | // Panics if cannot convert the id into an integer 39 | // this should never happen as the router ensures that 40 | // this is a valid number 41 | func getProductID(r *http.Request) int { 42 | vars := mux.Vars(r) 43 | // convert the id into an integer and return 44 | id, err := strconv.Atoi(vars["id"]) 45 | if err != nil { 46 | panic(err) 47 | } 48 | return id 49 | 50 | } 51 | -------------------------------------------------------------------------------- /distributedapp/cmd/teacherportalservice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | stlog "log" 7 | 8 | "github.com/erankitcs/golang_learning/distributedapp/log" 9 | "github.com/erankitcs/golang_learning/distributedapp/registry" 10 | "github.com/erankitcs/golang_learning/distributedapp/service" 11 | "github.com/erankitcs/golang_learning/distributedapp/teacherportal" 12 | ) 13 | 14 | func main() { 15 | err := teacherportal.ImportTemplates() 16 | 17 | if err != nil { 18 | stlog.Fatal(err) 19 | } 20 | 21 | host, port := "localhost", "5000" 22 | 23 | serviceAddress := fmt.Sprintf("http://%v:%v", host, port) 24 | 25 | var r registry.Registration 26 | r.ServiceName = registry.TeacherPortalService 27 | r.ServiceURL = serviceAddress 28 | r.RequiredServices = []registry.ServiceName{ 29 | registry.LogService, 30 | registry.GradingService, 31 | } 32 | r.ServiceUpdateURL = r.ServiceURL + "/services" 33 | r.HeartbeatURL = r.ServiceURL + "/heartbeat" 34 | 35 | ctx, err := service.Start( 36 | context.Background(), 37 | r, 38 | host, 39 | port, 40 | teacherportal.RegisterHandlers, 41 | ) 42 | 43 | if err != nil { 44 | stlog.Fatal(err) 45 | } 46 | 47 | if logProvider, err := registry.GetProvider(registry.LogService); err == nil { 48 | log.SetClientLogger(logProvider, r.ServiceName) 49 | } 50 | 51 | <-ctx.Done() 52 | fmt.Println("Shutting down teacher portal.") 53 | 54 | } 55 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger-client/models/generic_error.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/strfmt" 12 | "github.com/go-openapi/swag" 13 | ) 14 | 15 | // GenericError GenericError is a generic error message returned by a server 16 | // 17 | // swagger:model GenericError 18 | type GenericError struct { 19 | 20 | // message 21 | Message string `json:"message,omitempty"` 22 | } 23 | 24 | // Validate validates this generic error 25 | func (m *GenericError) Validate(formats strfmt.Registry) error { 26 | return nil 27 | } 28 | 29 | // ContextValidate validates this generic error based on context it is used 30 | func (m *GenericError) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 31 | return nil 32 | } 33 | 34 | // MarshalBinary interface implementation 35 | func (m *GenericError) MarshalBinary() ([]byte, error) { 36 | if m == nil { 37 | return nil, nil 38 | } 39 | return swag.WriteJSON(m) 40 | } 41 | 42 | // UnmarshalBinary interface implementation 43 | func (m *GenericError) UnmarshalBinary(b []byte) error { 44 | var res GenericError 45 | if err := swag.ReadJSON(b, &res); err != nil { 46 | return err 47 | } 48 | *m = res 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-personal-budget-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | m2 "personal-budget/module2" 6 | "time" 7 | ) 8 | 9 | var months = []time.Month{ 10 | time.January, 11 | time.February, 12 | time.March, 13 | time.April, 14 | time.May, 15 | time.June, 16 | time.July, 17 | time.August, 18 | time.September, 19 | time.October, 20 | time.November, 21 | time.December, 22 | time.January, 23 | } 24 | 25 | func main() { 26 | bu, _ := m2.CreateBudget(time.January, 1000) 27 | bu.AddItem("bananas", 10.0) 28 | 29 | fmt.Println("Items in January:", len(bu.Items)) 30 | fmt.Printf("Current cost for January: $%.2f \n", bu.CurrentCost()) 31 | 32 | m2.CreateBudget(time.February, 1000) 33 | 34 | bu2 := m2.GetBudget(time.February) 35 | bu2.AddItem("bananas", 10.0) 36 | bu2.AddItem("coffee", 3.99) 37 | bu2.AddItem("gym", 50.0) 38 | bu2.RemoveItem("coffee") 39 | fmt.Println("Items in February:", len(bu2.Items)) 40 | fmt.Printf("Current cost for February: $%.2f \n", bu2.CurrentCost()) 41 | 42 | fmt.Println("Resetting Budget Report...") 43 | m2.InitializeReport() 44 | 45 | for _, month := range months { 46 | _, err := m2.CreateBudget(month, 100.00) 47 | if err == nil { 48 | fmt.Println("Budget created for", month) 49 | } else { 50 | fmt.Println("Error creating budget:", err) 51 | } 52 | } 53 | 54 | _, err := m2.CreateBudget(time.December, 100.00) 55 | fmt.Println(err) 56 | } 57 | -------------------------------------------------------------------------------- /microservices/product-api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | "os" 8 | "os/signal" 9 | "syscall" 10 | "time" 11 | 12 | "github.com/erankitcs/golang_learning/microservices/product-api/handlers" 13 | ) 14 | 15 | var bindAddress = ":9090" 16 | 17 | func main() { 18 | //Create a logger 19 | l := log.New(os.Stdout, "product-api ", log.LstdFlags) 20 | // New Product handler 21 | ph := handlers.NewProduct(l) 22 | // creating new Muxer and register handler 23 | sm := http.NewServeMux() 24 | sm.Handle("/", ph) 25 | //creating new server 26 | s := http.Server{ 27 | Addr: bindAddress, 28 | Handler: sm, 29 | ErrorLog: l, 30 | ReadTimeout: 5 * time.Second, 31 | WriteTimeout: 10 * time.Second, 32 | IdleTimeout: 120 * time.Second, 33 | } 34 | 35 | //Starting the server 36 | go func() { 37 | l.Printf("Starting Server on Port %s\n", bindAddress) 38 | err := s.ListenAndServe() 39 | if err != nil { 40 | l.Printf("Error in starting the server: %s\n", err) 41 | os.Exit(1) 42 | } 43 | }() 44 | 45 | //Gracefull shutdown 46 | c := make(chan os.Signal, 1) 47 | signal.Notify(c, os.Interrupt) 48 | signal.Notify(c, syscall.SIGTERM) 49 | 50 | //block util a signal recieved 51 | sig := <-c 52 | log.Println("Got Signal: ", sig) 53 | ctx, cancelFun := context.WithTimeout(context.Background(), 30*time.Second) 54 | cancelFun() 55 | s.Shutdown(ctx) 56 | 57 | } 58 | -------------------------------------------------------------------------------- /gostandard_libs/fmt_demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | type messageType int 9 | 10 | const ( 11 | INFO messageType = 0 + iota 12 | WARNING 13 | ERROR 14 | ) 15 | 16 | const ( 17 | InfoColor = "\033[1;34m%s\033[0m" 18 | WarningColor = "\033[1;33m%s\033[0m" 19 | ErrorColor = "\033[1;31m%s\033[0m" 20 | ) 21 | 22 | func main() { 23 | var firstNumber int 24 | println("Whats you first number ?") 25 | fmt.Scanln("%d", &firstNumber) 26 | 27 | var secondNumber int 28 | println("Whats you second number ?") 29 | fmt.Scanln("%d", &secondNumber) 30 | 31 | fmt.Printf("Two number sum is %v", firstNumber+secondNumber) 32 | 33 | fmt.Println("\nMessage Formating program.") 34 | 35 | fileName := "test.txt" 36 | 37 | showMessage(INFO, fmt.Sprintf("About to open %s", fileName)) 38 | 39 | file, err := os.Open("test.txt") 40 | if err != nil { 41 | showMessage(ERROR, err.Error()) 42 | } 43 | defer file.Close() 44 | 45 | } 46 | 47 | func showMessage(messageType messageType, message string) { 48 | switch messageType { 49 | case INFO: 50 | printMessage := fmt.Sprintf("\nInformation: \n%s\n", message) 51 | fmt.Printf(InfoColor, printMessage) 52 | case WARNING: 53 | printMessage := fmt.Sprintf("\nWarning: \n%s\n", message) 54 | fmt.Printf(WarningColor, printMessage) 55 | case ERROR: 56 | printMessage := fmt.Sprintf("\nError: \n%s\n", message) 57 | fmt.Printf(ErrorColor, printMessage) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /distributedappdocker/cmd/teacherportalservice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | stlog "log" 7 | 8 | "github.com/erankitcs/golang_learning/distributedapp/log" 9 | "github.com/erankitcs/golang_learning/distributedapp/registry" 10 | "github.com/erankitcs/golang_learning/distributedapp/service" 11 | "github.com/erankitcs/golang_learning/distributedapp/teacherportal" 12 | ) 13 | 14 | func main() { 15 | err := teacherportal.ImportTemplates() 16 | 17 | if err != nil { 18 | stlog.Fatal(err) 19 | } 20 | 21 | host, port := "localhost", "5000" 22 | 23 | serviceAddress := fmt.Sprintf("http://%v:%v", host, port) 24 | globalServiceURL := fmt.Sprintf("http://teacherportalservice:%v", port) 25 | var r registry.Registration 26 | r.ServiceName = registry.TeacherPortalService 27 | r.ServiceURL = serviceAddress 28 | r.RequiredServices = []registry.ServiceName{ 29 | registry.LogService, 30 | registry.GradingService, 31 | } 32 | r.ServiceUpdateURL = globalServiceURL + "/services" 33 | r.HeartbeatURL = globalServiceURL + "/heartbeat" 34 | 35 | ctx, err := service.Start( 36 | context.Background(), 37 | r, 38 | host, 39 | port, 40 | teacherportal.RegisterHandlers, 41 | ) 42 | 43 | if err != nil { 44 | stlog.Fatal(err) 45 | } 46 | 47 | if logProvider, err := registry.GetProvider(registry.LogService); err == nil { 48 | log.SetClientLogger(logProvider, r.ServiceName) 49 | } 50 | 51 | <-ctx.Done() 52 | fmt.Println("Shutting down teacher portal.") 53 | 54 | } 55 | -------------------------------------------------------------------------------- /ginframeworkdemo/vacationtracker/templates/employee.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | PTO Events - {{.LastName}}, {{.FirstName}} 8 | 9 | 10 | 11 |

PTO Information for {{.LastName}}, {{.FirstName}}

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {{range .TimeOff}} 20 | 21 | 22 | 23 | 24 | 25 | 26 | {{end}} 27 | 28 |
DateAmount [h]TypeStatus
{{.StartDate.Format "02-Jan"}}{{.Amount}}{{.Type}}{{.Status}}
29 | 30 |
31 | Request PTO 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | 48 |
Date
Amount [h]
  45 | 46 |
49 |
50 |
51 | 52 | -------------------------------------------------------------------------------- /gostandard_libs/custom_type/typesruntime.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func main() { 9 | 10 | type person struct { 11 | personId int 12 | firstName string 13 | lastName string 14 | } 15 | 16 | newPerson := person{0, "Ankit", "Singh"} 17 | 18 | fmt.Printf("My person is %s %s with Id %d\n", newPerson.firstName, newPerson.lastName, newPerson.personId) 19 | fmt.Printf("Type is %v \n", reflect.TypeOf(newPerson)) 20 | fmt.Printf("Value is %v \n", reflect.ValueOf(newPerson)) 21 | fmt.Printf("Kind of type is %v \n", reflect.ValueOf(newPerson).Kind()) 22 | type employee struct { 23 | empId int 24 | firstName string 25 | lastName string 26 | } 27 | 28 | type customer struct { 29 | customerId int 30 | firstName string 31 | lastName string 32 | company string 33 | } 34 | 35 | newEmp := employee{0, "Ankit", "Singh"} 36 | newCus := customer{100, "Ankit", "Singh", "NAB"} 37 | 38 | addPerson(newEmp) 39 | addPerson(newCus) 40 | 41 | } 42 | 43 | func addPerson(p interface{}) bool { 44 | if reflect.ValueOf(p).Kind() == reflect.Struct { 45 | v := reflect.ValueOf(p) 46 | 47 | switch reflect.TypeOf(p).Name() { 48 | case "employee": 49 | empString := "insert into emp (?,?,?)" 50 | fmt.Printf("SQL String %s \n", empString) 51 | fmt.Printf("Added %v \n", v.Field(1)) 52 | case "customer": 53 | custString := "insert into cust (?,?,?)" 54 | fmt.Printf("SQL String %s \n", custString) 55 | fmt.Printf("Added %v \n", v.Field(1)) 56 | } 57 | return true 58 | } else { 59 | return false 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/handlers/get.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/erankitcs/golang_learning/microservices/product-api-withswagger/data" 7 | ) 8 | 9 | // swagger:route GET /products products listProducts 10 | // Return a list of product. 11 | // responses: 12 | // 200: productsResponse 13 | func (p *Products) ListAll(rw http.ResponseWriter, r *http.Request) { 14 | p.l.Println("[DEBUG] get all records") 15 | prods := data.GetProducts() 16 | rw.Header().Add("Content-Type", "application/json") 17 | err := data.ToJSON(prods, rw) 18 | if err != nil { 19 | p.l.Println("[ERROR] serializing product", err) 20 | } 21 | } 22 | 23 | // swagger:route GET /products/{id} products listSingleProduct 24 | // Return a single product. 25 | // responses: 26 | // 200: productResponse 27 | func (p *Products) ListSingle(rw http.ResponseWriter, r *http.Request) { 28 | p.l.Println("[DEBUG] get single requested product") 29 | pid := getProductID(r) 30 | prod, err := data.GetProductByID(pid) 31 | switch err { 32 | case nil: 33 | case data.ErrorProductNotFound: 34 | p.l.Println("[ERROR] fetching product", err) 35 | rw.WriteHeader(http.StatusNotFound) 36 | data.ToJSON(&GenericError{Message: err.Error()}, rw) 37 | return 38 | default: 39 | p.l.Println("[ERROR] fetching product", err) 40 | 41 | rw.WriteHeader(http.StatusInternalServerError) 42 | data.ToJSON(&GenericError{Message: err.Error()}, rw) 43 | return 44 | } 45 | err = data.ToJSON(prod, rw) 46 | if err != nil { 47 | p.l.Println("[ERROR] serializing product", err) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ginframeworkdemo/requestdemo/public/employee.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | PTO Events - Jane, Allion 8 | 9 | 10 | 11 |

PTO Information for Jane, Allison

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
DateAmount [h]TypeStatus
1-Jan8HolidayTaken
16-Aug16PTOScheduled
8-Dec16PTORequested
38 | 39 |
40 | Request PTO 41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 56 | 57 |
Date
Amount [h]
  54 | 55 |
58 |
59 |
60 | 61 | -------------------------------------------------------------------------------- /ginframeworkdemo/vacationtracker/public/employee.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | PTO Events - Jane, Allion 8 | 9 | 10 | 11 |

PTO Information for Jane, Allison

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
DateAmount [h]TypeStatus
1-Jan8HolidayTaken
16-Aug16PTOScheduled
8-Dec16PTORequested
38 | 39 |
40 | Request PTO 41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 56 | 57 |
Date
Amount [h]
  54 | 55 |
58 |
59 |
60 | 61 | -------------------------------------------------------------------------------- /gostandard_libs/custom_type/functions.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "runtime" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | func main() { 12 | ourTitle := "the go standard library" 13 | newTitle := properTitle(ourTitle) 14 | fmt.Printf("%s\n", newTitle) 15 | fmt.Printf("Double function : %d", doubleOurNumber(3)) 16 | 17 | timed := MakeTimedFunction(properTitle).(func(string) string) 18 | newTitle1 := timed(ourTitle) 19 | fmt.Println(newTitle1) 20 | timedToo := MakeTimedFunction(doubleOurNumber).(func(int) int) 21 | fmt.Println(timedToo(2)) 22 | } 23 | 24 | func MakeTimedFunction(f interface{}) interface{} { 25 | rf := reflect.TypeOf(f) 26 | if rf.Kind() != reflect.Func { 27 | panic("expects a function") 28 | } 29 | vf := reflect.ValueOf(f) 30 | wrapperF := reflect.MakeFunc(rf, func(in []reflect.Value) []reflect.Value { 31 | start := time.Now() 32 | out := vf.Call(in) 33 | end := time.Now() 34 | fmt.Printf("Calling %s took %v \n", runtime.FuncForPC(vf.Pointer()).Name(), end.Sub(start)) 35 | return out 36 | }) 37 | return wrapperF.Interface() 38 | } 39 | 40 | func properTitle(input string) string { 41 | // from: https://golangcookbook.com/chapters/strings/title/ 42 | words := strings.Fields(input) 43 | smallwords := " a an on the to " 44 | 45 | for index, word := range words { 46 | if strings.Contains(smallwords, " "+word+" ") { 47 | words[index] = word 48 | } else { 49 | words[index] = strings.Title(word) 50 | } 51 | } 52 | return strings.Join(words, " ") 53 | } 54 | 55 | func doubleOurNumber(a int) int { 56 | 57 | time.Sleep(1 * time.Second) 58 | return a * 2 59 | } 60 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/handlers/03_dispatch_handler_test.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "bytes" 5 | "golang-fifa-world-cup-web-service/data" 6 | "net/http" 7 | "net/http/httptest" 8 | "testing" 9 | ) 10 | 11 | func TestCorrectHTTPGetMethodDispatch(t *testing.T) { 12 | setup() 13 | 14 | req, _ := http.NewRequest("GET", "/winners", nil) 15 | 16 | rr := httptest.NewRecorder() 17 | handler := http.HandlerFunc(WinnersHandler) 18 | handler.ServeHTTP(rr, req) 19 | 20 | if body := rr.Body.String(); body == "" { 21 | t.Error("Did not properly dispatch HTTP GET") 22 | } 23 | } 24 | 25 | func TestCorrectHTTPPostMethodDispatch(t *testing.T) { 26 | setup() 27 | 28 | var jsonStr = []byte(`{"country":"Croatia", "year": 2030}`) 29 | req, _ := http.NewRequest("POST", "/winners", bytes.NewBuffer(jsonStr)) 30 | req.Header.Set("Content-Type", "application/json") 31 | req.Header.Set("X-ACCESS-TOKEN", data.AccessToken) 32 | 33 | rr := httptest.NewRecorder() 34 | handler := http.HandlerFunc(WinnersHandler) 35 | handler.ServeHTTP(rr, req) 36 | 37 | if status := rr.Code; status != http.StatusCreated { 38 | t.Error("Did not properly dispatch HTTP POST", status) 39 | } 40 | } 41 | 42 | func TestCorrectHTTPUnsupportedMethodDispatch(t *testing.T) { 43 | setup() 44 | 45 | req, _ := http.NewRequest("PUT", "/winners", nil) 46 | 47 | rr := httptest.NewRecorder() 48 | handler := http.HandlerFunc(WinnersHandler) 49 | handler.ServeHTTP(rr, req) 50 | 51 | if status := rr.Code; status != http.StatusMethodNotAllowed { 52 | t.Error("Did not properly catch unsupported HTTP methods", status) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ginframeworkdemo/vacationtracker/employee/data.go: -------------------------------------------------------------------------------- 1 | package employee 2 | 3 | import "time" 4 | 5 | var employees = []Employee{ 6 | { 7 | ID: 962134, 8 | FirstName: "Jennifer", 9 | LastName: "Wat", 10 | Position: "CEO", 11 | StartDate: time.Now().Add(-13 * time.Hour * 24 * 365), 12 | Status: "Active", 13 | TotalPTO: 30, 14 | TimeOff: []TimeOff{ 15 | { 16 | Type: TimeoffTypeHoliday, 17 | Amount: 8., 18 | StartDate: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC), 19 | Status: TimeoffStatusTaken, 20 | }, { 21 | Type: TimeoffTypePTO, 22 | Amount: 16., 23 | StartDate: time.Date(2023, 8, 16, 0, 0, 0, 0, time.UTC), 24 | Status: TimeoffStatusScheduled, 25 | }, { 26 | Type: TimeoffTypePTO, 27 | Amount: 16., 28 | StartDate: time.Date(2023, 12, 8, 0, 0, 0, 0, time.UTC), 29 | Status: TimeoffStatusRequested, 30 | }, 31 | }, 32 | }, 33 | { 34 | ID: 176158, 35 | FirstName: "Allison", 36 | LastName: "Jane", 37 | Position: "COO", 38 | StartDate: time.Now().Add(-4 * time.Hour * 24 * 365), 39 | Status: "Active", 40 | TotalPTO: 20, 41 | TimeOff: nil, 42 | }, 43 | { 44 | ID: 160898, 45 | FirstName: "Aakar", 46 | LastName: "Uppal", 47 | Position: "CTO", 48 | StartDate: time.Now().Add(-6 * time.Hour * 24 * 365), 49 | TotalPTO: 20, 50 | TimeOff: nil, 51 | }, 52 | { 53 | ID: 297365, 54 | FirstName: "Jonathon", 55 | LastName: "Anderson", 56 | Position: "Worker Bee", 57 | StartDate: time.Now().Add(-12 * time.Hour * 24 * 365), 58 | TotalPTO: 30, 59 | TimeOff: nil, 60 | }, 61 | } 62 | -------------------------------------------------------------------------------- /grpcdemo/cert/generate_cert.sh: -------------------------------------------------------------------------------- 1 | #Removing old files. 2 | rm *.pem 3 | rm *.srl 4 | 5 | # 1. Generate CA's private key and self-signed certificate 6 | openssl req -x509 -newkey rsa:4096 -days 365 -nodes -keyout ca-key.pem -out ca-cert.pem -subj "/C=AU/ST=Vic/L=Melbourne/O=Go grpc/OU=Learning/CN=*.grpclearning.test/emailAddress=grpcgo.test@gmail.com" 7 | 8 | echo "CA's self-signed certificate" 9 | openssl x509 -in ca-cert.pem -noout -text 10 | 11 | # 2. Generate web server's private key and certificate signing request (CSR) 12 | openssl req -newkey rsa:4096 -nodes -keyout server-key.pem -out server-req.pem -subj "/C=AU/ST=Vic/L=Melbourne/O=Go grpc testing/OU=Learning/CN=*.gogrpcserver.com/emailAddress=grpcgoserver.test@gmail.com" 13 | 14 | # 3. Use CA's private key to sign web server's CSR and get back the signed certificate 15 | openssl x509 -req -in server-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile server-ext.cnf 16 | 17 | echo "Server's signed certificate" 18 | openssl x509 -in server-cert.pem -noout -text 19 | 20 | # 4. Generate client's private key and certificate signing request (CSR) 21 | openssl req -newkey rsa:4096 -nodes -keyout client-key.pem -out client-req.pem -subj "/C=AU/ST=Vic/L=Melbourne/O=Go grpc testing/OU=Learning/CN=*.gogrpcclient.com/emailAddress=grpcgoclient.test@gmail.com" 22 | 23 | # 5. Use CA's private key to sign client's CSR and get back the signed certificate 24 | openssl x509 -req -in client-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile client-ext.cnf 25 | 26 | echo "Client's signed certificate" 27 | openssl x509 -in client-cert.pem -noout -text 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/data/validation.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | 7 | "github.com/go-playground/validator/v10" 8 | ) 9 | 10 | type ValidationError struct { 11 | validator.FieldError 12 | } 13 | 14 | func (v ValidationError) Error() string { 15 | return fmt.Sprintf( 16 | "Key: '%s' Error: Field validation for '%s' failed on the '%s' tag", 17 | v.Namespace(), 18 | v.Field(), 19 | v.Tag(), 20 | ) 21 | } 22 | 23 | type ValidationErrors []ValidationError 24 | 25 | func (v ValidationErrors) Errors() []string { 26 | errs := []string{} 27 | for _, err := range v { 28 | errs = append(errs, err.Error()) 29 | } 30 | return errs 31 | } 32 | 33 | type Validation struct { 34 | validate *validator.Validate 35 | } 36 | 37 | func NewValidation() *Validation { 38 | validate := validator.New() 39 | validate.RegisterValidation("sku", validateSKU) 40 | return &Validation{validate} 41 | } 42 | 43 | func (v *Validation) Validate(i interface{}) ValidationErrors { 44 | //fmt.Println(i) 45 | errs, ok := v.validate.Struct(i).(validator.ValidationErrors) 46 | //fmt.Println(errs) 47 | //fmt.Println(ok) 48 | if !ok || errs == nil || len(errs) == 0 { 49 | return nil 50 | } 51 | 52 | var returnErrs []ValidationError 53 | 54 | for _, err := range errs { 55 | ve := ValidationError{err} 56 | returnErrs = append(returnErrs, ve) 57 | } 58 | //fmt.Println(returnErrs) 59 | return returnErrs 60 | } 61 | 62 | func validateSKU(fl validator.FieldLevel) bool { 63 | // sku example abhb-sdd-sdscc 64 | re := regexp.MustCompile(`[a-z]+-[a-z]+-[a-z]+`) 65 | matches := re.FindAllString(fl.Field().String(), -1) 66 | return len(matches) == 1 67 | 68 | } 69 | -------------------------------------------------------------------------------- /ginframeworkdemo/responsedemo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "log" 6 | "net/http" 7 | "os" 8 | 9 | "github.com/gin-gonic/gin" 10 | ) 11 | 12 | func main() { 13 | router := gin.Default() 14 | 15 | router.StaticFile("/", "index.html") 16 | 17 | router.GET("/tale_of_two_cities", func(ctx *gin.Context) { 18 | // Simple File Serving 19 | //ctx.File("a_tale_of_two_cities.txt") 20 | 21 | // Data way of sharing 22 | f, err := os.Open("a_tale_of_two_cities.txt") 23 | if err != nil { 24 | ctx.AbortWithError(http.StatusInternalServerError, err) 25 | } 26 | defer f.Close() 27 | // IO Reader way 28 | /* data, err := io.ReadAll(f) 29 | if err != nil { 30 | ctx.AbortWithError(http.StatusInternalServerError, err) 31 | } 32 | ctx.Data(http.StatusOK, "test/plain", data) */ 33 | ///Stream way of handling 34 | ctx.Stream(streamer(f)) 35 | }) 36 | 37 | router.GET("/great_expectations", func(ctx *gin.Context) { 38 | f, err := os.Open("great_expectations.txt") 39 | if err != nil { 40 | ctx.AbortWithError(http.StatusInternalServerError, err) 41 | } 42 | defer f.Close() 43 | fi, err := f.Stat() 44 | if err != nil { 45 | ctx.AbortWithError(http.StatusInternalServerError, err) 46 | } 47 | ctx.DataFromReader(http.StatusOK, fi.Size(), "text/plain", f, map[string]string{ 48 | "Content-Disposition": "attachment;filename=great_expectations.txt", 49 | }) 50 | }) 51 | 52 | log.Fatal(router.Run(":3000")) 53 | 54 | } 55 | 56 | func streamer(r io.Reader) func(io.Writer) bool { 57 | return func(step io.Writer) bool { 58 | for { 59 | buf := make([]byte, 4*2^10) 60 | if _, err := r.Read(buf); err == nil { 61 | _, err := step.Write(buf) 62 | return err == nil 63 | } else { 64 | return false 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /gostandard_libs/custom_type/media/media.go: -------------------------------------------------------------------------------- 1 | package media 2 | 3 | import "strings" 4 | 5 | /* This exportable. 6 | type Movie struct { 7 | Title string 8 | Rating Rating 9 | BoxOffice float32 10 | } */ 11 | 12 | type Catalogable interface { 13 | NewMovie(title string, rating Rating, boxOffice float32) 14 | GetTitle() string 15 | GetRating() string 16 | GetBoxOffice() float32 17 | SetTitle(newTitle string) 18 | SetRating(newRating Rating) 19 | SetBoxOffice(newBoxOffice float32) 20 | } 21 | 22 | type Movie struct { 23 | title string 24 | rating Rating 25 | boxOffice float32 26 | } 27 | 28 | type Rating string 29 | 30 | const ( 31 | R = "R (Restricted)" 32 | G = "G (General audiences)" 33 | PG = "PG (Parental Guidance)" 34 | PG13 = "PG-13 (Parental Caution)" 35 | NC17 = "NC-17 (No children under 17)" 36 | ) 37 | 38 | /* 39 | func NewMovie(title string, rating Rating, boxOffice float32) Movie { 40 | return Movie{ 41 | title: title, 42 | rating: rating, 43 | boxOffice: boxOffice, 44 | } 45 | } */ 46 | // Dont want to return a copy of moview instead use same copy. 47 | func (m *Movie) NewMovie(title string, rating Rating, boxOffice float32) { 48 | m.title = title 49 | m.rating = rating 50 | m.boxOffice = boxOffice 51 | } 52 | 53 | func (m *Movie) GetTitle() string { 54 | return strings.ToTitle(m.title) 55 | } 56 | 57 | func (m *Movie) GetRating() string { 58 | return string(m.rating) 59 | } 60 | 61 | func (m *Movie) GetBoxOffice() float32 { 62 | return m.boxOffice 63 | } 64 | 65 | func (m *Movie) SetTitle(newTitle string) { 66 | m.title = newTitle 67 | } 68 | 69 | func (m *Movie) SetRating(newRating Rating) { 70 | m.rating = newRating 71 | } 72 | 73 | func (m *Movie) SetBoxOffice(newBoxOffice float32) { 74 | m.boxOffice = newBoxOffice 75 | } 76 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/handlers/handlers.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "golang-fifa-world-cup-web-service/data" 5 | "net/http" 6 | ) 7 | 8 | // RootHandler returns an empty body status code 9 | func RootHandler(res http.ResponseWriter, req *http.Request) { 10 | res.WriteHeader(http.StatusNoContent) 11 | } 12 | 13 | // ListWinners returns winners from the list 14 | func ListWinners(res http.ResponseWriter, req *http.Request) { 15 | res.Header().Set("Content-Type", "application/json") 16 | year := req.URL.Query().Get("year") 17 | if year == "" { 18 | winners, err := data.ListAllJSON() 19 | if err != nil { 20 | res.WriteHeader(http.StatusInternalServerError) 21 | return 22 | } 23 | res.Write(winners) 24 | } else { 25 | filteredWinners, err := data.ListAllByYear(year) 26 | if err != nil { 27 | res.WriteHeader(http.StatusBadRequest) 28 | return 29 | } 30 | res.Write(filteredWinners) 31 | } 32 | 33 | } 34 | 35 | // AddNewWinner adds new winner to the list 36 | func AddNewWinner(res http.ResponseWriter, req *http.Request) { 37 | accessToken := req.Header.Get("X-ACCESS-TOKEN") 38 | isTokenValid := data.IsAccessTokenValid(accessToken) 39 | if !isTokenValid { 40 | res.WriteHeader(http.StatusUnauthorized) 41 | } else { 42 | err := data.AddNewWinner(req.Body) 43 | if err != nil { 44 | res.WriteHeader(http.StatusUnprocessableEntity) 45 | return 46 | } 47 | res.WriteHeader(http.StatusCreated) 48 | } 49 | } 50 | 51 | // WinnersHandler is the dispatcher for all /winners URL 52 | func WinnersHandler(res http.ResponseWriter, req *http.Request) { 53 | switch req.Method { 54 | case http.MethodGet: 55 | ListWinners(res, req) 56 | case http.MethodPost: 57 | AddNewWinner(res, req) 58 | default: 59 | res.WriteHeader(http.StatusMethodNotAllowed) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /microservices/product-api-gorilla/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | "os" 8 | "os/signal" 9 | "syscall" 10 | "time" 11 | 12 | "github.com/erankitcs/golang_learning/microservices/product-api-gorilla/handlers" 13 | "github.com/gorilla/mux" 14 | ) 15 | 16 | var bindAddress = ":9090" 17 | 18 | func main() { 19 | //Create a logger 20 | l := log.New(os.Stdout, "product-api ", log.LstdFlags) 21 | // New Product handler 22 | ph := handlers.NewProduct(l) 23 | 24 | sm := mux.NewRouter() 25 | 26 | getRouter := sm.Methods(http.MethodGet).Subrouter() 27 | getRouter.HandleFunc("/", ph.GetProducts) 28 | 29 | putRouter := sm.Methods(http.MethodPut).Subrouter() 30 | putRouter.HandleFunc("/{id:[0-9]+}", ph.UpdateProduct) 31 | putRouter.Use(ph.MiddlewareProductsValidation) 32 | 33 | postRouter := sm.Methods(http.MethodPost).Subrouter() 34 | postRouter.HandleFunc("/", ph.AddProduct) 35 | postRouter.Use(ph.MiddlewareProductsValidation) 36 | 37 | //creating new server 38 | s := http.Server{ 39 | Addr: bindAddress, 40 | Handler: sm, 41 | ErrorLog: l, 42 | ReadTimeout: 5 * time.Second, 43 | WriteTimeout: 10 * time.Second, 44 | IdleTimeout: 120 * time.Second, 45 | } 46 | 47 | //Starting the server 48 | go func() { 49 | l.Printf("Starting Server on Port %s\n", bindAddress) 50 | err := s.ListenAndServe() 51 | if err != nil { 52 | l.Printf("Error in starting the server: %s\n", err) 53 | os.Exit(1) 54 | } 55 | }() 56 | 57 | //Gracefull shutdown 58 | c := make(chan os.Signal, 1) 59 | signal.Notify(c, os.Interrupt) 60 | signal.Notify(c, syscall.SIGTERM) 61 | 62 | //block util a signal recieved 63 | sig := <-c 64 | log.Println("Got Signal: ", sig) 65 | ctx, cancelFun := context.WithTimeout(context.Background(), 30*time.Second) 66 | cancelFun() 67 | s.Shutdown(ctx) 68 | 69 | } 70 | -------------------------------------------------------------------------------- /golang-async-logging-library/cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "alog" 5 | "bufio" 6 | "flag" 7 | "fmt" 8 | "io" 9 | "log" 10 | "os" 11 | "strings" 12 | ) 13 | 14 | func main() { 15 | out := flag.String("out", "stdout", "File name to use for log output. If stdout is provided, then output is written directly to the console.") 16 | async := flag.Bool("async", false, "This flag determines if the logger should write asynchronously.") 17 | flag.Parse() 18 | 19 | var w io.Writer 20 | var err error 21 | if strings.ToLower(*out) == "stdout" { 22 | w = os.Stdout 23 | } else { 24 | w, err = os.Create(*out) 25 | if err != nil { 26 | log.Fatal("Unable to open log file", err) 27 | } 28 | } 29 | l := alog.New(w) 30 | go l.Start() 31 | 32 | messageChan := l.MessageChannel() 33 | errChan := l.ErrorChannel() 34 | 35 | if errChan != nil { 36 | go func(errChan <-chan error) { 37 | err := <-errChan 38 | l.Stop() 39 | log.Fatalf("Error received from logger: %v\n", err) 40 | }(errChan) 41 | } 42 | 43 | for { 44 | reader := bufio.NewReader(os.Stdin) 45 | 46 | fmt.Println("Please enter message to write to log or 'q' to quit.") 47 | input, err := reader.ReadString('\n') 48 | if err != nil { 49 | fmt.Println("Unable to read input from command line, please try again.", err) 50 | continue 51 | } 52 | 53 | if strings.ToLower(input) == "q\n" || strings.ToLower(input) == "q\r\n" { 54 | if wc, ok := w.(io.Closer); ok { 55 | err := wc.Close() 56 | if err != nil { 57 | fmt.Println("Failed to close log file:", err) 58 | } 59 | } 60 | l.Stop() 61 | break 62 | } 63 | if *async { 64 | if messageChan != nil { 65 | messageChan <- input 66 | } 67 | } else { 68 | _, err = l.Write(input) 69 | if err != nil { 70 | fmt.Println("Unable to write message out to log") 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger-client/client/products/delete_product_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package products 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/go-openapi/runtime" 12 | "github.com/go-openapi/strfmt" 13 | ) 14 | 15 | // DeleteProductReader is a Reader for the DeleteProduct structure. 16 | type DeleteProductReader struct { 17 | formats strfmt.Registry 18 | } 19 | 20 | // ReadResponse reads a server response into the received o. 21 | func (o *DeleteProductReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 22 | switch response.Code() { 23 | case 201: 24 | result := NewDeleteProductCreated() 25 | if err := result.readResponse(response, consumer, o.formats); err != nil { 26 | return nil, err 27 | } 28 | return result, nil 29 | default: 30 | return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) 31 | } 32 | } 33 | 34 | // NewDeleteProductCreated creates a DeleteProductCreated with default headers values 35 | func NewDeleteProductCreated() *DeleteProductCreated { 36 | return &DeleteProductCreated{} 37 | } 38 | 39 | /* DeleteProductCreated describes a response with status code 201, with default header values. 40 | 41 | No content is returned by this API endpoint 42 | */ 43 | type DeleteProductCreated struct { 44 | } 45 | 46 | func (o *DeleteProductCreated) Error() string { 47 | return fmt.Sprintf("[DELETE /products/{id}][%d] deleteProductCreated ", 201) 48 | } 49 | 50 | func (o *DeleteProductCreated) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 51 | 52 | return nil 53 | } 54 | -------------------------------------------------------------------------------- /concurrentprogram/books/book.go: -------------------------------------------------------------------------------- 1 | package books 2 | 3 | import "fmt" 4 | 5 | type Book struct { 6 | ID int 7 | Title string 8 | Author string 9 | YearPublished int 10 | } 11 | 12 | func (b *Book) String() string { 13 | return fmt.Sprintf( 14 | "Title:\t\t%q\n"+ 15 | "Author:\t\t%q\n"+ 16 | "Published:\t%v\n", b.Title, b.Author, b.YearPublished) 17 | } 18 | 19 | var MyBook = []Book{ 20 | Book{ 21 | ID: 1, 22 | Title: "The Hitchhiker's Guide to the Galaxy", 23 | Author: "Douglas Adams", 24 | YearPublished: 1979, 25 | }, 26 | Book{ 27 | ID: 2, 28 | Title: "The Hobbit", 29 | Author: "J.R.R. Tolkien", 30 | YearPublished: 1937, 31 | }, 32 | Book{ 33 | ID: 3, 34 | Title: "A Tale of Two Cities", 35 | Author: "Charles Dickens", 36 | YearPublished: 1859, 37 | }, 38 | Book{ 39 | ID: 4, 40 | Title: "Les Misérables", 41 | Author: "Victor Hugo", 42 | YearPublished: 1862, 43 | }, 44 | Book{ 45 | ID: 5, 46 | Title: "Harry Potter and the Philosopher's Stone", 47 | Author: "J.K. Rowling", 48 | YearPublished: 1997, 49 | }, 50 | Book{ 51 | ID: 6, 52 | Title: "I, Robot", 53 | Author: "Isaac Asimov", 54 | YearPublished: 1950, 55 | }, 56 | Book{ 57 | ID: 7, 58 | Title: "The Gods Themselves", 59 | Author: "Isaac Asimov", 60 | YearPublished: 1973, 61 | }, 62 | Book{ 63 | ID: 8, 64 | Title: "The Moon is a Harsh Mistress", 65 | Author: "Robert A. Heinlein", 66 | YearPublished: 1966, 67 | }, 68 | Book{ 69 | ID: 9, 70 | Title: "On Basilisk Station", 71 | Author: "David Weber", 72 | YearPublished: 1993, 73 | }, 74 | Book{ 75 | ID: 10, 76 | Title: "The Android's Dream", 77 | Author: "John Scalzi", 78 | YearPublished: 2006, 79 | }, 80 | } 81 | -------------------------------------------------------------------------------- /testinggolang/messages/message_test.go: -------------------------------------------------------------------------------- 1 | package messages 2 | 3 | import ( 4 | "crypto/sha1" 5 | "crypto/sha256" 6 | "crypto/sha512" 7 | "testing" 8 | ) 9 | 10 | //Start with Test then next letter must be in Capital letter. 11 | // Immediate failure -t.FailNow , Fatal and Fatalf. Fatal will stop the execution of tests 12 | // Non immediate - t.Fail , Error and Errorf 13 | func TestGreet(t *testing.T) { 14 | got := Greet("Ankit") 15 | expect := "Hello, Ankit!" 16 | if got != expect { 17 | t.Errorf("Did not get expected result. Wanted %q got: %q", expect, got) 18 | } 19 | 20 | } 21 | 22 | func TestGreetTableDriven(t *testing.T) { 23 | scenarios := []struct { 24 | input string 25 | expect string 26 | }{ 27 | {input: "Ankit", expect: "Hello, Ankit!"}, 28 | {input: "", expect: "Hello, !"}, 29 | } 30 | 31 | for _, s := range scenarios { 32 | got := Greet(s.input) 33 | if got != s.expect { 34 | t.Errorf("Did not got expected result for input: '%v'. Expected %q and got %q", s.input, got, s.expect) 35 | } 36 | } 37 | 38 | } 39 | 40 | func TestDapart(t *testing.T) { 41 | t.Log("Running Depart Test") 42 | got := depart("Ankit") 43 | expect := "Goodbye, Ankit" 44 | if got != expect { 45 | t.Errorf("Did not get expected result. Wanted %q got: %q", expect, got) 46 | } 47 | } 48 | 49 | func BenchmarkSHA1(b *testing.B) { 50 | data := []byte("My Benchmark testing..") 51 | b.StartTimer() 52 | for i := 0; i < b.N; i++ { 53 | sha1.Sum(data) 54 | } 55 | } 56 | 57 | func BenchmarkSHA256(b *testing.B) { 58 | data := []byte("My Benchmark testing..") 59 | b.StartTimer() 60 | for i := 0; i < b.N; i++ { 61 | sha256.Sum256(data) 62 | } 63 | } 64 | 65 | func BenchmarkSHA512(b *testing.B) { 66 | data := []byte("My Benchmark testing..") 67 | b.StartTimer() 68 | for i := 0; i < b.N; i++ { 69 | sha512.Sum512(data) 70 | } 71 | } 72 | 73 | func BenchmarkSHA512Alloc(b *testing.B) { 74 | data := []byte("My Benchmark testing..") 75 | b.StartTimer() 76 | for i := 0; i < b.N; i++ { 77 | h := sha512.New() 78 | h.Sum(data) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erankitcs/golang_learning/microservices/product-api-withswagger 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/go-openapi/runtime v0.24.1 7 | github.com/go-playground/validator/v10 v10.11.0 8 | github.com/gorilla/handlers v1.5.1 9 | github.com/gorilla/mux v1.8.0 10 | github.com/stretchr/testify v1.8.0 11 | ) 12 | 13 | require ( 14 | github.com/PuerkitoBio/purell v1.1.1 // indirect 15 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 16 | github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect 17 | github.com/davecgh/go-spew v1.1.1 // indirect 18 | github.com/felixge/httpsnoop v1.0.1 // indirect 19 | github.com/go-openapi/analysis v0.21.2 // indirect 20 | github.com/go-openapi/errors v0.20.2 // indirect 21 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 22 | github.com/go-openapi/jsonreference v0.19.6 // indirect 23 | github.com/go-openapi/loads v0.21.1 // indirect 24 | github.com/go-openapi/spec v0.20.4 // indirect 25 | github.com/go-openapi/strfmt v0.21.2 // indirect 26 | github.com/go-openapi/swag v0.21.1 // indirect 27 | github.com/go-openapi/validate v0.21.0 // indirect 28 | github.com/go-playground/locales v0.14.0 // indirect 29 | github.com/go-playground/universal-translator v0.18.0 // indirect 30 | github.com/go-stack/stack v1.8.1 // indirect 31 | github.com/josharian/intern v1.0.0 // indirect 32 | github.com/leodido/go-urn v1.2.1 // indirect 33 | github.com/mailru/easyjson v0.7.7 // indirect 34 | github.com/mitchellh/mapstructure v1.4.3 // indirect 35 | github.com/oklog/ulid v1.3.1 // indirect 36 | github.com/pmezard/go-difflib v1.0.0 // indirect 37 | go.mongodb.org/mongo-driver v1.8.3 // indirect 38 | golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect 39 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect 40 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect 41 | golang.org/x/text v0.3.7 // indirect 42 | gopkg.in/yaml.v2 v2.4.0 // indirect 43 | gopkg.in/yaml.v3 v3.0.1 // indirect 44 | ) 45 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/handlers/docs.go: -------------------------------------------------------------------------------- 1 | // Package Product API. 2 | // 3 | // The purpose of this API is to provide list of products, add new product and update the existing product. 4 | // Schemes: http 5 | // Host: localhost 6 | // BasePath: / 7 | // Version: 0.0.1 8 | // License: MIT http://opensource.org/licenses/MIT 9 | // Contact: er.ankit.cs@gmail.com 10 | // Consumes: 11 | // - application/json 12 | // 13 | // Produces: 14 | // - application/json 15 | // swagger:meta 16 | package handlers 17 | 18 | import "github.com/erankitcs/golang_learning/microservices/product-api-withswagger/data" 19 | 20 | // Generic error message returned as a string 21 | // swagger:response errorResponse 22 | type errorResponseWrapper struct { 23 | // Description of the error 24 | // in: body 25 | Body GenericError 26 | } 27 | 28 | // Validation error message returned as a string 29 | // swagger:response errorValidation 30 | type errorValidationWrapper struct { 31 | // Description of the error 32 | // in: body 33 | Body GenericError 34 | } 35 | 36 | // A list of product return into the response 37 | // swagger:response productsResponse 38 | type productsResponseWrapper struct { 39 | // All products in the system 40 | // in:body 41 | Body []data.Product 42 | } 43 | 44 | // Data structure representing a single product 45 | // swagger:response productResponse 46 | type productResponseWrapper struct { 47 | // Newly created product 48 | // in: body 49 | Body data.Product 50 | } 51 | 52 | // No content is returned by this API endpoint 53 | // swagger:response noContentResponse 54 | type noContentResponseWrapper struct { 55 | } 56 | 57 | // swagger:parameters deleteProduct listSingleProduct 58 | type productIDParamsWrapper struct { 59 | // The id of the product for which the operation relates 60 | // in: path 61 | // required: true 62 | ID int `json:"id"` 63 | } 64 | 65 | // swagger:parameters updateProduct createProduct 66 | type productParamsWrapper struct { 67 | // The product to be updated. 68 | // in: body 69 | // required: true 70 | Body data.Product 71 | } 72 | -------------------------------------------------------------------------------- /distributedapp/teacherportal/student.gohtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Student 7 | 8 | 9 |

10 | Grade Book 11 | - {{.LastName}}, {{.FirstName}}

12 | 13 | {{if gt (len .Grades) 0}} 14 | 15 | 16 | 17 | 18 | 19 | 20 | {{range .Grades}} 21 | 22 | 23 | 24 | 25 | 26 | {{end}} 27 |
TitleTypeScore
{{.Title}}{{.Type}}{{.Score}}
28 | {{else}} 29 | No grades available 30 | {{end}} 31 | 32 |
33 | Add a Grade 34 |
35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 51 | 52 | 53 | 54 | 57 | 58 |
Title 39 | 40 |
Type 45 | 50 |
Score 55 | 56 |
59 | 60 |
61 |
62 | 63 | 64 | -------------------------------------------------------------------------------- /distributedappdocker/teacherportal/student.gohtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Student 7 | 8 | 9 |

10 | Grade Book 11 | - {{.LastName}}, {{.FirstName}}

12 | 13 | {{if gt (len .Grades) 0}} 14 | 15 | 16 | 17 | 18 | 19 | 20 | {{range .Grades}} 21 | 22 | 23 | 24 | 25 | 26 | {{end}} 27 |
TitleTypeScore
{{.Title}}{{.Type}}{{.Score}}
28 | {{else}} 29 | No grades available 30 | {{end}} 31 | 32 |
33 | Add a Grade 34 |
35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 51 | 52 | 53 | 54 | 57 | 58 |
Title 39 | 40 |
Type 45 | 50 |
Score 55 | 56 |
59 | 60 |
61 |
62 | 63 | 64 | -------------------------------------------------------------------------------- /microservices/product-api/data/products.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "time" 8 | ) 9 | 10 | type Product struct { 11 | ID int `json:"id"` 12 | Name string `json:"name"` 13 | Description string `json:"description"` 14 | Price float32 `json:"price"` 15 | SKU string `json:"sku"` 16 | CreatedOn string `json:"-"` 17 | UpdatedOn string `json:"-"` 18 | DeletedOn string `json:"-"` 19 | } 20 | 21 | //Collection of product 22 | type Products []*Product 23 | 24 | func (p *Products) ToJSON(w io.Writer) error { 25 | e := json.NewEncoder(w) 26 | return e.Encode(p) 27 | } 28 | 29 | func (p *Product) FromJSON(r io.Reader) error { 30 | e := json.NewDecoder(r) 31 | return e.Decode(p) 32 | } 33 | 34 | var productList = []*Product{ 35 | { 36 | ID: 1, 37 | Name: "Latte", 38 | Description: "Frothy milky coffee", 39 | Price: 2.45, 40 | SKU: "abc323", 41 | CreatedOn: time.Now().UTC().String(), 42 | UpdatedOn: time.Now().UTC().String(), 43 | }, 44 | { 45 | ID: 2, 46 | Name: "Espresso", 47 | Description: "Short and strong coffee without milk", 48 | Price: 1.99, 49 | SKU: "fjd34", 50 | CreatedOn: time.Now().UTC().String(), 51 | UpdatedOn: time.Now().UTC().String(), 52 | }, 53 | } 54 | 55 | func GetProducts() Products { 56 | return productList 57 | } 58 | 59 | func getNextId() int { 60 | lp := productList[len(productList)-1] 61 | return lp.ID + 1 62 | } 63 | 64 | func AddProduct(p *Product) { 65 | p.ID = getNextId() 66 | productList = append(productList, p) 67 | 68 | } 69 | 70 | func UpdateProduct(id int, p *Product) error { 71 | _, ploc, err := findProduct(id) 72 | if err != nil { 73 | return err 74 | } 75 | p.ID = id 76 | productList[ploc] = p 77 | return nil 78 | } 79 | 80 | var ErrorProductNotFound = fmt.Errorf("Product not found") 81 | 82 | func findProduct(id int) (*Product, int, error) { 83 | for l, p := range productList { 84 | if p.ID == id { 85 | return p, l, nil 86 | } 87 | } 88 | return nil, -1, ErrorProductNotFound 89 | } 90 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger-client/client/products/list_products_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package products 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | "github.com/go-openapi/strfmt" 14 | 15 | "github.com/erankitcs/golang_learning/microservices/productapiclient/models" 16 | ) 17 | 18 | // ListProductsReader is a Reader for the ListProducts structure. 19 | type ListProductsReader struct { 20 | formats strfmt.Registry 21 | } 22 | 23 | // ReadResponse reads a server response into the received o. 24 | func (o *ListProductsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 25 | switch response.Code() { 26 | case 200: 27 | result := NewListProductsOK() 28 | if err := result.readResponse(response, consumer, o.formats); err != nil { 29 | return nil, err 30 | } 31 | return result, nil 32 | default: 33 | return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) 34 | } 35 | } 36 | 37 | // NewListProductsOK creates a ListProductsOK with default headers values 38 | func NewListProductsOK() *ListProductsOK { 39 | return &ListProductsOK{} 40 | } 41 | 42 | /* ListProductsOK describes a response with status code 200, with default header values. 43 | 44 | A list of product return into the response 45 | */ 46 | type ListProductsOK struct { 47 | Payload []*models.Product 48 | } 49 | 50 | func (o *ListProductsOK) Error() string { 51 | return fmt.Sprintf("[GET /products][%d] listProductsOK %+v", 200, o.Payload) 52 | } 53 | func (o *ListProductsOK) GetPayload() []*models.Product { 54 | return o.Payload 55 | } 56 | 57 | func (o *ListProductsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 58 | 59 | // response payload 60 | if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { 61 | return err 62 | } 63 | 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger-client/client/products/list_single_product_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package products 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/go-openapi/runtime" 13 | "github.com/go-openapi/strfmt" 14 | 15 | "github.com/erankitcs/golang_learning/microservices/productapiclient/models" 16 | ) 17 | 18 | // ListSingleProductReader is a Reader for the ListSingleProduct structure. 19 | type ListSingleProductReader struct { 20 | formats strfmt.Registry 21 | } 22 | 23 | // ReadResponse reads a server response into the received o. 24 | func (o *ListSingleProductReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { 25 | switch response.Code() { 26 | case 200: 27 | result := NewListSingleProductOK() 28 | if err := result.readResponse(response, consumer, o.formats); err != nil { 29 | return nil, err 30 | } 31 | return result, nil 32 | default: 33 | return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) 34 | } 35 | } 36 | 37 | // NewListSingleProductOK creates a ListSingleProductOK with default headers values 38 | func NewListSingleProductOK() *ListSingleProductOK { 39 | return &ListSingleProductOK{} 40 | } 41 | 42 | /* ListSingleProductOK describes a response with status code 200, with default header values. 43 | 44 | Data structure representing a single product 45 | */ 46 | type ListSingleProductOK struct { 47 | Payload *models.Product 48 | } 49 | 50 | func (o *ListSingleProductOK) Error() string { 51 | return fmt.Sprintf("[GET /products/{id}][%d] listSingleProductOK %+v", 200, o.Payload) 52 | } 53 | func (o *ListSingleProductOK) GetPayload() *models.Product { 54 | return o.Payload 55 | } 56 | 57 | func (o *ListSingleProductOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { 58 | 59 | o.Payload = new(models.Product) 60 | 61 | // response payload 62 | if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { 63 | return err 64 | } 65 | 66 | return nil 67 | } 68 | -------------------------------------------------------------------------------- /microservices/product-api-gorilla/handlers/handlers.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | "strconv" 9 | 10 | "github.com/erankitcs/golang_learning/microservices/product-api-gorilla/data" 11 | "github.com/gorilla/mux" 12 | ) 13 | 14 | type Products struct { 15 | l *log.Logger 16 | } 17 | 18 | func NewProduct(l *log.Logger) *Products { 19 | return &Products{l} 20 | } 21 | 22 | func (p *Products) GetProducts(rw http.ResponseWriter, r *http.Request) { 23 | lp := data.GetProducts() 24 | err := lp.ToJSON(rw) 25 | if err != nil { 26 | http.Error(rw, "Unable to parse product data", http.StatusInternalServerError) 27 | } 28 | } 29 | 30 | func (p *Products) AddProduct(rw http.ResponseWriter, r *http.Request) { 31 | p.l.Printf("Handling PUT request") 32 | prod := r.Context().Value(KeyProduct{}).(data.Product) 33 | data.AddProduct(&prod) 34 | } 35 | 36 | func (p *Products) UpdateProduct(rw http.ResponseWriter, r *http.Request) { 37 | p.l.Println("Handle PUT product") 38 | vars := mux.Vars(r) 39 | id, err := strconv.Atoi(vars["id"]) 40 | if err != nil { 41 | http.Error(rw, "Unxpected Id format", http.StatusBadRequest) 42 | } 43 | prod := r.Context().Value(KeyProduct{}).(data.Product) 44 | 45 | err = data.UpdateProduct(id, &prod) 46 | if err == data.ErrorProductNotFound { 47 | http.Error(rw, "Product not found", http.StatusNotFound) 48 | return 49 | } 50 | 51 | if err != nil { 52 | http.Error(rw, "Product update failed", http.StatusInternalServerError) 53 | return 54 | } 55 | 56 | } 57 | 58 | type KeyProduct struct{} 59 | 60 | func (p Products) MiddlewareProductsValidation(next http.Handler) http.Handler { 61 | return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { 62 | 63 | prod := data.Product{} 64 | 65 | err := prod.FromJSON(r.Body) 66 | if err != nil { 67 | http.Error(rw, "Unable to parse product request", http.StatusBadRequest) 68 | return 69 | } 70 | //validate the product 71 | err = prod.Validate() 72 | if err != nil { 73 | p.l.Println("[ERROR] Validating the product", err) 74 | http.Error(rw, fmt.Sprintf("Error validating the product: %s", err), http.StatusBadRequest) 75 | return 76 | } 77 | ctx := context.WithValue(r.Context(), KeyProduct{}, prod) 78 | r = r.WithContext(ctx) 79 | next.ServeHTTP(rw, r) 80 | }) 81 | } 82 | -------------------------------------------------------------------------------- /customdatatypes/datatypes3/organisation/person.go: -------------------------------------------------------------------------------- 1 | package organisation 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | type TwitterHandler string 10 | 11 | func (th TwitterHandler) RedirectURL() string { 12 | cleanHandler := strings.TrimPrefix(string(th), "@") 13 | return fmt.Sprintf("https://www.twitter.com/%s", cleanHandler) 14 | } 15 | 16 | type Identifiable interface { 17 | ID() string 18 | } 19 | 20 | type Citizen interface { 21 | Identifiable 22 | Country() string 23 | } 24 | 25 | type socialSecurityNumber string 26 | 27 | func NewSocialSecurityNumber(value string) Citizen { 28 | return socialSecurityNumber(value) 29 | } 30 | 31 | func (ssn socialSecurityNumber) ID() string { 32 | return string(ssn) 33 | } 34 | 35 | func (ssn socialSecurityNumber) Country() string { 36 | return "USA" 37 | } 38 | 39 | type europeanUnionIdentifier struct { 40 | id string 41 | country string 42 | } 43 | 44 | func NewEuropeanUnionIdentifier(id, country string) Citizen { 45 | return europeanUnionIdentifier{ 46 | id: id, 47 | country: country, 48 | } 49 | } 50 | 51 | func (eui europeanUnionIdentifier) ID() string { 52 | return eui.id 53 | } 54 | 55 | func (eui europeanUnionIdentifier) Country() string { 56 | return eui.country 57 | } 58 | 59 | type Name struct { 60 | First string 61 | Last string 62 | } 63 | 64 | func (n *Name) FullName() string { 65 | return fmt.Sprintf("%s %s", n.First, n.Last) 66 | } 67 | 68 | type Employee struct { 69 | Name 70 | } 71 | 72 | type Person struct { 73 | Name 74 | First string 75 | Last string 76 | twitterHandler TwitterHandler 77 | Citizen 78 | } 79 | 80 | func NewPerson(firstName, lastName string, citizen Citizen) Person { 81 | return Person{ 82 | Name: Name{ 83 | First: firstName, 84 | Last: lastName, 85 | }, 86 | Citizen: citizen, 87 | } 88 | } 89 | 90 | func (p *Person) SetTwitterHandler(handler TwitterHandler) error { 91 | if len(handler) == 0 { 92 | p.twitterHandler = handler 93 | } else if !strings.HasPrefix(string(handler), "@") { 94 | return errors.New("twitter handle must start with @ in text") 95 | } 96 | p.twitterHandler = handler 97 | return nil 98 | } 99 | 100 | func (p *Person) ID() string { 101 | return "123" 102 | } 103 | 104 | func (p *Person) TwitterHandler() TwitterHandler { 105 | return p.twitterHandler 106 | } 107 | -------------------------------------------------------------------------------- /customdatatypes/datatypes4/organisation/person.go: -------------------------------------------------------------------------------- 1 | package organisation 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | type TwitterHandler string 10 | 11 | func (th TwitterHandler) RedirectURL() string { 12 | cleanHandler := strings.TrimPrefix(string(th), "@") 13 | return fmt.Sprintf("https://www.twitter.com/%s", cleanHandler) 14 | } 15 | 16 | type Identifiable interface { 17 | ID() string 18 | } 19 | 20 | type Citizen interface { 21 | Identifiable 22 | Country() string 23 | } 24 | 25 | type socialSecurityNumber string 26 | 27 | func NewSocialSecurityNumber(value string) Citizen { 28 | return socialSecurityNumber(value) 29 | } 30 | 31 | func (ssn socialSecurityNumber) ID() string { 32 | return string(ssn) 33 | } 34 | 35 | func (ssn socialSecurityNumber) Country() string { 36 | return "USA" 37 | } 38 | 39 | type europeanUnionIdentifier struct { 40 | id string 41 | country []string 42 | } 43 | 44 | func NewEuropeanUnionIdentifier(id, country string) Citizen { 45 | return europeanUnionIdentifier{ 46 | id: id, 47 | country: []string{country}, 48 | } 49 | } 50 | 51 | func (eui europeanUnionIdentifier) ID() string { 52 | return eui.id 53 | } 54 | 55 | func (eui europeanUnionIdentifier) Country() string { 56 | return fmt.Sprintf("EU: %s", eui.country) 57 | } 58 | 59 | type Name struct { 60 | First string 61 | Last string 62 | } 63 | 64 | func (n *Name) FullName() string { 65 | return fmt.Sprintf("%s %s", n.First, n.Last) 66 | } 67 | 68 | type Employee struct { 69 | Name 70 | } 71 | 72 | type Person struct { 73 | Name 74 | First string 75 | Last string 76 | twitterHandler TwitterHandler 77 | Citizen 78 | } 79 | 80 | func NewPerson(firstName, lastName string, citizen Citizen) Person { 81 | return Person{ 82 | Name: Name{ 83 | First: firstName, 84 | Last: lastName, 85 | }, 86 | Citizen: citizen, 87 | } 88 | } 89 | 90 | func (p *Person) SetTwitterHandler(handler TwitterHandler) error { 91 | if len(handler) == 0 { 92 | p.twitterHandler = handler 93 | } else if !strings.HasPrefix(string(handler), "@") { 94 | return errors.New("twitter handle must start with @ in text") 95 | } 96 | p.twitterHandler = handler 97 | return nil 98 | } 99 | 100 | func (p *Person) ID() string { 101 | return "123" 102 | } 103 | 104 | func (p *Person) TwitterHandler() TwitterHandler { 105 | return p.twitterHandler 106 | } 107 | -------------------------------------------------------------------------------- /distributedapp/grades/mockdata.go: -------------------------------------------------------------------------------- 1 | package grades 2 | 3 | func init() { 4 | students = []Student{ 5 | Student{ 6 | ID: 1, 7 | FirstName: "Averill", 8 | LastName: "Simen", 9 | Grades: []Grade{ 10 | Grade{ 11 | Title: "Quiz 1", 12 | Type: GradeQuiz, 13 | Score: 85, 14 | }, 15 | Grade{ 16 | Title: "Week 1 Homework", 17 | Type: GradeHomework, 18 | Score: 94, 19 | }, 20 | Grade{ 21 | Title: "Quiz 2", 22 | Type: GradeQuiz, 23 | Score: 88, 24 | }, 25 | }, 26 | }, 27 | Student{ 28 | ID: 2, 29 | FirstName: "Marge", 30 | LastName: "Garrard", 31 | Grades: []Grade{ 32 | Grade{ 33 | Title: "Quiz 1", 34 | Type: GradeQuiz, 35 | Score: 100, 36 | }, 37 | Grade{ 38 | Title: "Week 1 Homework", 39 | Type: GradeHomework, 40 | Score: 100, 41 | }, 42 | Grade{ 43 | Title: "Quiz 2", 44 | Type: GradeQuiz, 45 | Score: 88, 46 | }, 47 | }, 48 | }, 49 | Student{ 50 | ID: 3, 51 | FirstName: "Sydnie", 52 | LastName: "Barber", 53 | Grades: []Grade{ 54 | Grade{ 55 | Title: "Quiz 1", 56 | Type: GradeQuiz, 57 | Score: 77, 58 | }, 59 | Grade{ 60 | Title: "Week 1 Homework", 61 | Type: GradeHomework, 62 | Score: 0, 63 | }, 64 | Grade{ 65 | Title: "Quiz 2", 66 | Type: GradeQuiz, 67 | Score: 65, 68 | }, 69 | }, 70 | }, 71 | Student{ 72 | ID: 4, 73 | FirstName: "Louie", 74 | LastName: "Easton", 75 | Grades: []Grade{ 76 | Grade{ 77 | Title: "Quiz 1", 78 | Type: GradeQuiz, 79 | Score: 88, 80 | }, 81 | Grade{ 82 | Title: "Week 1 Homework", 83 | Type: GradeHomework, 84 | Score: 93, 85 | }, 86 | Grade{ 87 | Title: "Quiz 2", 88 | Type: GradeQuiz, 89 | Score: 84, 90 | }, 91 | }, 92 | }, 93 | Student{ 94 | ID: 5, 95 | FirstName: "Kylee", 96 | LastName: "Attwood", 97 | Grades: []Grade{ 98 | Grade{ 99 | Title: "Quiz 1", 100 | Type: GradeQuiz, 101 | Score: 95, 102 | }, 103 | Grade{ 104 | Title: "Week 1 Homework", 105 | Type: GradeHomework, 106 | Score: 100, 107 | }, 108 | Grade{ 109 | Title: "Quiz 2", 110 | Type: GradeQuiz, 111 | Score: 97, 112 | }, 113 | }, 114 | }, 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /distributedappdocker/grades/mockdata.go: -------------------------------------------------------------------------------- 1 | package grades 2 | 3 | func init() { 4 | students = []Student{ 5 | Student{ 6 | ID: 1, 7 | FirstName: "Averill", 8 | LastName: "Simen", 9 | Grades: []Grade{ 10 | Grade{ 11 | Title: "Quiz 1", 12 | Type: GradeQuiz, 13 | Score: 85, 14 | }, 15 | Grade{ 16 | Title: "Week 1 Homework", 17 | Type: GradeHomework, 18 | Score: 94, 19 | }, 20 | Grade{ 21 | Title: "Quiz 2", 22 | Type: GradeQuiz, 23 | Score: 88, 24 | }, 25 | }, 26 | }, 27 | Student{ 28 | ID: 2, 29 | FirstName: "Marge", 30 | LastName: "Garrard", 31 | Grades: []Grade{ 32 | Grade{ 33 | Title: "Quiz 1", 34 | Type: GradeQuiz, 35 | Score: 100, 36 | }, 37 | Grade{ 38 | Title: "Week 1 Homework", 39 | Type: GradeHomework, 40 | Score: 100, 41 | }, 42 | Grade{ 43 | Title: "Quiz 2", 44 | Type: GradeQuiz, 45 | Score: 88, 46 | }, 47 | }, 48 | }, 49 | Student{ 50 | ID: 3, 51 | FirstName: "Sydnie", 52 | LastName: "Barber", 53 | Grades: []Grade{ 54 | Grade{ 55 | Title: "Quiz 1", 56 | Type: GradeQuiz, 57 | Score: 77, 58 | }, 59 | Grade{ 60 | Title: "Week 1 Homework", 61 | Type: GradeHomework, 62 | Score: 0, 63 | }, 64 | Grade{ 65 | Title: "Quiz 2", 66 | Type: GradeQuiz, 67 | Score: 65, 68 | }, 69 | }, 70 | }, 71 | Student{ 72 | ID: 4, 73 | FirstName: "Louie", 74 | LastName: "Easton", 75 | Grades: []Grade{ 76 | Grade{ 77 | Title: "Quiz 1", 78 | Type: GradeQuiz, 79 | Score: 88, 80 | }, 81 | Grade{ 82 | Title: "Week 1 Homework", 83 | Type: GradeHomework, 84 | Score: 93, 85 | }, 86 | Grade{ 87 | Title: "Quiz 2", 88 | Type: GradeQuiz, 89 | Score: 84, 90 | }, 91 | }, 92 | }, 93 | Student{ 94 | ID: 5, 95 | FirstName: "Kylee", 96 | LastName: "Attwood", 97 | Grades: []Grade{ 98 | Grade{ 99 | Title: "Quiz 1", 100 | Type: GradeQuiz, 101 | Score: 95, 102 | }, 103 | Grade{ 104 | Title: "Week 1 Homework", 105 | Type: GradeHomework, 106 | Score: 100, 107 | }, 108 | Grade{ 109 | Title: "Quiz 2", 110 | Type: GradeQuiz, 111 | Score: 97, 112 | }, 113 | }, 114 | }, 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-personal-budget-cli/module2/budget_2.go: -------------------------------------------------------------------------------- 1 | package module2 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | ) 7 | 8 | // START Initial code 9 | 10 | // Budget stores Budget information 11 | type Budget struct { 12 | Max float32 13 | Items []Item 14 | } 15 | 16 | // Item stores Item information 17 | type Item struct { 18 | Description string 19 | Price float32 20 | } 21 | 22 | var report map[time.Month]*Budget 23 | 24 | // InitializeReport creates an empty map 25 | // to store each budget 26 | func InitializeReport() { 27 | report = make(map[time.Month]*Budget) 28 | } 29 | 30 | func init() { 31 | InitializeReport() 32 | } 33 | 34 | // CurrentCost returns how much we've added 35 | // to the current budget 36 | func (b Budget) CurrentCost() float32 { 37 | var sum float32 38 | for _, item := range b.Items { 39 | sum += item.Price 40 | } 41 | return sum 42 | } 43 | 44 | var errDoesNotFitBudget = errors.New("Item does not fit the budget") 45 | 46 | var errReportIsFull = errors.New("Report is full") 47 | 48 | var errDuplicateEntry = errors.New("Cannot add duplicate entry") 49 | 50 | // END Initial code 51 | 52 | // START Project code 53 | 54 | // AddItem adds an item to the current budget 55 | func (b *Budget) AddItem(description string, price float32) error { 56 | if b.CurrentCost()+price > b.Max { 57 | return errDoesNotFitBudget 58 | } 59 | 60 | newItem := Item{ 61 | Description: description, 62 | Price: price, 63 | } 64 | b.Items = append(b.Items, newItem) 65 | 66 | return nil 67 | } 68 | 69 | // RemoveItem removes a given item from the current budget 70 | func (b *Budget) RemoveItem(description string) { 71 | for i := range b.Items { 72 | if b.Items[i].Description == description { 73 | b.Items = append(b.Items[:i], b.Items[i+1:]...) 74 | break 75 | } 76 | } 77 | } 78 | 79 | // CreateBudget creates a new budget with a specified max 80 | func CreateBudget(month time.Month, max float32) (*Budget, error) { 81 | var newBudget *Budget 82 | if len(report) >= 12 { 83 | return nil, errReportIsFull 84 | } 85 | if _, hasEntry := report[month]; hasEntry { 86 | return nil, errDuplicateEntry 87 | } 88 | newBudget = &Budget{ 89 | Max: max, 90 | } 91 | report[month] = newBudget 92 | 93 | return newBudget, nil 94 | } 95 | 96 | // GetBudget returns budget for given month 97 | func GetBudget(month time.Month) *Budget { 98 | if budget, ok := report[month]; ok { 99 | return budget 100 | } 101 | return nil 102 | } 103 | 104 | // END Project code 105 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | "os" 8 | "os/signal" 9 | "syscall" 10 | "time" 11 | 12 | "github.com/erankitcs/golang_learning/microservices/product-api-withswagger/data" 13 | "github.com/erankitcs/golang_learning/microservices/product-api-withswagger/handlers" 14 | "github.com/go-openapi/runtime/middleware" 15 | gohandlers "github.com/gorilla/handlers" 16 | "github.com/gorilla/mux" 17 | ) 18 | 19 | var bindAddress = ":9090" 20 | 21 | func main() { 22 | //Create a logger 23 | l := log.New(os.Stdout, "product-api ", log.LstdFlags) 24 | v := data.NewValidation() 25 | // New Product handler 26 | ph := handlers.NewProduct(l, v) 27 | 28 | // create a new serve mux and register the handlers 29 | sm := mux.NewRouter() 30 | 31 | getRouter := sm.Methods(http.MethodGet).Subrouter() 32 | getRouter.HandleFunc("/products", ph.ListAll) 33 | getRouter.HandleFunc("/products/{id:[0-9]+}", ph.ListSingle) 34 | 35 | putRouter := sm.Methods(http.MethodPut).Subrouter() 36 | putRouter.HandleFunc("/products", ph.Update) 37 | putRouter.Use(ph.MiddlewareProductsValidation) 38 | 39 | postRouter := sm.Methods(http.MethodPost).Subrouter() 40 | postRouter.HandleFunc("/products", ph.Create) 41 | postRouter.Use(ph.MiddlewareProductsValidation) 42 | 43 | deleteRouter := sm.Methods(http.MethodDelete).Subrouter() 44 | deleteRouter.HandleFunc("/products/{id:[0-9]+}", ph.Delete) 45 | 46 | ops := middleware.RedocOpts{SpecURL: "/swagger.yaml"} 47 | sh := middleware.Redoc(ops, nil) 48 | getRouter.Handle("/docs", sh) 49 | getRouter.Handle("/swagger.yaml", http.FileServer(http.Dir("./"))) 50 | 51 | ch := gohandlers.CORS(gohandlers.AllowedOrigins([]string{"http://localhost:3000"})) 52 | //creating new server 53 | s := http.Server{ 54 | Addr: bindAddress, 55 | Handler: ch(sm), 56 | ErrorLog: l, 57 | ReadTimeout: 5 * time.Second, 58 | WriteTimeout: 10 * time.Second, 59 | IdleTimeout: 120 * time.Second, 60 | } 61 | 62 | //Starting the server 63 | go func() { 64 | l.Printf("Starting Server on Port %s\n", bindAddress) 65 | err := s.ListenAndServe() 66 | if err != nil { 67 | l.Printf("Error in starting the server: %s\n", err) 68 | os.Exit(1) 69 | } 70 | }() 71 | 72 | //Gracefull shutdown 73 | c := make(chan os.Signal, 1) 74 | signal.Notify(c, os.Interrupt) 75 | signal.Notify(c, syscall.SIGTERM) 76 | 77 | //block util a signal recieved 78 | sig := <-c 79 | log.Println("Got Signal: ", sig) 80 | ctx, cancelFun := context.WithTimeout(context.Background(), 30*time.Second) 81 | cancelFun() 82 | s.Shutdown(ctx) 83 | 84 | } 85 | -------------------------------------------------------------------------------- /microservices/product-api-gorilla/data/products.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "regexp" 8 | "time" 9 | 10 | "github.com/go-playground/validator/v10" 11 | ) 12 | 13 | type Product struct { 14 | ID int `json:"id"` 15 | Name string `json:"name" validate:"required"` 16 | Description string `json:"description"` 17 | Price float32 `json:"price" validate:"gt=0"` 18 | SKU string `json:"sku" validate:"required,sku"` 19 | CreatedOn string `json:"-"` 20 | UpdatedOn string `json:"-"` 21 | DeletedOn string `json:"-"` 22 | } 23 | 24 | //Collection of product 25 | type Products []*Product 26 | 27 | func (p *Product) Validate() error { 28 | validate := validator.New() 29 | validate.RegisterValidation("sku", validateSKU) 30 | return validate.Struct(p) 31 | } 32 | 33 | func validateSKU(fl validator.FieldLevel) bool { 34 | // sku example abhb-sdd-sdscc 35 | re := regexp.MustCompile(`[a-z]+-[a-z]+-[a-z]+`) 36 | matches := re.FindAllString(fl.Field().String(), -1) 37 | return len(matches) == 1 38 | 39 | } 40 | 41 | func (p *Products) ToJSON(w io.Writer) error { 42 | e := json.NewEncoder(w) 43 | return e.Encode(p) 44 | } 45 | 46 | func (p *Product) FromJSON(r io.Reader) error { 47 | e := json.NewDecoder(r) 48 | return e.Decode(p) 49 | } 50 | 51 | var productList = []*Product{ 52 | { 53 | ID: 1, 54 | Name: "Latte", 55 | Description: "Frothy milky coffee", 56 | Price: 2.45, 57 | SKU: "abc323", 58 | CreatedOn: time.Now().UTC().String(), 59 | UpdatedOn: time.Now().UTC().String(), 60 | }, 61 | { 62 | ID: 2, 63 | Name: "Espresso", 64 | Description: "Short and strong coffee without milk", 65 | Price: 1.99, 66 | SKU: "fjd34", 67 | CreatedOn: time.Now().UTC().String(), 68 | UpdatedOn: time.Now().UTC().String(), 69 | }, 70 | } 71 | 72 | func GetProducts() Products { 73 | return productList 74 | } 75 | 76 | func getNextId() int { 77 | lp := productList[len(productList)-1] 78 | return lp.ID + 1 79 | } 80 | 81 | func AddProduct(p *Product) { 82 | p.ID = getNextId() 83 | productList = append(productList, p) 84 | 85 | } 86 | 87 | func UpdateProduct(id int, p *Product) error { 88 | _, ploc, err := findProduct(id) 89 | if err != nil { 90 | return err 91 | } 92 | p.ID = id 93 | productList[ploc] = p 94 | return nil 95 | } 96 | 97 | var ErrorProductNotFound = fmt.Errorf("Product not found") 98 | 99 | func findProduct(id int) (*Product, int, error) { 100 | for l, p := range productList { 101 | if p.ID == id { 102 | return p, l, nil 103 | } 104 | } 105 | return nil, -1, ErrorProductNotFound 106 | } 107 | -------------------------------------------------------------------------------- /microservices/product-api/handlers/handlers.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "regexp" 7 | "strconv" 8 | 9 | "github.com/erankitcs/golang_learning/microservices/product-api/data" 10 | ) 11 | 12 | type Products struct { 13 | l *log.Logger 14 | } 15 | 16 | func NewProduct(l *log.Logger) *Products { 17 | return &Products{l} 18 | } 19 | 20 | func (p *Products) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 21 | if r.Method == http.MethodGet { 22 | p.getProducts(rw, r) 23 | return 24 | } 25 | 26 | if r.Method == http.MethodPost { 27 | p.addProduct(rw, r) 28 | return 29 | } 30 | if r.Method == http.MethodPut { 31 | regx := regexp.MustCompile(`/([0-9]+)`) 32 | g := regx.FindAllStringSubmatch(r.URL.Path, -1) 33 | if len(g) != 1 { 34 | p.l.Println("Invalid URI more than one id") 35 | http.Error(rw, "Invalid URI", http.StatusBadRequest) 36 | } 37 | if len(g[0]) != 2 { 38 | p.l.Println("Invalid URI more than one capture group") 39 | http.Error(rw, "Invalid URI", http.StatusBadRequest) 40 | return 41 | } 42 | idString := g[0][1] 43 | id, err := strconv.Atoi(idString) 44 | if err != nil { 45 | p.l.Println("Invalid URI unable to convert to numer", idString) 46 | http.Error(rw, "Invalid URI", http.StatusBadRequest) 47 | return 48 | } 49 | p.updateProduct(id, rw, r) 50 | return 51 | } 52 | 53 | rw.WriteHeader(http.StatusMethodNotAllowed) 54 | 55 | } 56 | 57 | func (p *Products) getProducts(rw http.ResponseWriter, r *http.Request) { 58 | lp := data.GetProducts() 59 | //d, err := json.Marshal(lp) 60 | // Encoder is much faster and memory efficient 61 | err := lp.ToJSON(rw) 62 | if err != nil { 63 | http.Error(rw, "Unable to parse product data", http.StatusInternalServerError) 64 | } 65 | //rw.Write(d) 66 | } 67 | 68 | func (p *Products) addProduct(rw http.ResponseWriter, r *http.Request) { 69 | p.l.Printf("Handling PUT request") 70 | newprod := &data.Product{} 71 | err := newprod.FromJSON(r.Body) 72 | if err != nil { 73 | http.Error(rw, "Unable to parse product request", http.StatusBadRequest) 74 | } 75 | //p.l.Printf("New Product %#v", newprod) 76 | data.AddProduct(newprod) 77 | } 78 | 79 | func (p *Products) updateProduct(id int, rw http.ResponseWriter, r *http.Request) { 80 | p.l.Println("Handle PUT product") 81 | prod := &data.Product{} 82 | 83 | err := prod.FromJSON(r.Body) 84 | if err != nil { 85 | http.Error(rw, "Unable to parse product request", http.StatusBadRequest) 86 | } 87 | err = data.UpdateProduct(id, prod) 88 | if err == data.ErrorProductNotFound { 89 | http.Error(rw, "Product not found", http.StatusNotFound) 90 | return 91 | } 92 | 93 | if err != nil { 94 | http.Error(rw, "Product update failed", http.StatusInternalServerError) 95 | return 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /customdatatypes/datatypes5/organisation/person.go: -------------------------------------------------------------------------------- 1 | package organisation 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | type TwitterHandler string 11 | 12 | func (th TwitterHandler) RedirectURL() string { 13 | cleanHandler := strings.TrimPrefix(string(th), "@") 14 | return fmt.Sprintf("https://www.twitter.com/%s", cleanHandler) 15 | } 16 | 17 | type Identifiable interface { 18 | ID() string 19 | } 20 | 21 | type Citizen interface { 22 | Identifiable 23 | Country() string 24 | } 25 | 26 | type socialSecurityNumber string 27 | 28 | func NewSocialSecurityNumber(value string) Citizen { 29 | return socialSecurityNumber(value) 30 | } 31 | 32 | func (ssn socialSecurityNumber) ID() string { 33 | return string(ssn) 34 | } 35 | 36 | func (ssn socialSecurityNumber) Country() string { 37 | return "USA" 38 | } 39 | 40 | type europeanUnionIdentifier struct { 41 | id string 42 | country []string 43 | } 44 | 45 | func NewEuropeanUnionIdentifier(id interface{}, country string) Citizen { 46 | switch v := id.(type) { 47 | case string: 48 | return europeanUnionIdentifier{ 49 | id: v, 50 | country: []string{country}, 51 | } 52 | case int: 53 | return europeanUnionIdentifier{ 54 | id: strconv.Itoa(v), 55 | country: []string{country}, 56 | } 57 | case europeanUnionIdentifier: 58 | return v 59 | case Person: 60 | euId, _ := v.Citizen.(europeanUnionIdentifier) 61 | return euId 62 | default: 63 | panic("Using invalid type initialize EU identifier") 64 | } 65 | } 66 | 67 | func (eui europeanUnionIdentifier) ID() string { 68 | return eui.id 69 | } 70 | 71 | func (eui europeanUnionIdentifier) Country() string { 72 | return fmt.Sprintf("EU: %s", eui.country) 73 | } 74 | 75 | type Name struct { 76 | First string 77 | Last string 78 | } 79 | 80 | func (n *Name) FullName() string { 81 | return fmt.Sprintf("%s %s", n.First, n.Last) 82 | } 83 | 84 | type Employee struct { 85 | Name 86 | } 87 | 88 | type Person struct { 89 | Name 90 | First string 91 | Last string 92 | twitterHandler TwitterHandler 93 | Citizen 94 | } 95 | 96 | func NewPerson(firstName, lastName string, citizen Citizen) Person { 97 | return Person{ 98 | Name: Name{ 99 | First: firstName, 100 | Last: lastName, 101 | }, 102 | Citizen: citizen, 103 | } 104 | } 105 | 106 | func (p *Person) SetTwitterHandler(handler TwitterHandler) error { 107 | if len(handler) == 0 { 108 | p.twitterHandler = handler 109 | } else if !strings.HasPrefix(string(handler), "@") { 110 | return errors.New("twitter handle must start with @ in text") 111 | } 112 | p.twitterHandler = handler 113 | return nil 114 | } 115 | 116 | func (p *Person) TwitterHandler() TwitterHandler { 117 | return p.twitterHandler 118 | } 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GoLang Programming Learning 2 | This repo is created for learning GO language. It consist of basics of golang and advanced use cases. 3 | 4 | ## Basics 5 | 6 | ### Go Standard Library 7 | 1. [Go Args ](gostandard_libs/args_demo) 8 | 2. [Input using Bufio](gostandard_libs/bufio_demo) 9 | 3. [Custom Data types](gostandard_libs/custom_type) 10 | 4. [File Handling](gostandard_libs/filemaker_demo) 11 | 5. [Flag Inputs](gostandard_libs/flag_demo) 12 | 6. [Formated Input/Output using fmt](gostandard_libs/fmt_demo) 13 | 7. [Logers in Golang](gostandard_libs/loger_demo) 14 | 8. [Primitives and Slices](gostandard_libs/others_demo) 15 | 9. [Print input/output](gostandard_libs/print_demo) 16 | 10. [Time handling](gostandard_libs/time_demo) 17 | 11. [Trace in Golang](gostandard_libs/trace_demo) 18 | 12. [Working with Functions](functions) 19 | 13. [Custom Datatypes](customdatatypes) 20 | 14. [Testing in Golang](testinggolang) 21 | 15. [A CLI in goland](pluralsight_projects/golang-personal-budget-cli) 22 | 16. [Advanced Branching into Golang](pluralsight_projects/golang-advanced-branching) 23 | 24 | ### Concurrent Programming 25 | 1. [Channel Basics with PingPong Game](pingpong) 26 | 2. [Channel and Sync Advance Usecases with DB Cache System](concurrentprogram) 27 | 3. [Asynchronous Go Logging](golang-async-logging-library) 28 | 29 | ### Web Services 30 | 1. [A Simple Web Service in Golang](webservice) 31 | 2. [A Pluralsight Fifa World Cup WebService](pluralsight_projects/golang-fifa-world-cup-web-service) 32 | 33 | ### Distributed Application Programming 34 | 1. A true distributed system in go along with in-built load balancing and auto discovery [Distributed App in Go](distributedapp) 35 | 36 | ### Web based Application in Golang 37 | 1. [A Teacher Portal Web App](distributedapp/teacherportal) 38 | 2. [A Employee Vacation Tracker Web App Using gin framework](ginframeworkdemo) 39 | 40 | ### Microservices with Golang 41 | 1. [Microservice in golang basics](microservices/product-api) 42 | 2. [Microservice in golang with Gorilla Framework](microservices/product-api-gorilla) 43 | 3. [Microservice in golang with Gorilla Framework and Swagger File](microservices/product-api-withswagger) 44 | 4. [Microservice in golang with Gorilla Framework, Swagger File and Client](microservices/product-api-withswagger-client) 45 | 46 | 47 | 48 | ### gRPC based Services 49 | 1. A gRPC based APIs (service and client) with TLS and mTLS setup and automated testing [gRPC with mTLS](grpcdemo) 50 | 51 | ### Docker with Golang 52 | 1. [gRPC Based Service with Docker](grpcdemo) 53 | 2. [Distributed Golang App with Docker](distributedappdocker) 54 | 55 | ### Learning References 56 | 1. Most of above projects and knowledge is coming from [Pluralsight Golang Path](https://app.pluralsight.com/paths/skills/go-core-language) 57 | 2. Microservices with Go By [Nic Jackson](https://youtu.be/VzBGi_n65iU) 58 | 59 | ### Few More Learning Links. 60 | 1. Go Testing - https://quii.gitbook.io/learn-go-with-tests/ 61 | 2. Using Gin - https://github.com/PacktPublishing/Building-Distributed-Applications-in-Gin 62 | 3. Practical Go- https://www.practical-go-lessons.com/ 63 | 4. Go Security - https://checkmarx.gitbooks.io/go-scp/content/ 64 | -------------------------------------------------------------------------------- /distributedapp/grades/server.go: -------------------------------------------------------------------------------- 1 | package grades 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "log" 8 | "net/http" 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | func RegisterHandlers() { 14 | handler := new(studentsHandler) 15 | http.Handle("/students", handler) 16 | http.Handle("/students/", handler) 17 | 18 | } 19 | 20 | type studentsHandler struct { 21 | } 22 | 23 | func (sh studentsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 24 | pathSegment := strings.Split(r.URL.Path, "/") 25 | switch len(pathSegment) { 26 | case 2: 27 | sh.getAll(w, r) 28 | case 3: 29 | id, err := strconv.Atoi(pathSegment[2]) 30 | if err != nil { 31 | w.WriteHeader(http.StatusNotFound) 32 | return 33 | } 34 | sh.getOne(w, r, id) 35 | case 4: 36 | id, err := strconv.Atoi(pathSegment[2]) 37 | if err != nil { 38 | w.WriteHeader(http.StatusNotFound) 39 | return 40 | } 41 | sh.addGrade(w, r, id) 42 | default: 43 | w.WriteHeader(http.StatusNotFound) 44 | return 45 | } 46 | } 47 | 48 | func (sh studentsHandler) getAll(w http.ResponseWriter, r *http.Request) { 49 | studentsMutex.Lock() 50 | defer studentsMutex.Unlock() 51 | 52 | data, err := sh.toJSON(students) 53 | if err != nil { 54 | w.WriteHeader(http.StatusInternalServerError) 55 | log.Println(err) 56 | } 57 | w.Header().Add("Content-Type", "application/json") 58 | w.Write(data) 59 | } 60 | 61 | func (sh studentsHandler) getOne(w http.ResponseWriter, r *http.Request, id int) { 62 | studentsMutex.Lock() 63 | defer studentsMutex.Unlock() 64 | 65 | student, err := students.GetByID(id) 66 | if err != nil { 67 | if err != nil { 68 | w.WriteHeader(http.StatusNotFound) 69 | log.Println(err) 70 | return 71 | } 72 | } 73 | 74 | data, err := sh.toJSON(student) 75 | if err != nil { 76 | w.WriteHeader(http.StatusInternalServerError) 77 | log.Println(fmt.Errorf("Failed to serialize students: %q", err)) 78 | return 79 | } 80 | w.Header().Add("content-type", "application/json") 81 | w.Write(data) 82 | } 83 | 84 | func (sh studentsHandler) addGrade(w http.ResponseWriter, r *http.Request, id int) { 85 | studentsMutex.Lock() 86 | defer studentsMutex.Unlock() 87 | 88 | student, err := students.GetByID(id) 89 | 90 | if err != nil { 91 | w.WriteHeader(http.StatusNotFound) 92 | log.Println(err) 93 | return 94 | } 95 | var g Grade 96 | dec := json.NewDecoder(r.Body) 97 | err = dec.Decode(&g) 98 | if err != nil { 99 | w.WriteHeader(http.StatusBadRequest) 100 | fmt.Println(err) 101 | return 102 | } 103 | student.Grades = append(student.Grades, g) 104 | w.WriteHeader(http.StatusCreated) 105 | data, err := sh.toJSON(g) 106 | if err != nil { 107 | //w.WriteHeader(http.StatusInternalServerError) 108 | fmt.Println(err) 109 | return 110 | } 111 | w.Header().Add("content-type", "application/json") 112 | w.Write(data) 113 | 114 | } 115 | 116 | func (sh studentsHandler) toJSON(obj interface{}) ([]byte, error) { 117 | var b bytes.Buffer 118 | enc := json.NewEncoder(&b) 119 | err := enc.Encode(obj) 120 | if err != nil { 121 | return nil, fmt.Errorf("Failed to serialize stundents: %q", err) 122 | } 123 | return b.Bytes(), nil 124 | } 125 | -------------------------------------------------------------------------------- /distributedappdocker/grades/server.go: -------------------------------------------------------------------------------- 1 | package grades 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "log" 8 | "net/http" 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | func RegisterHandlers() { 14 | handler := new(studentsHandler) 15 | http.Handle("/students", handler) 16 | http.Handle("/students/", handler) 17 | 18 | } 19 | 20 | type studentsHandler struct { 21 | } 22 | 23 | func (sh studentsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 24 | pathSegment := strings.Split(r.URL.Path, "/") 25 | switch len(pathSegment) { 26 | case 2: 27 | sh.getAll(w, r) 28 | case 3: 29 | id, err := strconv.Atoi(pathSegment[2]) 30 | if err != nil { 31 | w.WriteHeader(http.StatusNotFound) 32 | return 33 | } 34 | sh.getOne(w, r, id) 35 | case 4: 36 | id, err := strconv.Atoi(pathSegment[2]) 37 | if err != nil { 38 | w.WriteHeader(http.StatusNotFound) 39 | return 40 | } 41 | sh.addGrade(w, r, id) 42 | default: 43 | w.WriteHeader(http.StatusNotFound) 44 | return 45 | } 46 | } 47 | 48 | func (sh studentsHandler) getAll(w http.ResponseWriter, r *http.Request) { 49 | studentsMutex.Lock() 50 | defer studentsMutex.Unlock() 51 | 52 | data, err := sh.toJSON(students) 53 | if err != nil { 54 | w.WriteHeader(http.StatusInternalServerError) 55 | log.Println(err) 56 | } 57 | w.Header().Add("Content-Type", "application/json") 58 | w.Write(data) 59 | } 60 | 61 | func (sh studentsHandler) getOne(w http.ResponseWriter, r *http.Request, id int) { 62 | studentsMutex.Lock() 63 | defer studentsMutex.Unlock() 64 | 65 | student, err := students.GetByID(id) 66 | if err != nil { 67 | if err != nil { 68 | w.WriteHeader(http.StatusNotFound) 69 | log.Println(err) 70 | return 71 | } 72 | } 73 | 74 | data, err := sh.toJSON(student) 75 | if err != nil { 76 | w.WriteHeader(http.StatusInternalServerError) 77 | log.Println(fmt.Errorf("Failed to serialize students: %q", err)) 78 | return 79 | } 80 | w.Header().Add("content-type", "application/json") 81 | w.Write(data) 82 | } 83 | 84 | func (sh studentsHandler) addGrade(w http.ResponseWriter, r *http.Request, id int) { 85 | studentsMutex.Lock() 86 | defer studentsMutex.Unlock() 87 | 88 | student, err := students.GetByID(id) 89 | 90 | if err != nil { 91 | w.WriteHeader(http.StatusNotFound) 92 | log.Println(err) 93 | return 94 | } 95 | var g Grade 96 | dec := json.NewDecoder(r.Body) 97 | err = dec.Decode(&g) 98 | if err != nil { 99 | w.WriteHeader(http.StatusBadRequest) 100 | fmt.Println(err) 101 | return 102 | } 103 | student.Grades = append(student.Grades, g) 104 | w.WriteHeader(http.StatusCreated) 105 | data, err := sh.toJSON(g) 106 | if err != nil { 107 | //w.WriteHeader(http.StatusInternalServerError) 108 | fmt.Println(err) 109 | return 110 | } 111 | w.Header().Add("content-type", "application/json") 112 | w.Write(data) 113 | 114 | } 115 | 116 | func (sh studentsHandler) toJSON(obj interface{}) ([]byte, error) { 117 | var b bytes.Buffer 118 | enc := json.NewEncoder(&b) 119 | err := enc.Encode(obj) 120 | if err != nil { 121 | return nil, fmt.Errorf("Failed to serialize stundents: %q", err) 122 | } 123 | return b.Bytes(), nil 124 | } 125 | -------------------------------------------------------------------------------- /grpcdemo/README.md: -------------------------------------------------------------------------------- 1 | ### Vacation Tracker based on GRPC and GO Lang 2 | 3 | 4 | ### Tools to install 5 | ``` 6 | go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 7 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 8 | go env GOPATH 9 | $env:PATH +="{GO PATH HERE}\bin" 10 | ``` 11 | ### Commands 12 | 13 | 1. Generating Server Code from protoc message 14 | ``` 15 | cd server 16 | go mod init github.com/erankitcs/golang_learning/grpcdemo/server 17 | protoc --proto_path=../pb ../pb/*.proto --go_out=. --go-grpc_out=. 18 | ``` 19 | 20 | 2. Certificate Generate commands 21 | ``` 22 | cd cert 23 | # 1. Generate CA's private key and self-signed certificate 24 | openssl req -x509 -newkey rsa:4096 -days 365 -nodes -keyout ca-key.pem -out ca-cert.pem -subj "/C=AU/ST=Vic/L=Melbourne/O=Go Grpc/OU=Testing/CN=*.gogrpc.test/emailAddress=gogrpctest@gmail.com" 25 | # View CA certificate 26 | openssl x509 -in ca-cert.pem -noout -text 27 | 28 | # 2. Generate web server's private key and certificate signing request (CSR) 29 | openssl req -newkey rsa:4096 -nodes -keyout server-key.pem -out server-req.pem -subj "/C=AU/ST=Vic/L=Melbourne/O=Go Grpc/OU=ServerTesting/CN=*.gogrpcserver.com/emailAddress=gogrpcserver@gmail.com" 30 | 31 | # 3. Use CA's private key to sign web server's CSR and get back the signed certificate 32 | openssl x509 -req -in server-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile server-ext.cnf 33 | 34 | echo "Server's signed certificate" 35 | openssl x509 -in server-cert.pem -noout -text 36 | 37 | # 4. Move certs starts with server into cert folder inside server. 38 | ``` 39 | 40 | 3. Build and Run server, use -mtls=true for running into mTLS Mode. 41 | ``` 42 | cd server 43 | go build . 44 | ./server.exe 45 | ``` 46 | 47 | 4. Call server via grpccurl 48 | 49 | - You need to add below line for local DNS resolution. 50 | 51 | 127.0.0.1 test.gogrpcserver.com 52 | 53 | - Need to set Environment variable 54 | ``` 55 | $env:GODEBUG="x509ignoreCN=0" 56 | ``` 57 | - Run below command to call grpc server. 58 | ``` 59 | grpcurl -cacert ca-cert.pem test.gogrpcserver.com:9000 messages.EmployeeService/GetAll 60 | ``` 61 | 62 | *Postman support grpc now* 63 | https://blog.postman.com/postman-now-supports-grpc/ 64 | 65 | 5. Call via Golang based client. 66 | - Run go mod init and get client for grpc 67 | ``` 68 | cd client 69 | go mod init github.com/erankitcs/golang_learning/grpcdemo/client 70 | protoc --proto_path=../pb ../pb/*.proto --go_out=. --go-grpc_out=. 71 | go mod tidy 72 | go build . 73 | ``` 74 | - Run Client, -tls true for TLS setup and -mtls true for mTLS setup. 75 | ``` 76 | ./client.exe -tls true 77 | ``` 78 | 79 | 6. Server Testing 80 | ``` 81 | cd server 82 | go test -v 83 | ``` 84 | 85 | 7. Docker setup for Server 86 | ``` 87 | docker build -t employeegrpcserver -f server/Dockerfile . 88 | docker run -d -p 9000:9000 -e tls=mtls --network host --name employeegrpcserver employeegrpcserver 89 | ``` 90 | 8. Docker setup for Client 91 | ``` 92 | docker build -t employeegrpcclient -f client/Dockerfile . 93 | docker run -e tls=mtls -e opt=1 -e serverhost=localhost --network host --name grpcclient employeegrpcclient 94 | ``` 95 | - Docker Links\ 96 | https://www.docker.com/blog/tag/go-env-series/ 97 | https://github.com/chris-crone/containerized-go-dev 98 | -------------------------------------------------------------------------------- /pluralsight_projects/golang-fifa-world-cup-web-service/handlers/02_post_handler_test.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "golang-fifa-world-cup-web-service/data" 7 | "net/http" 8 | "net/http/httptest" 9 | "testing" 10 | ) 11 | 12 | func TestAddNewWinnerHandlerReturnsUnauthorizedForInvalidAccessToken(t *testing.T) { 13 | setup() 14 | 15 | req, _ := http.NewRequest("POST", "/winners", nil) 16 | req.Header.Set("X-ACCESS-TOKEN", data.AccessToken+"bla") 17 | rr := httptest.NewRecorder() 18 | handler := http.HandlerFunc(AddNewWinner) 19 | handler.ServeHTTP(rr, req) 20 | 21 | if status := rr.Code; status != http.StatusUnauthorized { 22 | t.Error("Did not return status 401 - Unauthorized for invalid Access Token") 23 | } 24 | } 25 | 26 | func TestAddNewWinnerHandlerReturnsCreatedForValidAccessToken(t *testing.T) { 27 | var jsonStr = []byte(`{"country":"Croatia", "year": 2030}`) 28 | req, _ := http.NewRequest("POST", "/winners", bytes.NewBuffer(jsonStr)) 29 | req.Header.Set("Content-Type", "application/json") 30 | req.Header.Set("X-ACCESS-TOKEN", data.AccessToken) 31 | 32 | rr := httptest.NewRecorder() 33 | handler := http.HandlerFunc(AddNewWinner) 34 | handler.ServeHTTP(rr, req) 35 | 36 | if status := rr.Code; status != http.StatusCreated { 37 | t.Error("Did not return status 201 - Created for valid Access Token") 38 | } 39 | } 40 | 41 | func TestAddNewWinnerHandlerAddsNewWinnerWithValidData(t *testing.T) { 42 | setup() 43 | 44 | var jsonStr = []byte(`{"country":"Croatia", "year": 2030}`) 45 | req, _ := http.NewRequest("POST", "/winners", bytes.NewBuffer(jsonStr)) 46 | req.Header.Set("Content-Type", "application/json") 47 | req.Header.Set("X-ACCESS-TOKEN", data.AccessToken) 48 | 49 | rr := httptest.NewRecorder() 50 | handler := http.HandlerFunc(AddNewWinner) 51 | handler.ServeHTTP(rr, req) 52 | 53 | allWinners, _ := data.ListAllJSON() 54 | var winners data.Winners 55 | json.Unmarshal([]byte(allWinners), &winners) 56 | 57 | if len(winners.Winners) != 22 { 58 | t.Error("Did not properly add new winner to the list") 59 | } 60 | } 61 | 62 | func TestAddNewWinnerHandlerReturnsUnprocessableEntityForEmptyPayload(t *testing.T) { 63 | setup() 64 | 65 | // Invalid because empty 66 | var jsonStr = []byte(``) 67 | req, _ := http.NewRequest("POST", "/winners", bytes.NewBuffer(jsonStr)) 68 | req.Header.Set("X-ACCESS-TOKEN", data.AccessToken) 69 | rr := httptest.NewRecorder() 70 | handler := http.HandlerFunc(AddNewWinner) 71 | handler.ServeHTTP(rr, req) 72 | if status := rr.Code; status != http.StatusUnprocessableEntity { 73 | t.Error("Did not properly validate winner payload") 74 | } 75 | } 76 | 77 | func TestAddNewWinnerHandlerDoesNotAddInvalidNewWinner(t *testing.T) { 78 | setup() 79 | 80 | // Invalid entry because year is in the past. 81 | var jsonStr = []byte(`{"country":"Croatia", "year": 1984}`) 82 | req, _ := http.NewRequest("POST", "/winners", bytes.NewBuffer(jsonStr)) 83 | req.Header.Set("Content-Type", "application/json") 84 | req.Header.Set("X-ACCESS-TOKEN", data.AccessToken) 85 | 86 | rr := httptest.NewRecorder() 87 | handler := http.HandlerFunc(AddNewWinner) 88 | handler.ServeHTTP(rr, req) 89 | 90 | allWinners, _ := data.ListAllJSON() 91 | var winners data.Winners 92 | json.Unmarshal([]byte(allWinners), &winners) 93 | 94 | if rr.Code == http.StatusOK || len(winners.Winners) != 21 { 95 | t.Error("Added invalid winner to list") 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /golang-async-logging-library/module3_test.go: -------------------------------------------------------------------------------- 1 | package alog 2 | 3 | import ( 4 | "bytes" 5 | "strings" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | // 01 11 | func TestNewInitializesShutdownChannelsModule3(t *testing.T) { 12 | alog := New(nil) 13 | if alog.shutdownCh == nil { 14 | t.Error("shutdownCh field not initialized") 15 | } 16 | 17 | if alog.shutdownCompleteCh == nil { 18 | t.Error("shutdownCompleteCh field not initialized") 19 | } 20 | } 21 | 22 | // 02 23 | 24 | func TestShutdownMethodModule3(t *testing.T) { 25 | alog := New(nil) 26 | alog.shutdownCompleteCh = make(chan struct{}, 1) 27 | alog.shutdown() 28 | time.Sleep(100 * time.Millisecond) 29 | select { 30 | case _, ok := <-alog.msgCh: 31 | if ok { 32 | t.Error("msgCh not closed by shutdown() method") 33 | } 34 | default: 35 | t.Error("msgCh not closed by shutdown() method") 36 | } 37 | select { 38 | case <-alog.shutdownCompleteCh: 39 | default: 40 | t.Error("shutdown() doesn't send message to shutdownCompleteCh") 41 | } 42 | 43 | } 44 | 45 | // 03 46 | 47 | func TestStartMethodCallsShutdownModule3(t *testing.T) { 48 | b := bytes.NewBuffer([]byte{}) 49 | alog := New(b) 50 | alog.shutdownCh = make(chan struct{}, 1) 51 | alog.shutdownCompleteCh = make(chan struct{}, 1) 52 | go alog.Start() 53 | alog.shutdownCh <- struct{}{} 54 | time.Sleep(100 * time.Millisecond) 55 | 56 | select { 57 | case _, ok := <-alog.msgCh: 58 | if ok { 59 | t.Error("Passing message to shutdownCh doesn't call shutdown()") 60 | } 61 | default: 62 | t.Error("Passing message to shutdownCh doesn't call shutdown()") 63 | } 64 | select { 65 | case <-alog.shutdownCompleteCh: 66 | default: 67 | t.Error("Passing message to shutdownCh doesn't call shutdown()") 68 | } 69 | if b.Len() != 0 { 70 | t.Error("Passing message to shutdownCh doesn't break out of the Start method's for loop. " + 71 | "Note that 'break' statements can be used for select and for loops so a label might be " + 72 | "required to break out the loop.") 73 | } 74 | } 75 | 76 | // 04 77 | 78 | func TestStopMethodModule3(t *testing.T) { 79 | alog := New(nil) 80 | alog.shutdownCh = make(chan struct{}, 1) 81 | alog.shutdownCompleteCh = make(chan struct{}, 1) 82 | alog.shutdownCompleteCh <- struct{}{} 83 | alog.Stop() 84 | select { 85 | case <-alog.shutdownCh: 86 | default: 87 | t.Error("Stop() method doesn't send signal to shutdownCh channel") 88 | } 89 | select { 90 | case <-alog.shutdownCompleteCh: 91 | t.Error("Stop() method doesn't wait for signal from shutdownCompleteCh channel") 92 | default: 93 | } 94 | } 95 | 96 | // 05 97 | 98 | func TestWriteAllBeforeShutdownModule3(t *testing.T) { 99 | b := bytes.NewBuffer([]byte{}) 100 | alog := New(sleepingWriter{b}) 101 | alog.msgCh = make(chan string, 2) 102 | go alog.Start() 103 | alog.msgCh <- "first" 104 | alog.msgCh <- "second" 105 | time.Sleep(10 * time.Millisecond) 106 | doneCh := make(chan struct{}) 107 | go func() { 108 | alog.Stop() 109 | written := b.String() 110 | if !strings.Contains(written, "first") || !strings.Contains(written, "second") { 111 | t.Error("Not all messages written before logger shutdown") 112 | } 113 | doneCh <- struct{}{} 114 | }() 115 | select { 116 | case <-time.Tick(1 * time.Second): 117 | t.Error("Test timed out, please check that the Done method on the wait group is being called in the write method") 118 | case <-doneCh: 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /microservices/product-api-withswagger/data/products.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // ErrProductNotFound is an error raised when a product can not be found in the database 8 | var ErrorProductNotFound = fmt.Errorf("Product not found") 9 | 10 | // Product defines the structure for an API product 11 | // swagger:model 12 | type Product struct { 13 | // the id for the product 14 | // 15 | // required: false 16 | // min:1 17 | ID int `json:"id"` 18 | 19 | // the name for this poduct 20 | // 21 | // required: true 22 | // max length: 255 23 | Name string `json:"name" validate:"required"` 24 | 25 | // the description for this poduct 26 | // 27 | // required: false 28 | // max length: 10000 29 | Description string `json:"description"` 30 | 31 | // the price for the product 32 | // 33 | // required: true 34 | // min: 0.01 35 | Price float32 `json:"price" validate:"gt=0"` 36 | 37 | // the SKU for the product 38 | // 39 | // required: true 40 | // pattern: [a-z]+-[a-z]+-[a-z]+ 41 | SKU string `json:"sku" validate:"required,sku"` 42 | } 43 | 44 | //Collection of product 45 | type Products []*Product 46 | 47 | // func (p *Product) Validate() error { 48 | // validate := validator.New() 49 | // validate.RegisterValidation("sku", validateSKU) 50 | // return validate.Struct(p) 51 | // } 52 | 53 | var productList = []*Product{ 54 | { 55 | ID: 1, 56 | Name: "Latte", 57 | Description: "Frothy milky coffee", 58 | Price: 2.45, 59 | SKU: "abc323", 60 | }, 61 | { 62 | ID: 2, 63 | Name: "Espresso", 64 | Description: "Short and strong coffee without milk", 65 | Price: 1.99, 66 | SKU: "fjd34", 67 | }, 68 | } 69 | 70 | // GetProducts returns all products from the database 71 | func GetProducts() Products { 72 | return productList 73 | } 74 | 75 | // GetProductByID returns a single product which matches the id from the 76 | // database. 77 | // If a product is not found this function returns a ProductNotFound error 78 | func GetProductByID(id int) (*Product, error) { 79 | i := findIndexByProductID(id) 80 | if i == -1 { 81 | return nil, ErrorProductNotFound 82 | } 83 | return productList[i], nil 84 | } 85 | 86 | // UpdateProduct replaces a product in the database with the given 87 | // item. 88 | // If a product with the given id does not exist in the database 89 | // this function returns a ProductNotFound erro 90 | func UpdateProduct(p *Product) error { 91 | i := findIndexByProductID(p.ID) 92 | if i == -1 { 93 | return ErrorProductNotFound 94 | } 95 | productList[i] = p 96 | return nil 97 | } 98 | 99 | // AddProduct adds a new product to the database 100 | func AddProduct(p *Product) { 101 | maxID := productList[len(productList)-1].ID 102 | p.ID = maxID + 1 103 | productList = append(productList, p) 104 | 105 | } 106 | 107 | // DeleteProduct deletes a product from the database 108 | func DeleteProduct(id int) error { 109 | i := findIndexByProductID(id) 110 | if i == -1 { 111 | return ErrorProductNotFound 112 | } 113 | productList = append(productList[:i], productList[i+1:]...) 114 | return nil 115 | } 116 | 117 | // findIndex finds the index of a product in the database 118 | // returns -1 when no product can be found 119 | func findIndexByProductID(id int) int { 120 | for i, p := range productList { 121 | if p.ID == id { 122 | return i 123 | } 124 | } 125 | return -1 126 | } 127 | -------------------------------------------------------------------------------- /webservice/controllers/user.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | "regexp" 7 | "strconv" 8 | 9 | "github.com/erankitcs/golang_learning/webservice/models" 10 | ) 11 | 12 | type userController struct { 13 | userIDPattern *regexp.Regexp 14 | } 15 | 16 | func (uc userController) ServeHTTP(w http.ResponseWriter, r *http.Request) { 17 | // w.Write([]byte("Hello from User Controller.")) 18 | if r.URL.Path == "/users" { 19 | switch r.Method { 20 | case http.MethodGet: 21 | uc.getAll(w, r) 22 | case http.MethodPost: 23 | uc.post(w, r) 24 | default: 25 | w.WriteHeader(http.StatusNotImplemented) 26 | } 27 | } else { 28 | matches := uc.userIDPattern.FindStringSubmatch(r.URL.Path) 29 | if len(matches) == 0 { 30 | w.WriteHeader(http.StatusNotFound) 31 | return 32 | } 33 | id, err := strconv.Atoi(matches[1]) 34 | if err != nil { 35 | w.WriteHeader(http.StatusNotFound) 36 | return 37 | } 38 | switch r.Method { 39 | case http.MethodGet: 40 | uc.get(id, w) 41 | case http.MethodPut: 42 | uc.put(id, w, r) 43 | case http.MethodDelete: 44 | uc.delete(id, w) 45 | default: 46 | w.WriteHeader(http.StatusNotImplemented) 47 | } 48 | 49 | } 50 | } 51 | 52 | func (uc *userController) getAll(w http.ResponseWriter, r *http.Request) { 53 | encodeResponseAsJSON(models.GetUsers(), w) 54 | } 55 | 56 | func (uc *userController) get(id int, w http.ResponseWriter) { 57 | u, err := models.GetUserById(id) 58 | if err != nil { 59 | w.WriteHeader(http.StatusInternalServerError) 60 | return 61 | } 62 | encodeResponseAsJSON(u, w) 63 | } 64 | 65 | func (uc *userController) post(w http.ResponseWriter, r *http.Request) { 66 | u, err := uc.parseRequest(r) 67 | if err != nil { 68 | w.WriteHeader(http.StatusInternalServerError) 69 | w.Write([]byte("Could not parse User Object.")) 70 | return 71 | } 72 | u, err = models.AddUser(u) 73 | if err != nil { 74 | w.WriteHeader(http.StatusInternalServerError) 75 | w.Write([]byte(err.Error())) 76 | return 77 | } 78 | encodeResponseAsJSON(u, w) 79 | } 80 | 81 | func (uc *userController) put(id int, w http.ResponseWriter, r *http.Request) { 82 | u, err := uc.parseRequest(r) 83 | if err != nil { 84 | w.WriteHeader(http.StatusInternalServerError) 85 | w.Write([]byte("Could not parse User object")) 86 | return 87 | } 88 | if id != u.ID { 89 | w.WriteHeader(http.StatusBadRequest) 90 | w.Write([]byte("ID of submitted user must match ID in URL")) 91 | return 92 | } 93 | u, err = models.UpdateUser(u) 94 | if err != nil { 95 | w.WriteHeader(http.StatusInternalServerError) 96 | w.Write([]byte(err.Error())) 97 | return 98 | } 99 | encodeResponseAsJSON(u, w) 100 | } 101 | 102 | func (uc *userController) delete(id int, w http.ResponseWriter) { 103 | err := models.RemoveUserById(id) 104 | if err != nil { 105 | w.WriteHeader(http.StatusInternalServerError) 106 | w.Write([]byte(err.Error())) 107 | return 108 | } 109 | w.WriteHeader(http.StatusOK) 110 | } 111 | 112 | func newUserController() *userController { 113 | return &userController{ 114 | userIDPattern: regexp.MustCompile(`^/users/(\d+)/?`), 115 | } 116 | } 117 | 118 | func (uc *userController) parseRequest(r *http.Request) (models.User, error) { 119 | dec := json.NewDecoder(r.Body) 120 | var u models.User 121 | err := dec.Decode(&u) 122 | if err != nil { 123 | return models.User{}, nil 124 | } 125 | return u, nil 126 | } 127 | --------------------------------------------------------------------------------