├── LICENSE ├── README.md ├── background-tasks-in-go ├── background-workers ├── go.mod ├── go.sum ├── main.go └── workers │ └── workers.go ├── cache-by-tags-in-go ├── go.mod ├── go.sum └── main.go ├── checksum-validation-in-go ├── go.mod ├── main.go └── secret.txt ├── context-cancellation-in-go ├── exampleOne.go ├── exampleTwo.go ├── go.mod └── main.go ├── create-queues-in-aws-sqs-using-go ├── go.mod ├── go.sum └── main.go ├── delete-files-in-aws-s3-using-go ├── docker-compose.yml ├── go.mod ├── go.sum └── main.go ├── delete-queues-in-aws-sqs-using-go ├── go.mod ├── go.sum └── main.go ├── how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack ├── create.go ├── delete.go ├── deleteTable.go ├── go.mod ├── go.sum ├── insert.go ├── main.go ├── query.go ├── sortkeys │ └── main.go └── update.go ├── implementing-mtls-in-go ├── certificate │ └── certificate.go ├── go.mod ├── main.go └── server │ └── server.go ├── list-queues-in-aws-sqs-using-go ├── go.mod ├── go.sum └── main.go ├── listing-files-in-aws-s3-using-go ├── docker-compose.yml ├── go.mod ├── go.sum └── main.go ├── multipart-requests-in-go ├── multipart-form-data │ ├── client.html │ └── server │ │ └── main.go └── multipart-related │ ├── client.go │ └── server │ └── main.go ├── receive-messages-from-aws-sqs-using-go ├── go.mod ├── go.sum └── main.go ├── send-messages-to-aws-sqs-using-go ├── go.mod ├── go.sum └── main.go ├── string-length-in-go ├── go.mod ├── go.sum └── main.go ├── tail-comment-in-python ├── file.txt └── main.py ├── union-find-in-python └── main.py ├── uploading-files-to-aws-s3-using-go ├── docker-compose.yml ├── go.mod ├── go.sum └── main.go ├── vaildate-tor-ipaddress-in-go ├── go.mod └── validate.go └── validate-email-address-in-go ├── go.mod ├── validate.go └── validate_test.go /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Bharghava Varun Ayada 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blog Source Code 2 | 3 | This repo contains reference source code for the blog [ayada.dev](https://ayada.dev) 4 | 5 | ## Blog Posts 6 | - [Multipart Requests in Go](https://ayada.dev/posts/multipart-requests-in-go/) in [multipart-requests-in-go](multipart-requests-in-go/) 7 | - [Caching records by tags in Go](https://ayada.dev/posts/cache-by-tags-in-go/) in [cache-by-tags-in-go](cache-by-tags-in-go/) 8 | - [Validate email address in Go](https://ayada.dev/posts/validate-email-address-in-go/) in [validate-email-address-in-go](validate-email-address-in-go/) 9 | - [Validate Tor IP Address in Go](https://ayada.dev/posts/vaildate-tor-ipaddress-in-go/) in [vaildate-tor-ipaddress-in-go](vaildate-tor-ipaddress-in-go/) -------------------------------------------------------------------------------- /background-tasks-in-go/background-workers: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abvarun226/blog-source-code/a0bdc4a29b75249ba3cf374845e273fe66e0aac0/background-tasks-in-go/background-workers -------------------------------------------------------------------------------- /background-tasks-in-go/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/abvarun226/background-workers 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/apex/log v1.9.0 7 | github.com/gorilla/mux v1.8.0 8 | github.com/pkg/errors v0.9.1 9 | ) 10 | -------------------------------------------------------------------------------- /background-tasks-in-go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0= 2 | github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA= 3 | github.com/apex/logs v1.0.0/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= 4 | github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= 5 | github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= 6 | github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 7 | github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= 8 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 10 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 12 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 13 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 14 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 15 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 16 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 17 | github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= 18 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 19 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 20 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 21 | github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= 22 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 23 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 24 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 25 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 26 | github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= 27 | github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 28 | github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 29 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 30 | github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= 31 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 32 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 33 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 34 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 35 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 36 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 37 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 38 | github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 39 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 40 | github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= 41 | github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= 42 | github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= 43 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 44 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 45 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 46 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 47 | github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= 48 | github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk= 49 | github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk= 50 | github.com/tj/go-buffer v1.1.0/go.mod h1:iyiJpfFcR2B9sXu7KvjbT9fpM4mOelRSDTbntVj52Uc= 51 | github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= 52 | github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= 53 | github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= 54 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 55 | golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 56 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 57 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 58 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 59 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 60 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 61 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 62 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 63 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 64 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 65 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 66 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 67 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 68 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 69 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 70 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 71 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 72 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 73 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 74 | gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo= 75 | gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 76 | -------------------------------------------------------------------------------- /background-tasks-in-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | "os" 8 | "os/signal" 9 | "syscall" 10 | "time" 11 | 12 | "github.com/abvarun226/background-workers/workers" 13 | "github.com/apex/log" 14 | "github.com/gorilla/mux" 15 | ) 16 | 17 | func main() { 18 | ctx := context.Background() 19 | graceperiod := 5 * time.Second 20 | workerCount := 10 21 | buffer := 100 22 | httpAddr := ":8000" 23 | 24 | log.Info("starting workers") 25 | w := workers.New(workerCount, buffer) 26 | w.Start(ctx) 27 | 28 | h := handler{worker: w} 29 | 30 | router := mux.NewRouter() 31 | router.HandleFunc("/queue-task", h.queueTask).Methods("POST") 32 | 33 | srv := &http.Server{ 34 | Addr: httpAddr, 35 | Handler: router, 36 | } 37 | 38 | done := make(chan os.Signal, 1) 39 | signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) 40 | 41 | log.Info("starting http server") 42 | go func() { 43 | if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { 44 | log.WithError(err).Fatalf("listen failed") 45 | } 46 | }() 47 | 48 | <-done 49 | log.Info("http server stopped") 50 | 51 | ctxTimeout, cancel := context.WithTimeout(ctx, graceperiod) 52 | defer func() { 53 | w.Stop() 54 | cancel() 55 | }() 56 | 57 | if err := srv.Shutdown(ctxTimeout); err != nil { 58 | log.WithError(err).Fatalf("http server shutdown failed") 59 | } 60 | } 61 | 62 | type handler struct { 63 | worker workers.WorkerIface 64 | } 65 | 66 | func (h *handler) queueTask(w http.ResponseWriter, r *http.Request) { 67 | var input queueTaskInput 68 | if err := json.NewDecoder(r.Body).Decode(&input); err != nil { 69 | log.WithError(err).Info("failed to read POST body") 70 | renderResponse(w, http.StatusBadRequest, `{"error": "failed to read POST body"}`) 71 | return 72 | } 73 | defer r.Body.Close() 74 | 75 | // parse the work duration from the request body. 76 | workDuration, errParse := time.ParseDuration(input.WorkDuration) 77 | if errParse != nil { 78 | log.WithError(errParse).Info("failed to parse work duration in request") 79 | renderResponse(w, http.StatusBadRequest, `{"error": "failed to parse work duration in request"}`) 80 | return 81 | } 82 | 83 | // queue the task in background task manager. 84 | if err := h.worker.QueueTask(input.TaskID, workDuration); err != nil { 85 | log.WithError(err).Info("failed to queue task") 86 | if err == workers.ErrWorkerBusy { 87 | w.Header().Set("Retry-After", "60") 88 | renderResponse(w, http.StatusServiceUnavailable, `{"error": "workers are busy, try again later"}`) 89 | return 90 | } 91 | renderResponse(w, http.StatusInternalServerError, `{"error": "failed to queue task"}`) 92 | return 93 | } 94 | 95 | renderResponse(w, http.StatusAccepted, `{"status": "task queued successfully"}`) 96 | } 97 | 98 | func renderResponse(w http.ResponseWriter, status int, message string) { 99 | w.Header().Set("content-type", "application/json") 100 | w.WriteHeader(status) 101 | w.Write([]byte(message)) 102 | } 103 | 104 | type queueTaskInput struct { 105 | TaskID string `json:"task_id"` 106 | WorkDuration string `json:"work_duration"` 107 | } 108 | -------------------------------------------------------------------------------- /background-tasks-in-go/workers/workers.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | "time" 7 | 8 | "github.com/apex/log" 9 | "github.com/pkg/errors" 10 | ) 11 | 12 | type worker struct { 13 | workchan chan workType 14 | workerCount int 15 | buffer int 16 | wg *sync.WaitGroup 17 | cancelFunc context.CancelFunc 18 | } 19 | 20 | type WorkerIface interface { 21 | Start(pctx context.Context) 22 | Stop() 23 | QueueTask(task string, workDuration time.Duration) error 24 | } 25 | 26 | func New(workerCount, buffer int) WorkerIface { 27 | w := worker{ 28 | workchan: make(chan workType, buffer), 29 | workerCount: workerCount, 30 | buffer: buffer, 31 | wg: new(sync.WaitGroup), 32 | } 33 | 34 | return &w 35 | } 36 | 37 | func (w *worker) Start(pctx context.Context) { 38 | ctx, cancelFunc := context.WithCancel(pctx) 39 | w.cancelFunc = cancelFunc 40 | 41 | for i := 0; i < w.workerCount; i++ { 42 | w.wg.Add(1) 43 | go w.spawnWorkers(ctx) 44 | } 45 | } 46 | 47 | func (w *worker) Stop() { 48 | log.Info("stop workers") 49 | close(w.workchan) 50 | w.cancelFunc() 51 | w.wg.Wait() 52 | log.Info("all workers exited!") 53 | } 54 | 55 | func (w *worker) QueueTask(task string, workDuration time.Duration) error { 56 | if len(w.workchan) >= w.buffer { 57 | return ErrWorkerBusy 58 | } 59 | 60 | w.workchan <- workType{TaskID: task, WorkDuration: workDuration} 61 | 62 | return nil 63 | } 64 | 65 | func (w *worker) spawnWorkers(ctx context.Context) { 66 | defer w.wg.Done() 67 | 68 | for work := range w.workchan { 69 | select { 70 | case <-ctx.Done(): 71 | return 72 | default: 73 | w.doWork(ctx, work.TaskID, work.WorkDuration) 74 | } 75 | } 76 | } 77 | 78 | func (w *worker) doWork(ctx context.Context, task string, workDuration time.Duration) { 79 | log.WithField("task", task).Info("do some work now...") 80 | sleepContext(ctx, workDuration) 81 | log.WithField("task", task).Info("work completed!") 82 | } 83 | 84 | func sleepContext(ctx context.Context, sleep time.Duration) { 85 | select { 86 | case <-ctx.Done(): 87 | case <-time.After(sleep): 88 | } 89 | } 90 | 91 | type workType struct { 92 | TaskID string 93 | WorkDuration time.Duration 94 | } 95 | 96 | var ( 97 | ErrWorkerBusy = errors.New("workers are busy, try again later") 98 | ) 99 | -------------------------------------------------------------------------------- /cache-by-tags-in-go/go.mod: -------------------------------------------------------------------------------- 1 | module go.imgur.com/cache-by-tags 2 | 3 | go 1.18 4 | 5 | require github.com/go-redis/redis/v7 v7.4.1 6 | 7 | require gopkg.in/yaml.v2 v2.2.8 // indirect 8 | -------------------------------------------------------------------------------- /cache-by-tags-in-go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 2 | github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI= 3 | github.com/go-redis/redis/v7 v7.4.1/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= 4 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 5 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 6 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 7 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 8 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 9 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 10 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 11 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 12 | github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= 13 | github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 14 | github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= 15 | github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 16 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 17 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 18 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= 19 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 20 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 21 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 22 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 23 | golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= 24 | golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 25 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 26 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 27 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 28 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 29 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 30 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 31 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 32 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 33 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 34 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 35 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 36 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 37 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 38 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 39 | -------------------------------------------------------------------------------- /cache-by-tags-in-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "time" 7 | 8 | "github.com/go-redis/redis/v7" 9 | ) 10 | 11 | func main() { 12 | client := redis.NewClient( 13 | &redis.Options{ 14 | Addr: "localhost:6379", 15 | Password: "", // no password set 16 | DB: 0, // use default DB 17 | }, 18 | ) 19 | 20 | app := cache{client: client} 21 | 22 | k := "data:key1" 23 | v := "randomstringdata" 24 | 25 | tags := make([]string, 0) 26 | for i := 1; i <= 60; i++ { 27 | tags = append(tags, fmt.Sprintf("post%d", i)) 28 | } 29 | app.SetByTags(k, v, 30*time.Minute, tags) 30 | 31 | k = "data:key2" 32 | tags = nil 33 | for i := 10; i <= 60; i++ { 34 | tags = append(tags, fmt.Sprintf("post%d", i)) 35 | } 36 | app.SetByTags(k, v, 30*time.Minute, tags) 37 | 38 | k = "data:key3" 39 | tags = nil 40 | for i := 50; i <= 60; i++ { 41 | tags = append(tags, fmt.Sprintf("post%d", i)) 42 | } 43 | app.SetByTags(k, v, 30*time.Minute, tags) 44 | 45 | tags = nil 46 | for i := 1; i <= 10; i++ { 47 | tags = append(tags, fmt.Sprintf("post%d", i)) 48 | } 49 | app.Invalidate(tags) 50 | } 51 | 52 | type cache struct { 53 | client *redis.Client 54 | } 55 | 56 | // SetByTags will set cache by given tags. 57 | func (c *cache) SetByTags(key, value string, expiry time.Duration, tags []string) { 58 | t := time.Now() 59 | 60 | pipe := c.client.TxPipeline() 61 | for _, tag := range tags { 62 | pipe.SAdd("comment_by_tags:"+tag, key) 63 | } 64 | pipe.Set(key, value, expiry) 65 | 66 | if _, err := pipe.Exec(); err != nil { 67 | log.Printf("error in pipeline: %v", err) 68 | } 69 | 70 | log.Printf("SetByTags: time take = %dms", time.Since(t).Milliseconds()) 71 | } 72 | 73 | // Invalidate will invalidate cache with given tags. 74 | func (c *cache) Invalidate(tags []string) { 75 | t := time.Now() 76 | keys := make([]string, 0) 77 | for _, tag := range tags { 78 | tagKey := "comment_by_tags:" + tag 79 | k, _ := c.client.SMembers(tagKey).Result() 80 | keys = append(keys, tagKey) 81 | keys = append(keys, k...) 82 | } 83 | c.client.Del(keys...) 84 | log.Printf("Invalidate: time take = %dms", time.Since(t).Milliseconds()) 85 | } 86 | -------------------------------------------------------------------------------- /checksum-validation-in-go/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/abvarun226/checksum-validation-in-go 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /checksum-validation-in-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/md5" 5 | "crypto/sha256" 6 | "fmt" 7 | "io" 8 | "log" 9 | "os" 10 | ) 11 | 12 | func main() { 13 | f, err := os.Open("secret.txt") 14 | if err != nil { 15 | log.Fatal(err) 16 | } 17 | defer f.Close() 18 | 19 | fmt.Printf("md5 checksum: %s\n", checksumMD5(f)) 20 | fmt.Printf("sha256 checksum: %s\n", checksumSHA256(f)) 21 | } 22 | 23 | func checksumMD5(f io.Reader) string { 24 | h := md5.New() 25 | if _, err := io.Copy(h, f); err != nil { 26 | log.Fatal(err) 27 | } 28 | 29 | return fmt.Sprintf("%x", h.Sum(nil)) 30 | } 31 | 32 | func checksumSHA256(f io.Reader) string { 33 | h := sha256.New() 34 | if _, err := io.Copy(h, f); err != nil { 35 | log.Fatal(err) 36 | } 37 | 38 | return fmt.Sprintf("%x", h.Sum(nil)) 39 | } 40 | -------------------------------------------------------------------------------- /checksum-validation-in-go/secret.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer felis odio, cursus eget ex eu, suscipit tempus felis. Praesent in tincidunt mauris. Ut cursus finibus nunc a consequat. Pellentesque interdum ipsum nulla, nec posuere nibh posuere ut. Sed euismod elit ut nunc hendrerit porta. Morbi tristique nisi quis luctus pharetra. Phasellus et blandit purus. Vestibulum magna urna, elementum at orci a, semper cursus est. Quisque tortor purus, elementum eget commodo a, luctus vitae metus. Phasellus in eleifend mauris. Ut ultrices lacus et magna volutpat, vitae commodo ante malesuada. Curabitur luctus, tellus in cursus consectetur, nisl ex sagittis lacus, et blandit lacus tellus eget dui. Integer condimentum nunc turpis. -------------------------------------------------------------------------------- /context-cancellation-in-go/exampleOne.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | func exampleOne() { 11 | ctx, cancelFunc := context.WithCancel(context.Background()) 12 | 13 | wg := new(sync.WaitGroup) 14 | wg.Add(2) // we will start two ticker goroutines. 15 | 16 | go func() { 17 | // start the two ticker functions in separate goroutines. 18 | go runTicker(ctx, wg) 19 | go anotherTicker(ctx, wg) 20 | 21 | // sleep for 10s for ticker functions to print something to the console. 22 | time.Sleep(10 * time.Second) 23 | 24 | // after 10s, cancel the context. 25 | cancelFunc() 26 | }() 27 | 28 | // wait for the ticker functions to complete. 29 | wg.Wait() 30 | } 31 | 32 | func anotherTicker(ctx context.Context, wg *sync.WaitGroup) { 33 | defer wg.Done() 34 | for { 35 | select { 36 | case <-time.After(2 * time.Second): 37 | sleepContext(ctx, time.Minute) // sleep here indicates some work. 38 | fmt.Println(time.Now(), "another ticker executed") 39 | case <-ctx.Done(): 40 | return 41 | } 42 | } 43 | 44 | } 45 | 46 | func runTicker(ctx context.Context, wg *sync.WaitGroup) { 47 | defer wg.Done() 48 | for { 49 | select { 50 | case <-time.After(2 * time.Second): 51 | fmt.Println(time.Now(), "ticker executed") 52 | case <-ctx.Done(): 53 | return 54 | } 55 | } 56 | } 57 | 58 | // a sleep function that honors context cancellation. 59 | func sleepContext(ctx context.Context, delay time.Duration) { 60 | select { 61 | case <-ctx.Done(): 62 | case <-time.After(delay): 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /context-cancellation-in-go/exampleTwo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | func exampleTwo() { 10 | ctx, cancelFunc := context.WithCancel(context.Background()) 11 | cancelFunc() // cancel the context immediately. 12 | 13 | for i := 0; i < 5; i++ { 14 | execute(ctx) // execute function 5 times, each time there is no sleep. 15 | } 16 | } 17 | 18 | func execute(ctx context.Context) { 19 | fmt.Println(time.Now(), "executing func") 20 | 21 | // since ctx was cancelled immediately, sleepContext will return immediately without any sleep. 22 | sleepContext(ctx, 5*time.Second) 23 | } 24 | -------------------------------------------------------------------------------- /context-cancellation-in-go/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/abvarun226/context-cancellation 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /context-cancellation-in-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | example := flag.Int("example", 1, "the example to run") 10 | flag.Parse() 11 | 12 | switch *example { 13 | case 1: 14 | fmt.Printf("===== Running example 1 =====\n\n") 15 | exampleOne() 16 | 17 | case 2: 18 | fmt.Printf("===== Running example 2 =====\n\n") 19 | exampleTwo() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /create-queues-in-aws-sqs-using-go/go.mod: -------------------------------------------------------------------------------- 1 | module coding-library/sqs 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/aws/aws-sdk-go-v2 v1.16.16 7 | github.com/aws/aws-sdk-go-v2/config v1.17.7 8 | github.com/aws/aws-sdk-go-v2/service/sqs v1.19.10 9 | ) 10 | 11 | require ( 12 | github.com/aws/aws-sdk-go-v2/credentials v1.12.20 // indirect 13 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 // indirect 14 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 // indirect 15 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 // indirect 16 | github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 // indirect 17 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect 18 | github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 // indirect 19 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5 // indirect 20 | github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 // indirect 21 | github.com/aws/smithy-go v1.13.3 // indirect 22 | ) 23 | -------------------------------------------------------------------------------- /create-queues-in-aws-sqs-using-go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= 2 | github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= 3 | github.com/aws/aws-sdk-go-v2/config v1.17.7 h1:odVM52tFHhpqZBKNjVW5h+Zt1tKHbhdTQRb+0WHrNtw= 4 | github.com/aws/aws-sdk-go-v2/config v1.17.7/go.mod h1:dN2gja/QXxFF15hQreyrqYhLBaQo1d9ZKe/v/uplQoI= 5 | github.com/aws/aws-sdk-go-v2/credentials v1.12.20 h1:9+ZhlDY7N9dPnUmf7CDfW9In4sW5Ff3bh7oy4DzS1IE= 6 | github.com/aws/aws-sdk-go-v2/credentials v1.12.20/go.mod h1:UKY5HyIux08bbNA7Blv4PcXQ8cTkGh7ghHMFklaviR4= 7 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 h1:r08j4sbZu/RVi+BNxkBJwPMUYY3P8mgSDuKkZ/ZN1lE= 8 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17/go.mod h1:yIkQcCDYNsZfXpd5UX2Cy+sWA1jPgIhGTw9cOBzfVnQ= 9 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 h1:s4g/wnzMf+qepSNgTvaQQHNxyMLKSawNhKCPNy++2xY= 10 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= 11 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 h1:/K482T5A3623WJgWT8w1yRAFK4RzGzEl7y39yhtn9eA= 12 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= 13 | github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 h1:wj5Rwc05hvUSvKuOF29IYb9QrCLjU+rHAy/x/o0DK2c= 14 | github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24/go.mod h1:jULHjqqjDlbyTa7pfM7WICATnOv+iOhjletM3N0Xbu8= 15 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 h1:Jrd/oMh0PKQc6+BowB+pLEwLIgaQF29eYbe7E1Av9Ug= 16 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17/go.mod h1:4nYOrY41Lrbk2170/BGkcJKBhws9Pfn8MG3aGqjjeFI= 17 | github.com/aws/aws-sdk-go-v2/service/sqs v1.19.10 h1:Y4civ9pg5cbQkSf/YGMfFZaIPAAAK61JV+NIzO8Ri4k= 18 | github.com/aws/aws-sdk-go-v2/service/sqs v1.19.10/go.mod h1:65Z/rmGw/6usiOFI0Tk4ddNUmPbjjPER1WLZwnFqxFM= 19 | github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 h1:pwvCchFUEnlceKIgPUouBJwK81aCkQ8UDMORfeFtW10= 20 | github.com/aws/aws-sdk-go-v2/service/sso v1.11.23/go.mod h1:/w0eg9IhFGjGyyncHIQrXtU8wvNsTJOP0R6PPj0wf80= 21 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5 h1:GUnZ62TevLqIoDyHeiWj2P7EqaosgakBKVvWriIdLQY= 22 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5/go.mod h1:csZuQY65DAdFBt1oIjO5hhBR49kQqop4+lcuCjf2arA= 23 | github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 h1:9pPi0PsFNAGILFfPCk8Y0iyEBGc6lu6OQ97U7hmdesg= 24 | github.com/aws/aws-sdk-go-v2/service/sts v1.16.19/go.mod h1:h4J3oPZQbxLhzGnk+j9dfYHi5qIOVJ5kczZd658/ydM= 25 | github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA= 26 | github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= 27 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 28 | github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 29 | github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 30 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 31 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 32 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 33 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 34 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 35 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 36 | -------------------------------------------------------------------------------- /create-queues-in-aws-sqs-using-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "log" 7 | 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/config" 10 | "github.com/aws/aws-sdk-go-v2/service/sqs" 11 | ) 12 | 13 | type SQSQueueAPI interface { 14 | CreateQueue(ctx context.Context, 15 | params *sqs.CreateQueueInput, 16 | optFns ...func(*sqs.Options)) (*sqs.CreateQueueOutput, error) 17 | } 18 | 19 | func CreateQueue(c context.Context, api SQSQueueAPI, input *sqs.CreateQueueInput) (*sqs.CreateQueueOutput, error) { 20 | return api.CreateQueue(c, input) 21 | } 22 | 23 | // creates an sqs client. 24 | func client(awsURL, region string) *sqs.Client { 25 | // customResolver is required here since we use localstack and need to point the aws url to localhost. 26 | customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) { 27 | return aws.Endpoint{ 28 | PartitionID: "aws", 29 | URL: awsURL, 30 | SigningRegion: region, 31 | }, nil 32 | 33 | }) 34 | 35 | // load the default aws config along with custom resolver. 36 | cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(customResolver)) 37 | if err != nil { 38 | log.Fatalf("configuration error: %v", err) 39 | } 40 | 41 | return sqs.NewFromConfig(cfg) 42 | } 43 | 44 | // create a queue with the given name and attribute. 45 | func createQueue(c *sqs.Client, queue *string, attr map[string]string) { 46 | input := &sqs.CreateQueueInput{ 47 | QueueName: queue, 48 | Attributes: attr, 49 | } 50 | 51 | result, err := CreateQueue(context.TODO(), c, input) 52 | if err != nil { 53 | log.Printf("error creating the queue: %v", err) 54 | return 55 | } 56 | 57 | log.Printf("Queue URL: %s", *result.QueueUrl) 58 | } 59 | 60 | func main() { 61 | // name of the queue as a command line option. 62 | queue := flag.String("q", "", "name of the queue") 63 | flag.Parse() 64 | 65 | // queue cannot be empty string. 66 | if *queue == "" { 67 | log.Println("-q argument is required. Specify a name for the queue") 68 | return 69 | } 70 | 71 | awsURL := "http://127.0.0.1:4566" 72 | awsRegion := "us-west-2" 73 | 74 | // create aws client. 75 | c := client(awsURL, awsRegion) 76 | 77 | // queue attributes. 78 | queueAttributes := map[string]string{ 79 | "DelaySeconds": "60", 80 | "MessageRetentionPeriod": "86400", 81 | } 82 | 83 | // create a queue with the given name. 84 | createQueue(c, queue, queueAttributes) 85 | } 86 | -------------------------------------------------------------------------------- /delete-files-in-aws-s3-using-go/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | localstack: 4 | image: localstack/localstack 5 | ports: 6 | - 4566:4566 7 | environment: 8 | - SERVICES=s3 -------------------------------------------------------------------------------- /delete-files-in-aws-s3-using-go/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/abvarun226/aws-s3 2 | 3 | go 1.17 4 | 5 | require github.com/aws/aws-sdk-go v1.42.23 6 | 7 | require github.com/jmespath/go-jmespath v0.4.0 // indirect 8 | -------------------------------------------------------------------------------- /delete-files-in-aws-s3-using-go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/aws/aws-sdk-go v1.42.23 h1:V0V5hqMEyVelgpu1e4gMPVCJ+KhmscdNxP/NWP1iCOA= 2 | github.com/aws/aws-sdk-go v1.42.23/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs= 3 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= 6 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 7 | github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= 8 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 9 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 10 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 11 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 12 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 13 | golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= 14 | golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 15 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 16 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 17 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 18 | golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 19 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 20 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 21 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 22 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 23 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 24 | -------------------------------------------------------------------------------- /delete-files-in-aws-s3-using-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "github.com/aws/aws-sdk-go/aws" 8 | "github.com/aws/aws-sdk-go/aws/awserr" 9 | "github.com/aws/aws-sdk-go/aws/session" 10 | "github.com/aws/aws-sdk-go/service/s3" 11 | "github.com/aws/aws-sdk-go/service/s3/s3manager" 12 | ) 13 | 14 | func main() { 15 | ctx := context.Background() 16 | bucket := "work-with-s3" 17 | 18 | conf := aws.NewConfig(). 19 | WithRegion("us-west-2"). 20 | WithEndpoint("http://127.0.0.1:4566"). 21 | WithS3ForcePathStyle(true) 22 | 23 | sess, err := session.NewSession(conf) 24 | if err != nil { 25 | log.Fatalf("failed to create a new aws session: %v", sess) 26 | } 27 | 28 | s3client := s3.New(sess) 29 | 30 | // create a new s3 bucket. 31 | if _, err := s3client.CreateBucket(&s3.CreateBucketInput{Bucket: aws.String(bucket)}); err != nil { 32 | if aerr, ok := err.(awserr.Error); ok && aerr.Code() != "Conflict" && aerr.Code() != "BucketAlreadyOwnedByYou" { 33 | log.Fatalf("failed to create a new s3 bucket: %v", err) 34 | } 35 | } 36 | 37 | // iterator to delete all files under `blog` directory. 38 | iter := s3manager.NewDeleteListIterator(s3client, &s3.ListObjectsInput{ 39 | Bucket: aws.String(bucket), 40 | Prefix: aws.String("blog/"), 41 | }) 42 | 43 | // use the iterator to delete the files. 44 | if err := s3manager.NewBatchDeleteWithClient(s3client).Delete(ctx, iter); err != nil { 45 | log.Fatalf("failed to delete files under given directory: %v", err) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /delete-queues-in-aws-sqs-using-go/go.mod: -------------------------------------------------------------------------------- 1 | module coding-library/sqs 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/aws/aws-sdk-go-v2 v1.16.16 7 | github.com/aws/aws-sdk-go-v2/config v1.17.7 8 | github.com/aws/aws-sdk-go-v2/service/sqs v1.19.10 9 | ) 10 | 11 | require ( 12 | github.com/aws/aws-sdk-go-v2/credentials v1.12.20 // indirect 13 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 // indirect 14 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 // indirect 15 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 // indirect 16 | github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 // indirect 17 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect 18 | github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 // indirect 19 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5 // indirect 20 | github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 // indirect 21 | github.com/aws/smithy-go v1.13.3 // indirect 22 | ) 23 | -------------------------------------------------------------------------------- /delete-queues-in-aws-sqs-using-go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= 2 | github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= 3 | github.com/aws/aws-sdk-go-v2/config v1.17.7 h1:odVM52tFHhpqZBKNjVW5h+Zt1tKHbhdTQRb+0WHrNtw= 4 | github.com/aws/aws-sdk-go-v2/config v1.17.7/go.mod h1:dN2gja/QXxFF15hQreyrqYhLBaQo1d9ZKe/v/uplQoI= 5 | github.com/aws/aws-sdk-go-v2/credentials v1.12.20 h1:9+ZhlDY7N9dPnUmf7CDfW9In4sW5Ff3bh7oy4DzS1IE= 6 | github.com/aws/aws-sdk-go-v2/credentials v1.12.20/go.mod h1:UKY5HyIux08bbNA7Blv4PcXQ8cTkGh7ghHMFklaviR4= 7 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 h1:r08j4sbZu/RVi+BNxkBJwPMUYY3P8mgSDuKkZ/ZN1lE= 8 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17/go.mod h1:yIkQcCDYNsZfXpd5UX2Cy+sWA1jPgIhGTw9cOBzfVnQ= 9 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 h1:s4g/wnzMf+qepSNgTvaQQHNxyMLKSawNhKCPNy++2xY= 10 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= 11 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 h1:/K482T5A3623WJgWT8w1yRAFK4RzGzEl7y39yhtn9eA= 12 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= 13 | github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 h1:wj5Rwc05hvUSvKuOF29IYb9QrCLjU+rHAy/x/o0DK2c= 14 | github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24/go.mod h1:jULHjqqjDlbyTa7pfM7WICATnOv+iOhjletM3N0Xbu8= 15 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 h1:Jrd/oMh0PKQc6+BowB+pLEwLIgaQF29eYbe7E1Av9Ug= 16 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17/go.mod h1:4nYOrY41Lrbk2170/BGkcJKBhws9Pfn8MG3aGqjjeFI= 17 | github.com/aws/aws-sdk-go-v2/service/sqs v1.19.10 h1:Y4civ9pg5cbQkSf/YGMfFZaIPAAAK61JV+NIzO8Ri4k= 18 | github.com/aws/aws-sdk-go-v2/service/sqs v1.19.10/go.mod h1:65Z/rmGw/6usiOFI0Tk4ddNUmPbjjPER1WLZwnFqxFM= 19 | github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 h1:pwvCchFUEnlceKIgPUouBJwK81aCkQ8UDMORfeFtW10= 20 | github.com/aws/aws-sdk-go-v2/service/sso v1.11.23/go.mod h1:/w0eg9IhFGjGyyncHIQrXtU8wvNsTJOP0R6PPj0wf80= 21 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5 h1:GUnZ62TevLqIoDyHeiWj2P7EqaosgakBKVvWriIdLQY= 22 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5/go.mod h1:csZuQY65DAdFBt1oIjO5hhBR49kQqop4+lcuCjf2arA= 23 | github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 h1:9pPi0PsFNAGILFfPCk8Y0iyEBGc6lu6OQ97U7hmdesg= 24 | github.com/aws/aws-sdk-go-v2/service/sts v1.16.19/go.mod h1:h4J3oPZQbxLhzGnk+j9dfYHi5qIOVJ5kczZd658/ydM= 25 | github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA= 26 | github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= 27 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 28 | github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 29 | github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 30 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 31 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 32 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 33 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 34 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 35 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 36 | -------------------------------------------------------------------------------- /delete-queues-in-aws-sqs-using-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "log" 7 | 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/config" 10 | "github.com/aws/aws-sdk-go-v2/service/sqs" 11 | ) 12 | 13 | type SQSQueueAPI interface { 14 | GetQueueUrl(ctx context.Context, 15 | params *sqs.GetQueueUrlInput, 16 | optFns ...func(*sqs.Options)) (*sqs.GetQueueUrlOutput, error) 17 | 18 | DeleteQueue(ctx context.Context, 19 | params *sqs.DeleteQueueInput, 20 | optFns ...func(*sqs.Options)) (*sqs.DeleteQueueOutput, error) 21 | } 22 | 23 | func GetQueueURL(c context.Context, api SQSQueueAPI, input *sqs.GetQueueUrlInput) (*sqs.GetQueueUrlOutput, error) { 24 | return api.GetQueueUrl(c, input) 25 | } 26 | 27 | func DeleteQueue(c context.Context, api SQSQueueAPI, input *sqs.DeleteQueueInput) (*sqs.DeleteQueueOutput, error) { 28 | return api.DeleteQueue(c, input) 29 | } 30 | 31 | // creates an sqs client. 32 | func client(ctx context.Context, awsURL, region string) *sqs.Client { 33 | // customResolver is required here since we use localstack and need to point the aws url to localhost. 34 | customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) { 35 | return aws.Endpoint{ 36 | PartitionID: "aws", 37 | URL: awsURL, 38 | SigningRegion: region, 39 | }, nil 40 | 41 | }) 42 | 43 | // load the default aws config along with custom resolver. 44 | cfg, err := config.LoadDefaultConfig(ctx, config.WithEndpointResolverWithOptions(customResolver)) 45 | if err != nil { 46 | log.Fatalf("configuration error: %v", err) 47 | } 48 | 49 | return sqs.NewFromConfig(cfg) 50 | } 51 | 52 | // delete a queue with the given name. 53 | func deleteQueue(ctx context.Context, c *sqs.Client, queue *string) { 54 | // Get the URL for the queue 55 | input := &sqs.GetQueueUrlInput{ 56 | QueueName: queue, 57 | } 58 | resultGet, err := GetQueueURL(ctx, c, input) 59 | if err != nil { 60 | log.Printf("error getting the queue URL: %v", err) 61 | return 62 | } 63 | queueURL := resultGet.QueueUrl 64 | 65 | // delete the queue using the queue URL 66 | dqInput := &sqs.DeleteQueueInput{ 67 | QueueUrl: queueURL, 68 | } 69 | if _, err := DeleteQueue(ctx, c, dqInput); err != nil { 70 | log.Printf("error deleting the queue: %v", err) 71 | return 72 | } 73 | 74 | log.Printf("deleted queue with URL: %s", *queueURL) 75 | } 76 | 77 | func main() { 78 | ctx := context.TODO() 79 | 80 | // name of the queue as a command line option. 81 | queue := flag.String("q", "", "name of the queue") 82 | flag.Parse() 83 | 84 | // queue cannot be empty string. 85 | if *queue == "" { 86 | log.Println("-q argument is required. Specify a name for the queue") 87 | return 88 | } 89 | 90 | awsURL := "http://127.0.0.1:4566" 91 | awsRegion := "us-west-2" 92 | 93 | // create aws client. 94 | c := client(ctx, awsURL, awsRegion) 95 | 96 | // delete a queue with the given name. 97 | deleteQueue(ctx, c, queue) 98 | } 99 | -------------------------------------------------------------------------------- /how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack/create.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/aws/aws-sdk-go/aws" 8 | "github.com/aws/aws-sdk-go/service/dynamodb" 9 | ) 10 | 11 | func createTable(svc *dynamodb.DynamoDB) { 12 | input := &dynamodb.CreateTableInput{ 13 | AttributeDefinitions: []*dynamodb.AttributeDefinition{ 14 | {AttributeName: aws.String("ID"), AttributeType: aws.String("N")}, 15 | }, 16 | KeySchema: []*dynamodb.KeySchemaElement{ 17 | {AttributeName: aws.String("ID"), KeyType: aws.String("HASH")}, 18 | }, 19 | ProvisionedThroughput: &dynamodb.ProvisionedThroughput{ 20 | ReadCapacityUnits: aws.Int64(5), 21 | WriteCapacityUnits: aws.Int64(5), 22 | }, 23 | TableName: aws.String("Employee"), 24 | } 25 | 26 | if _, err := svc.CreateTable(input); err != nil { 27 | log.Fatalf("failed to create table: %v", err) 28 | } 29 | 30 | fmt.Println("Table created successfully") 31 | } 32 | -------------------------------------------------------------------------------- /how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack/delete.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/aws/aws-sdk-go/aws" 8 | "github.com/aws/aws-sdk-go/service/dynamodb" 9 | ) 10 | 11 | func delete(svc *dynamodb.DynamoDB) { 12 | input := &dynamodb.DeleteItemInput{ 13 | TableName: aws.String("Employee"), 14 | Key: map[string]*dynamodb.AttributeValue{ 15 | "ID": { 16 | N: aws.String("1"), 17 | }, 18 | }, 19 | } 20 | 21 | if _, err := svc.DeleteItem(input); err != nil { 22 | log.Fatalf("failed to delete item: %v", err) 23 | } 24 | 25 | fmt.Println("Item deleted successfully") 26 | } 27 | -------------------------------------------------------------------------------- /how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack/deleteTable.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/aws/aws-sdk-go/aws" 8 | "github.com/aws/aws-sdk-go/service/dynamodb" 9 | ) 10 | 11 | func deleteTable(svc *dynamodb.DynamoDB) { 12 | input := &dynamodb.DeleteTableInput{ 13 | TableName: aws.String("Employee2"), 14 | } 15 | 16 | if _, err := svc.DeleteTable(input); err != nil { 17 | log.Fatalf("failed to delete item: %v", err) 18 | } 19 | 20 | fmt.Println("Item deleted successfully") 21 | } 22 | -------------------------------------------------------------------------------- /how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack/go.mod: -------------------------------------------------------------------------------- 1 | module varun/go-dynamodb 2 | 3 | go 1.19 4 | 5 | require github.com/aws/aws-sdk-go v1.44.266 6 | 7 | require github.com/jmespath/go-jmespath v0.4.0 // indirect 8 | -------------------------------------------------------------------------------- /how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack/go.sum: -------------------------------------------------------------------------------- 1 | github.com/aws/aws-sdk-go v1.44.266 h1:MWd775dcYf7NrwgcHLtlsIbWoWkX8p4vomfNHr88zH0= 2 | github.com/aws/aws-sdk-go v1.44.266/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= 3 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= 6 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 7 | github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= 8 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 9 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 10 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 11 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 12 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 13 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 14 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 15 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 16 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 17 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 18 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 19 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 20 | golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= 21 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 22 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 23 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 24 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 25 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 26 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 27 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 28 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 29 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 30 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 31 | golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 32 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 33 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 34 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 35 | golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 36 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 37 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 38 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 39 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 40 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 41 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 42 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 43 | -------------------------------------------------------------------------------- /how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack/insert.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/aws/aws-sdk-go/aws" 8 | "github.com/aws/aws-sdk-go/service/dynamodb" 9 | "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" 10 | ) 11 | 12 | func insert(svc *dynamodb.DynamoDB) { 13 | item := Employee{ 14 | ID: 1, 15 | Name: "John Doe", 16 | Age: 30, 17 | } 18 | 19 | av, err := dynamodbattribute.MarshalMap(item) 20 | if err != nil { 21 | log.Fatalf("failed to marshal item: %v", err) 22 | } 23 | 24 | input := &dynamodb.PutItemInput{ 25 | Item: av, 26 | TableName: aws.String("Employee"), 27 | } 28 | 29 | if _, err := svc.PutItem(input); err != nil { 30 | log.Fatalf("failed to put item: %v", err) 31 | } 32 | 33 | fmt.Println("Item inserted successfully") 34 | } 35 | -------------------------------------------------------------------------------- /how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/aws/aws-sdk-go/aws" 7 | "github.com/aws/aws-sdk-go/aws/session" 8 | "github.com/aws/aws-sdk-go/service/dynamodb" 9 | ) 10 | 11 | type Employee struct { 12 | ID int 13 | Name string 14 | Age int 15 | } 16 | 17 | func main() { 18 | sess, err := session.NewSession(&aws.Config{ 19 | Region: aws.String("us-east-1"), 20 | Endpoint: aws.String("http://localhost:4566"), 21 | }) 22 | if err != nil { 23 | log.Fatalf("failed to start new session: %v", err) 24 | } 25 | 26 | svc := dynamodb.New(sess) 27 | 28 | deleteTable(svc) 29 | } 30 | -------------------------------------------------------------------------------- /how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack/query.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/aws/aws-sdk-go/aws" 8 | "github.com/aws/aws-sdk-go/service/dynamodb" 9 | "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" 10 | ) 11 | 12 | func query(svc *dynamodb.DynamoDB) { 13 | input := &dynamodb.QueryInput{ 14 | ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ 15 | ":val": { 16 | N: aws.String("1"), 17 | }, 18 | }, 19 | KeyConditionExpression: aws.String("ID = :val"), 20 | TableName: aws.String("Employee"), 21 | } 22 | 23 | result, err := svc.Query(input) 24 | if err != nil { 25 | log.Fatalf("failed to query: %v", err) 26 | return 27 | } 28 | 29 | for _, item := range result.Items { 30 | emp := Employee{} 31 | 32 | err = dynamodbattribute.UnmarshalMap(item, &emp) 33 | if err != nil { 34 | log.Fatalf("failed to unmarshal item: %v", err) 35 | return 36 | } 37 | 38 | fmt.Printf("%+v\\n", emp) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack/sortkeys/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/aws/aws-sdk-go/aws" 8 | "github.com/aws/aws-sdk-go/aws/session" 9 | "github.com/aws/aws-sdk-go/service/dynamodb" 10 | "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" 11 | ) 12 | 13 | type Employee struct { 14 | ID int 15 | Name string 16 | Age int 17 | City string 18 | Country string 19 | } 20 | 21 | func main() { 22 | sess, err := session.NewSession(&aws.Config{ 23 | Region: aws.String("us-east-1"), 24 | Endpoint: aws.String("http://localhost:4566"), 25 | }) 26 | if err != nil { 27 | log.Fatalf("failed to create new session: %v", err) 28 | } 29 | 30 | svc := dynamodb.New(sess) 31 | input := &dynamodb.CreateTableInput{ 32 | AttributeDefinitions: []*dynamodb.AttributeDefinition{ 33 | {AttributeName: aws.String("ID"), AttributeType: aws.String("N")}, 34 | {AttributeName: aws.String("Name"), AttributeType: aws.String("S")}, 35 | {AttributeName: aws.String("City"), AttributeType: aws.String("S")}, 36 | }, 37 | KeySchema: []*dynamodb.KeySchemaElement{ 38 | {AttributeName: aws.String("ID"), KeyType: aws.String("HASH")}, 39 | {AttributeName: aws.String("Name"), KeyType: aws.String("RANGE")}, 40 | }, 41 | GlobalSecondaryIndexes: []*dynamodb.GlobalSecondaryIndex{ 42 | { 43 | IndexName: aws.String("CityIndex"), 44 | KeySchema: []*dynamodb.KeySchemaElement{ 45 | {AttributeName: aws.String("ID"), KeyType: aws.String("HASH")}, 46 | {AttributeName: aws.String("City"), KeyType: aws.String("RANGE")}, 47 | }, 48 | Projection: &dynamodb.Projection{ 49 | ProjectionType: aws.String("ALL"), 50 | }, 51 | ProvisionedThroughput: &dynamodb.ProvisionedThroughput{ 52 | ReadCapacityUnits: aws.Int64(5), 53 | WriteCapacityUnits: aws.Int64(5), 54 | }, 55 | }, 56 | }, 57 | ProvisionedThroughput: &dynamodb.ProvisionedThroughput{ 58 | ReadCapacityUnits: aws.Int64(5), 59 | WriteCapacityUnits: aws.Int64(5), 60 | }, 61 | TableName: aws.String("Employee2"), 62 | } 63 | 64 | if _, err := svc.CreateTable(input); err != nil { 65 | log.Fatalf("failed to create table: %v", err) 66 | } 67 | 68 | fmt.Println("Table created successfully") 69 | 70 | item := Employee{ 71 | ID: 1, 72 | Name: "John Doe", 73 | Age: 30, 74 | City: "New York", 75 | Country: "USA", 76 | } 77 | 78 | av, err := dynamodbattribute.MarshalMap(item) 79 | if err != nil { 80 | log.Fatalf("failed to marshal item: %v", err) 81 | } 82 | 83 | input2 := &dynamodb.PutItemInput{ 84 | Item: av, 85 | TableName: aws.String("Employee2"), 86 | } 87 | 88 | if _, err := svc.PutItem(input2); err != nil { 89 | log.Fatalf("failed to insert item: %v", err) 90 | } 91 | 92 | fmt.Println("Item inserted successfully") 93 | 94 | input3 := &dynamodb.QueryInput{ 95 | ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ 96 | ":id": {N: aws.String("1")}, 97 | ":val": {S: aws.String("New York")}, 98 | }, 99 | KeyConditionExpression: aws.String("ID = :id and begins_with(City, :val)"), 100 | TableName: aws.String("Employee2"), 101 | IndexName: aws.String("CityIndex"), 102 | } 103 | 104 | result, err := svc.Query(input3) 105 | if err != nil { 106 | log.Fatalf("failed to query table: %v", err) 107 | } 108 | 109 | for _, item := range result.Items { 110 | emp := Employee{} 111 | 112 | if err := dynamodbattribute.UnmarshalMap(item, &emp); err != nil { 113 | log.Fatalf("failed to unmarshal item: %v", err) 114 | } 115 | 116 | fmt.Printf("%+v\\n", emp) 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /how-to-use-aws-dynamodb-with-go-a-practical-guide-with-localstack/update.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/aws/aws-sdk-go/aws" 8 | "github.com/aws/aws-sdk-go/service/dynamodb" 9 | ) 10 | 11 | func update(svc *dynamodb.DynamoDB) { 12 | input := &dynamodb.UpdateItemInput{ 13 | ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ 14 | ":n": { 15 | S: aws.String("Jane Doe"), 16 | }, 17 | }, 18 | TableName: aws.String("Employee"), 19 | Key: map[string]*dynamodb.AttributeValue{ 20 | "ID": { 21 | N: aws.String("1"), 22 | }, 23 | }, 24 | UpdateExpression: aws.String("set #name = :n"), 25 | ExpressionAttributeNames: map[string]*string{ 26 | "#name": aws.String("Name"), 27 | }, 28 | } 29 | 30 | if _, err := svc.UpdateItem(input); err != nil { 31 | log.Fatalf("failed to update item: %v", err) 32 | } 33 | 34 | fmt.Println("Item updated successfully") 35 | } 36 | -------------------------------------------------------------------------------- /implementing-mtls-in-go/certificate/certificate.go: -------------------------------------------------------------------------------- 1 | package certificate 2 | 3 | import ( 4 | "bytes" 5 | "crypto/rand" 6 | "crypto/rsa" 7 | "crypto/x509" 8 | "crypto/x509/pkix" 9 | "encoding/pem" 10 | "fmt" 11 | "io/ioutil" 12 | "log" 13 | "math/big" 14 | "net" 15 | "time" 16 | ) 17 | 18 | // Verification function will verify the client and server certificates using the root certificate that was provided in the function arguments. 19 | // If generateCertificate is set to true, it will also generate new client and server certificates that is signed by root certificate. 20 | func Verification(serverName string, clientPubKey, clientPrivKey, serverPubKey, serverPrivKey, rootPubKey, rootPrivKey string, generateCertificate bool) { 21 | ca, errCA := ReadCertificateAuthority(rootPubKey, rootPrivKey) 22 | if errCA != nil { 23 | log.Fatalf("failed to read ca certificate: %v", errCA) 24 | } 25 | 26 | if generateCertificate { 27 | // generate and sign client certificate using root certificate. 28 | if err := GenerateAndSignCertificate(ca, clientPubKey, clientPrivKey); err != nil { 29 | log.Fatalf("failed to generate client certificate: %v", err) 30 | } 31 | 32 | // generate and sign server certificate using root certificate. 33 | if err := GenerateAndSignCertificate(ca, serverPubKey, serverPrivKey); err != nil { 34 | log.Fatalf("failed to generate server certificate: %v", err) 35 | } 36 | } 37 | 38 | clientCert, errCert := ReadCertificate(clientPubKey, clientPrivKey) 39 | if errCert != nil { 40 | log.Fatalf("failed to read certificate: %v", errCert) 41 | } 42 | 43 | serverCert, errCert := ReadCertificate(serverPubKey, serverPrivKey) 44 | if errCert != nil { 45 | log.Fatalf("failed to read certificate: %v", errCert) 46 | } 47 | 48 | roots := x509.NewCertPool() 49 | roots.AddCert(ca.PublicKey) 50 | 51 | opts := x509.VerifyOptions{ 52 | Roots: roots, 53 | Intermediates: x509.NewCertPool(), 54 | DNSName: serverName, 55 | } 56 | 57 | // verify client certificate; return err on failure. 58 | if _, err := clientCert.PublicKey.Verify(opts); err != nil { 59 | log.Fatalf("failed to verify client certificate: %v", err) 60 | } 61 | 62 | // verify server certificate; return err on failure. 63 | if _, err := serverCert.PublicKey.Verify(opts); err != nil { 64 | log.Fatalf("failed to verify server certificate: %v", err) 65 | } 66 | 67 | log.Print("client and server cert verification succeeded") 68 | } 69 | 70 | // ReadCertificate reads and parses the certificates from files provided as argument to this function. 71 | func ReadCertificate(publicKeyFile, privateKeyFile string) (*KeyPair, error) { 72 | cert := new(KeyPair) 73 | 74 | privKey, errRead := ioutil.ReadFile(privateKeyFile) 75 | if errRead != nil { 76 | return nil, fmt.Errorf("failed to read private key: %w", errRead) 77 | } 78 | 79 | privPemBlock, _ := pem.Decode(privKey) 80 | 81 | // Note that we use PKCS1 to parse the private key here. 82 | parsedPrivKey, errParse := x509.ParsePKCS1PrivateKey(privPemBlock.Bytes) 83 | if errParse != nil { 84 | return nil, fmt.Errorf("failed to parse private key: %w", errParse) 85 | } 86 | 87 | cert.PrivateKey = parsedPrivKey 88 | 89 | pubKey, errRead := ioutil.ReadFile(publicKeyFile) 90 | if errRead != nil { 91 | return nil, fmt.Errorf("failed to read public key: %w", errRead) 92 | } 93 | 94 | publicPemBlock, _ := pem.Decode(pubKey) 95 | 96 | parsedPubKey, errParse := x509.ParseCertificate(publicPemBlock.Bytes) 97 | if errParse != nil { 98 | return nil, fmt.Errorf("failed to parse public key: %w", errParse) 99 | } 100 | 101 | cert.PublicKey = parsedPubKey 102 | 103 | return cert, nil 104 | } 105 | 106 | // ReadCertificateAuthority reads and parses the root certificate from files provided as argument to this function. 107 | func ReadCertificateAuthority(publicKeyFile, privateKeyFile string) (*KeyPair, error) { 108 | root := new(KeyPair) 109 | 110 | rootKey, errRead := ioutil.ReadFile(privateKeyFile) 111 | if errRead != nil { 112 | return nil, fmt.Errorf("failed to read private key: %w", errRead) 113 | } 114 | 115 | privPemBlock, _ := pem.Decode(rootKey) 116 | 117 | // Note that we use PKCS8 to parse the private key here. 118 | rootPrivKey, errParse := x509.ParsePKCS8PrivateKey(privPemBlock.Bytes) 119 | if errParse != nil { 120 | return nil, fmt.Errorf("failed to parse private key: %w", errParse) 121 | } 122 | 123 | root.PrivateKey = rootPrivKey.(*rsa.PrivateKey) 124 | 125 | rootCert, errRead := ioutil.ReadFile(publicKeyFile) 126 | if errRead != nil { 127 | return nil, fmt.Errorf("failed to read public key: %w", errRead) 128 | } 129 | 130 | publicPemBlock, _ := pem.Decode(rootCert) 131 | 132 | rootPubCrt, errParse := x509.ParseCertificate(publicPemBlock.Bytes) 133 | if errParse != nil { 134 | return nil, fmt.Errorf("failed to parse public key: %w", errParse) 135 | } 136 | 137 | root.PublicKey = rootPubCrt 138 | 139 | return root, nil 140 | } 141 | 142 | // GenerateAndSignCertificate method will use the root certificate's public and private key to generate a certificate and sign it. 143 | // The certificate's public and private keys will be stored in the files provided as argument to this function. 144 | func GenerateAndSignCertificate(root *KeyPair, publicKeyFile, privateKeyFile string) error { 145 | cert := &x509.Certificate{ 146 | SerialNumber: big.NewInt(1658), 147 | Subject: pkix.Name{ 148 | Organization: []string{"ayada"}, 149 | Country: []string{"US"}, 150 | Province: []string{"California"}, 151 | Locality: []string{"San Francisco"}, 152 | CommonName: "localhost", 153 | }, 154 | DNSNames: []string{"localhost", "ayada.dev"}, 155 | IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback}, 156 | NotBefore: time.Now(), 157 | NotAfter: time.Now().AddDate(10, 0, 0), 158 | SubjectKeyId: []byte{1, 2, 3, 4, 6}, 159 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, 160 | KeyUsage: x509.KeyUsageDigitalSignature, 161 | } 162 | 163 | certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096) 164 | if err != nil { 165 | return err 166 | } 167 | 168 | certBytes, err := x509.CreateCertificate(rand.Reader, cert, root.PublicKey, &certPrivKey.PublicKey, root.PrivateKey) 169 | if err != nil { 170 | return err 171 | } 172 | 173 | certPEM := new(bytes.Buffer) 174 | pem.Encode(certPEM, &pem.Block{ 175 | Type: "CERTIFICATE", 176 | Bytes: certBytes, 177 | }) 178 | 179 | certPrivKeyPEM := new(bytes.Buffer) 180 | pem.Encode(certPrivKeyPEM, &pem.Block{ 181 | Type: "RSA PRIVATE KEY", 182 | Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey), 183 | }) 184 | 185 | if err := ioutil.WriteFile(publicKeyFile, certPEM.Bytes(), 0644); err != nil { 186 | return fmt.Errorf("failed to write to public key file: %w", err) 187 | } 188 | 189 | if err := ioutil.WriteFile(privateKeyFile, certPrivKeyPEM.Bytes(), 0644); err != nil { 190 | return fmt.Errorf("failed to write to private key file: %w", err) 191 | } 192 | 193 | return nil 194 | } 195 | 196 | type KeyPair struct { 197 | PublicKey *x509.Certificate 198 | PrivateKey *rsa.PrivateKey 199 | } 200 | -------------------------------------------------------------------------------- /implementing-mtls-in-go/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/abvarun226/mtls-proxy 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /implementing-mtls-in-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/abvarun226/mtls-proxy/certificate" 5 | "github.com/abvarun226/mtls-proxy/server" 6 | ) 7 | 8 | const ( 9 | clientPublicKey = "certs/client.pem" 10 | clientPrivateKey = "certs/client.key" 11 | 12 | serverPublicKey = "certs/server.pem" 13 | serverPrivateKey = "certs/server.key" 14 | 15 | rootPublicKey = "certs/ca.pem" 16 | rootPrivateKey = "certs/ca.key" 17 | ) 18 | 19 | func main() { 20 | certificate.Verification("localhost", clientPublicKey, clientPrivateKey, serverPublicKey, serverPrivateKey, rootPublicKey, rootPrivateKey, false) 21 | 22 | srv := server.HTTPServer(serverPublicKey, serverPrivateKey, rootPublicKey) 23 | defer srv.Close() 24 | 25 | server.SendRequest(srv.URL, clientPublicKey, clientPrivateKey, rootPublicKey) 26 | } 27 | -------------------------------------------------------------------------------- /implementing-mtls-in-go/server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "encoding/pem" 7 | "fmt" 8 | "io/ioutil" 9 | "log" 10 | "net/http" 11 | "net/http/httptest" 12 | ) 13 | 14 | // HTTPServer will start a mTLS enabled httptest server and return the test server. 15 | // It requires server certificate's public and private key files and root certificate's public key file as arguments. 16 | func HTTPServer(serverPublicKey, serverPrivateKey, rootPublicKey string) *httptest.Server { 17 | // server certificate. 18 | serverCert, err := tls.LoadX509KeyPair(serverPublicKey, serverPrivateKey) 19 | if err != nil { 20 | return nil 21 | } 22 | 23 | // root certificate. 24 | rootCert, err := ioutil.ReadFile(rootPublicKey) 25 | if err != nil { 26 | log.Fatalf("failed to read root public key: %v", err) 27 | } 28 | rootCertPool := x509.NewCertPool() 29 | rootCertPool.AppendCertsFromPEM(rootCert) 30 | 31 | // httptest server with TLS config. 32 | server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 33 | fmt.Fprintln(w, "success!") 34 | })) 35 | server.TLS = &tls.Config{ 36 | Certificates: []tls.Certificate{serverCert}, 37 | ClientCAs: rootCertPool, 38 | ClientAuth: tls.RequireAndVerifyClientCert, 39 | } 40 | server.StartTLS() 41 | return server 42 | } 43 | 44 | // SendRequest function will send a GET request to the server URL provided in the argument. 45 | // It also requires client certificate's public and private key files and root certificate's public key file. 46 | func SendRequest(serverURL, clientPublicKey, clientPrivateKey, rootPublicKey string) { 47 | // root certificate public key 48 | rootCert, errRead := ioutil.ReadFile(rootPublicKey) 49 | if errRead != nil { 50 | log.Fatalf("failed to read public key: %v", errRead) 51 | } 52 | publicPemBlock, _ := pem.Decode(rootCert) 53 | rootPubCrt, errParse := x509.ParseCertificate(publicPemBlock.Bytes) 54 | if errParse != nil { 55 | log.Fatalf("failed to parse public key: %v", errParse) 56 | } 57 | 58 | rootCertpool := x509.NewCertPool() 59 | rootCertpool.AddCert(rootPubCrt) 60 | 61 | // client certificates. 62 | cert, err := tls.LoadX509KeyPair(clientPublicKey, clientPrivateKey) 63 | if err != nil { 64 | log.Fatalf("failed to load client certificate: %v", err) 65 | } 66 | 67 | // http client with root and client certificates. 68 | client := http.Client{ 69 | Transport: &http.Transport{ 70 | TLSClientConfig: &tls.Config{ 71 | RootCAs: rootCertpool, 72 | Certificates: []tls.Certificate{cert}, 73 | }, 74 | }, 75 | } 76 | 77 | resp, err := client.Get(serverURL) 78 | if err != nil { 79 | log.Printf("failed to GET: %v", err) 80 | return 81 | } 82 | 83 | body, errRead := ioutil.ReadAll(resp.Body) 84 | if errRead != nil { 85 | log.Printf("failed to read body: %v", err) 86 | return 87 | } 88 | defer resp.Body.Close() 89 | 90 | log.Printf("successful GET: %s", string(body)) 91 | } 92 | -------------------------------------------------------------------------------- /list-queues-in-aws-sqs-using-go/go.mod: -------------------------------------------------------------------------------- 1 | module coding-library/sqs 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/aws/aws-sdk-go-v2 v1.16.16 7 | github.com/aws/aws-sdk-go-v2/config v1.17.7 8 | github.com/aws/aws-sdk-go-v2/service/sqs v1.19.10 9 | ) 10 | 11 | require ( 12 | github.com/aws/aws-sdk-go-v2/credentials v1.12.20 // indirect 13 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 // indirect 14 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 // indirect 15 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 // indirect 16 | github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 // indirect 17 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect 18 | github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 // indirect 19 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5 // indirect 20 | github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 // indirect 21 | github.com/aws/smithy-go v1.13.3 // indirect 22 | ) 23 | -------------------------------------------------------------------------------- /list-queues-in-aws-sqs-using-go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= 2 | github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= 3 | github.com/aws/aws-sdk-go-v2/config v1.17.7 h1:odVM52tFHhpqZBKNjVW5h+Zt1tKHbhdTQRb+0WHrNtw= 4 | github.com/aws/aws-sdk-go-v2/config v1.17.7/go.mod h1:dN2gja/QXxFF15hQreyrqYhLBaQo1d9ZKe/v/uplQoI= 5 | github.com/aws/aws-sdk-go-v2/credentials v1.12.20 h1:9+ZhlDY7N9dPnUmf7CDfW9In4sW5Ff3bh7oy4DzS1IE= 6 | github.com/aws/aws-sdk-go-v2/credentials v1.12.20/go.mod h1:UKY5HyIux08bbNA7Blv4PcXQ8cTkGh7ghHMFklaviR4= 7 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 h1:r08j4sbZu/RVi+BNxkBJwPMUYY3P8mgSDuKkZ/ZN1lE= 8 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17/go.mod h1:yIkQcCDYNsZfXpd5UX2Cy+sWA1jPgIhGTw9cOBzfVnQ= 9 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 h1:s4g/wnzMf+qepSNgTvaQQHNxyMLKSawNhKCPNy++2xY= 10 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= 11 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 h1:/K482T5A3623WJgWT8w1yRAFK4RzGzEl7y39yhtn9eA= 12 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= 13 | github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 h1:wj5Rwc05hvUSvKuOF29IYb9QrCLjU+rHAy/x/o0DK2c= 14 | github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24/go.mod h1:jULHjqqjDlbyTa7pfM7WICATnOv+iOhjletM3N0Xbu8= 15 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 h1:Jrd/oMh0PKQc6+BowB+pLEwLIgaQF29eYbe7E1Av9Ug= 16 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17/go.mod h1:4nYOrY41Lrbk2170/BGkcJKBhws9Pfn8MG3aGqjjeFI= 17 | github.com/aws/aws-sdk-go-v2/service/sqs v1.19.10 h1:Y4civ9pg5cbQkSf/YGMfFZaIPAAAK61JV+NIzO8Ri4k= 18 | github.com/aws/aws-sdk-go-v2/service/sqs v1.19.10/go.mod h1:65Z/rmGw/6usiOFI0Tk4ddNUmPbjjPER1WLZwnFqxFM= 19 | github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 h1:pwvCchFUEnlceKIgPUouBJwK81aCkQ8UDMORfeFtW10= 20 | github.com/aws/aws-sdk-go-v2/service/sso v1.11.23/go.mod h1:/w0eg9IhFGjGyyncHIQrXtU8wvNsTJOP0R6PPj0wf80= 21 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5 h1:GUnZ62TevLqIoDyHeiWj2P7EqaosgakBKVvWriIdLQY= 22 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5/go.mod h1:csZuQY65DAdFBt1oIjO5hhBR49kQqop4+lcuCjf2arA= 23 | github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 h1:9pPi0PsFNAGILFfPCk8Y0iyEBGc6lu6OQ97U7hmdesg= 24 | github.com/aws/aws-sdk-go-v2/service/sts v1.16.19/go.mod h1:h4J3oPZQbxLhzGnk+j9dfYHi5qIOVJ5kczZd658/ydM= 25 | github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA= 26 | github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= 27 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 28 | github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 29 | github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 30 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 31 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 32 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 33 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 34 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 35 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 36 | -------------------------------------------------------------------------------- /list-queues-in-aws-sqs-using-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "github.com/aws/aws-sdk-go-v2/aws" 8 | "github.com/aws/aws-sdk-go-v2/config" 9 | "github.com/aws/aws-sdk-go-v2/service/sqs" 10 | ) 11 | 12 | type SQSQueueAPI interface { 13 | ListQueues(ctx context.Context, 14 | params *sqs.ListQueuesInput, 15 | optFns ...func(*sqs.Options)) (*sqs.ListQueuesOutput, error) 16 | } 17 | 18 | func ListQueues(c context.Context, api SQSQueueAPI, input *sqs.ListQueuesInput) (*sqs.ListQueuesOutput, error) { 19 | return api.ListQueues(c, input) 20 | } 21 | 22 | // creates an sqs client. 23 | func client(ctx context.Context, awsURL, region string) *sqs.Client { 24 | // customResolver is required here since we use localstack and need to point the aws url to localhost. 25 | customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) { 26 | return aws.Endpoint{ 27 | PartitionID: "aws", 28 | URL: awsURL, 29 | SigningRegion: region, 30 | }, nil 31 | 32 | }) 33 | 34 | // load the default aws config along with custom resolver. 35 | cfg, err := config.LoadDefaultConfig(ctx, config.WithEndpointResolverWithOptions(customResolver)) 36 | if err != nil { 37 | log.Fatalf("configuration error: %v", err) 38 | } 39 | 40 | return sqs.NewFromConfig(cfg) 41 | } 42 | 43 | // list all queues in AWS SQS account. 44 | func listQueues(ctx context.Context, c *sqs.Client) { 45 | inputList := &sqs.ListQueuesInput{} 46 | 47 | resultList, err := ListQueues(ctx, c, inputList) 48 | if err != nil { 49 | log.Printf("error retrieving queue URLs: %v", err) 50 | return 51 | } 52 | 53 | for i, url := range resultList.QueueUrls { 54 | log.Printf("%d: %s", i+1, url) 55 | } 56 | } 57 | 58 | func main() { 59 | ctx := context.TODO() 60 | 61 | awsURL := "http://127.0.0.1:4566" 62 | awsRegion := "us-west-2" 63 | 64 | // create aws client. 65 | c := client(ctx, awsURL, awsRegion) 66 | 67 | // list all queues in the SQS account. 68 | listQueues(ctx, c) 69 | } 70 | -------------------------------------------------------------------------------- /listing-files-in-aws-s3-using-go/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | localstack: 4 | image: localstack/localstack 5 | ports: 6 | - 4566:4566 7 | environment: 8 | - SERVICES=s3 -------------------------------------------------------------------------------- /listing-files-in-aws-s3-using-go/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/abvarun226/aws-s3-list 2 | 3 | go 1.17 4 | 5 | require github.com/aws/aws-sdk-go v1.42.23 6 | 7 | require github.com/jmespath/go-jmespath v0.4.0 // indirect 8 | -------------------------------------------------------------------------------- /listing-files-in-aws-s3-using-go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/aws/aws-sdk-go v1.42.23 h1:V0V5hqMEyVelgpu1e4gMPVCJ+KhmscdNxP/NWP1iCOA= 2 | github.com/aws/aws-sdk-go v1.42.23/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs= 3 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= 6 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 7 | github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= 8 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 9 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 10 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 11 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 12 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 13 | golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= 14 | golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 15 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 16 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 17 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 18 | golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 19 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 20 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 21 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 22 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 23 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 24 | -------------------------------------------------------------------------------- /listing-files-in-aws-s3-using-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "github.com/aws/aws-sdk-go/aws" 8 | "github.com/aws/aws-sdk-go/aws/awserr" 9 | "github.com/aws/aws-sdk-go/aws/session" 10 | "github.com/aws/aws-sdk-go/service/s3" 11 | ) 12 | 13 | func main() { 14 | ctx := context.Background() 15 | bucket := "work-with-s3" 16 | 17 | conf := aws.NewConfig(). 18 | WithRegion("us-west-2"). 19 | WithEndpoint("http://127.0.0.1:4566"). 20 | WithS3ForcePathStyle(true) 21 | 22 | sess, err := session.NewSession(conf) 23 | if err != nil { 24 | log.Fatalf("failed to create a new aws session: %v", sess) 25 | } 26 | 27 | s3client := s3.New(sess) 28 | 29 | // create a new s3 bucket. 30 | if _, err := s3client.CreateBucket(&s3.CreateBucketInput{Bucket: aws.String(bucket)}); err != nil { 31 | if aerr, ok := err.(awserr.Error); ok && aerr.Code() != "Conflict" && aerr.Code() != "BucketAlreadyOwnedByYou" { 32 | log.Fatalf("failed to create a new s3 bucket: %v", err) 33 | } 34 | } 35 | 36 | s3Keys := make([]string, 0) 37 | 38 | // list files under `blog` directory in `work-with-s3` bucket. 39 | if err := s3client.ListObjectsPagesWithContext(ctx, &s3.ListObjectsInput{ 40 | Bucket: aws.String(bucket), 41 | Prefix: aws.String("blog/"), // list files in the directory. 42 | }, func(o *s3.ListObjectsOutput, b bool) bool { // callback func to enable paging. 43 | for _, o := range o.Contents { 44 | s3Keys = append(s3Keys, *o.Key) 45 | } 46 | return true 47 | }); err != nil { 48 | log.Fatalf("failed to list items in s3 directory: %v", err) 49 | } 50 | 51 | log.Printf("number of files under `blog` directory: %d", len(s3Keys)) 52 | for _, k := range s3Keys { 53 | log.Printf("file: %s", k) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /multipart-requests-in-go/multipart-form-data/client.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 |