{"id":16179225,"url":"https://github.com/jonashackt/microservice-example-go","last_synced_at":"2025-08-13T20:33:29.042Z","repository":{"id":57562979,"uuid":"168216886","full_name":"jonashackt/microservice-example-go","owner":"jonashackt","description":"Example project showing how to create a simple Microservice with Go","archived":false,"fork":false,"pushed_at":"2019-02-28T07:04:47.000Z","size":23,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-27T21:00:00.370Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonashackt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-29T19:43:08.000Z","updated_at":"2024-09-23T18:53:00.000Z","dependencies_parsed_at":"2022-09-18T05:00:21.883Z","dependency_job_id":null,"html_url":"https://github.com/jonashackt/microservice-example-go","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fmicroservice-example-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fmicroservice-example-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fmicroservice-example-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fmicroservice-example-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonashackt","download_url":"https://codeload.github.com/jonashackt/microservice-example-go/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229780099,"owners_count":18122920,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-10T05:26:06.596Z","updated_at":"2024-12-15T04:08:41.770Z","avatar_url":"https://github.com/jonashackt.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# microservice-example-go\nExample project showing how to create a simple Microservice with Go\n\n\n# Getting started\n\nInspired by\n\nhttps://dzone.com/articles/go-microservices-blog-series-part-1\nhttps://dzone.com/articles/go-microservices-part-2-building-our-first-service\n\n## Setup a GO dev environment\n\n### GO workspace\n\nhttps://golang.org/doc/code.html\n\n`mkdir goworkspace`\n\nNow make this directory you 'central' go workspace on this machine:\n\n```\nexport GOPATH=`pwd`\n```\n\nAlso add this to your `~/.bash_profile`, e.g.:\n\n`export GOPATH=/Users/jonashecht/dev/goworkspace`\n\n\n### Install SDK\n\nhttps://golang.org/doc/install\n\n`brew install go` \n\n### IDE\n\nIntelliJ with Go Plugin or Goland, both from Jetbrains (see https://www.jetbrains.com/go/)\n\n### Create first project\n\n```\n$ cd goworkspace\nmkdir src/github.com/YourUserNameHere/microservice-example-go\ncd microservice-example-go\nmkdir accountservice\ncd accountservice\ntouch main.go\n```\n\nOpen the project in IntelliJ.\n\nNow implement the `main.go`:\n\n```go\npackage main\n\nimport (\n\n        \"fmt\"\n\n        )\n\nvar appName = \"accountservice\"\n\nfunc main() {\n\n    fmt.Printf(\"Starting %v\\n\", appName)\n\n}\n```\n\n### Run first go app\n\n```\ngo run *.go\n```\n\n# HTTP endpoints with Go\n\nsee https://thenewstack.io/make-a-restful-json-api-go/\n\n\n### Bootstrapping a HTTP server\n\nCreate a new dir and file `service/webservice.go` inside `accountservice`:\n\n```go\npackage service\n\nimport (\n\n\t\"net/http\"\n\n\t\"log\"\n\n)\n\nfunc StartWebServer(port string) {\n\n\tlog.Println(\"Starting HTTP service at \" + port)\n\n\terr := http.ListenAndServe(\":\" + port, nil)    // Goroutine will block here\n\n\tif err != nil {\n\n\t\tlog.Println(\"An error occured starting HTTP listener at port \" + port)\n\n\t\tlog.Println(\"Error: \" + err.Error())\n\n\t}\n\n}\n```\n\nUpdate [main.go](accountservice/main.go) to startup HTTP server:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/jonashackt/microservice-example-go/accountservice/service\"\n)\n\nvar appName = \"accountservice\"\n\nfunc main() {\n\n\tfmt.Printf(\"Stooaaarrrrting %v\\n\", appName)\n\tservice.StartWebServer(\"6767\")\n}\n```\n\nNow run the app again:\n\n```\n$ go run *.go\nStooaaarrrrting accountservice\n2019/01/29 21:13:19 Starting HTTP service at 6767\n```\n\nSwitch over to a new tab/bash and curl our new server:\n\n```\n$ curl localhost:6767\n404 page not found\n```\n\nAs we didn't declare any routes, this 404 should be great for now.\n\n\n### Adding Routes\n\nLet's use [gorillatoolkit](http://www.gorillatoolkit.org/) as the web toolkit for Go.\n\nTherefore create `routes.go` file inside `service` directory:\n\n```go\npackage service\n\nimport \"net/http\"\n\n// Defines a single route, e.g. a human readable name, HTTP method and the\n\n// pattern the function that will execute when the route is called.\n\ntype Route struct {\n\nName        string\n\nMethod      string\n\nPattern     string\n\nHandlerFunc http.HandlerFunc\n\n}\n\n// Defines the type Routes which is just an array (slice) of Route structs.\n\ntype Routes []Route\n\n// Initialize our routes\n\nvar routes = Routes{\n\nRoute{\n\n\"GetAccount\",                                     // Name\n\n\"GET\",                                            // HTTP method\n\n\"/accounts/{accountId}\",                          // Route pattern\n\nfunc(w http.ResponseWriter, r *http.Request) {\n\n            w.Header().Set(\"Content-Type\", \"application/json; charset=UTF-8\")\n\n            w.Write([]byte(\"{\\\"result\\\":\\\"OK\\\"}\"))\n\n        },\n\n},\n\n}\n```\n\nWe're using [Go structs](https://gobyexample.com/structs) here. Structs can be used to define data structure/models in Go. Here the struct defines everything needed for our first route.\n\nAnd __now - OMG! - there we are!__ We need to create some __boilderplate__ code to actually spin up the Gorilla Router (oh, I thought here's everything really better than in Spring Boot, hu?!!).\n\nSo let's create `router.go` also inside `service` directory:\n\n```go\npackage service\n\nimport (\n\n\"github.com/gorilla/mux\"\n\n)\n\n// Function that returns a pointer to a mux.Router we can use as a handler.\n\nfunc NewRouter() *mux.Router {\n\n    // Create an instance of the Gorilla router\n\nrouter := mux.NewRouter().StrictSlash(true)\n\n// Iterate over the routes we declared in routes.go and attach them to the router instance\n\nfor _, route := range routes {\n\n    // Attach each route, uses a Builder-like pattern to set each route up.\n\nrouter.Methods(route.Method).\n\n                Path(route.Pattern).\n\n                Name(route.Name).\n\n                Handler(route.HandlerFunc)\n\n}\n\nreturn router\n\n}\n```\n\nThat's interesting. We can access `routes` directly from [routes.go](accountservice/service/routes.go) without importing the file - it's in the same package.\n\nFurthermore we can use [range](https://gobyexample.com/range) and for (the `_` is just to ignore the index that range provides also) to iterate over our `routes` and set the route up with Gorilla's builder API.\n\nNow head over to [webserver.go](accountservice/service/webservice.go) and add the two lines at the start of the `StartWebServer` function:\n\n```go\nfunc StartWebServer(port string) {\n\n        r := NewRouter()             \n        http.Handle(\"/\", r) \n```\n\nStart the server again with `go run *.go` and curl \n\n```\n$ curl localhost:6767/accounts/10000 \n{\"result\":\"OK\"}\n```\n\n\n\n\n\n# Links\n\nhttps://www.golang-book.com/books/intro/4\n\nVery good basic concepts site:\nhttps://gobyexample.com\n\nCurated list of tools https://awesome-go.com/\n\nConfiguration / parameterization https://github.com/spf13/viper\n\nHTTP \u0026 Dependency Injection https://github.com/mustafaakin/gongular\n\n### Enums\n\nhttps://blog.learngoprogramming.com/golang-const-type-enums-iota-bc4befd096d3\n\nhttps://stackoverflow.com/questions/14426366/what-is-an-idiomatic-way-of-representing-enums-in-go\n\n### Testing\n\nhttps://jaxenter.de/testen-benchmarks-go-70936\n\nexecute\n\n```\ngo test -v\n```\n\nIf that doesn't work, it gives you something like this\n\n```\nweatherbackend-go jonashecht$ go test -v\n=== RUN   TestGetSenseInThat\n--- FAIL: TestGetSenseInThat (0.00s)\npanic: runtime error: invalid memory address or nil pointer dereference [recovered]\n\tpanic: runtime error: invalid memory address or nil pointer dereference\n[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x1244687]\n\ngoroutine 19 [running]:\ntesting.tRunner.func1(0xc000116100)\n\t/usr/local/Cellar/go/1.11.5/libexec/src/testing/testing.go:792 +0x387\npanic(0x128b6e0, 0x14e3340)\n\t/usr/local/Cellar/go/1.11.5/libexec/src/runtime/panic.go:513 +0x1b9\ngithub.com/gorilla/mux.(*Router).ServeHTTP(0x0, 0x1324900, 0xc00009c800, 0xc000116200)\n\t/Users/jonashecht/dev/goworkspace/src/github.com/gorilla/mux/mux.go:176 +0x37\ngithub.com/jonashackt/microservice-example-go/weatherbackend-go.executeRequest(0xc000116200, 0x3)\n\t/Users/jonashecht/dev/goworkspace/src/github.com/jonashackt/microservice-example-go/weatherbackend-go/main_test.go:33 +0xb0\ngithub.com/jonashackt/microservice-example-go/weatherbackend-go.TestGetSenseInThat(0xc000116100)\n\t/Users/jonashecht/dev/goworkspace/src/github.com/jonashackt/microservice-example-go/weatherbackend-go/main_test.go:22 +0x65\ntesting.tRunner(0xc000116100, 0x12eef18)\n\t/usr/local/Cellar/go/1.11.5/libexec/src/testing/testing.go:827 +0xbf\ncreated by testing.(*T).Run\n\t/usr/local/Cellar/go/1.11.5/libexec/src/testing/testing.go:878 +0x35c\nexit status 2\nFAIL\tgithub.com/jonashackt/microservice-example-go/weatherbackend-go\t0.018s\n```\n\nNow we should use Debugging to get more information\n\n### Debugging Go with IntelliJ on Mac\n\nYou maybe get an error, that tells you `could not launch process: exec: \"lldb-server\": executable file not found in $PATH` or the like.\n\nAll you need to do is to install X-Code command line tools with \n\n```\n$ xcode-select --install\n```\n\nFor me, this didn't work because of \"networking problems\". Luckily [you can download them directly](https://stackoverflow.com/a/20243261/4964553) from Apple Developer Tools site: https://developer.apple.com/downloads/index.action (you only need your Apple ID user \u0026 pw in place).\n\n\n\n### Vendoring\n\nhttps://goenning.net/2017/02/23/packages-vendoring-in-go/\n\nhttps://arslan.io/2018/08/26/using-go-modules-with-vendor-support-on-travis-ci/\n\n### Webservices\n\nhttps://jaxenter.de/restful-rest-api-go-golang-68845\n\nhttps://kev.inburke.com/kevin/golang-json-http/\n\nhttps://gist.github.com/reagent/043da4661d2984e9ecb1ccb5343bf438\n\n\n#### Testing Webservices\n\nhttptest\n\nStart the server again with `go run .` and curl \n\nUse Postman to access `localhost:6767/weather/general/outlook` via a POST with the following JSON body:\n\n```\n\n```\n\n\n\n##### gorilla-mux\n\nhttps://gowebexamples.com/routes-using-gorilla-mux/\n\nhttps://semaphoreci.com/community/tutorials/building-and-testing-a-rest-api-in-go-with-gorilla-mux-and-postgresql\n\nhttps://medium.com/@kelvin_sp/building-and-testing-a-rest-api-in-golang-using-gorilla-mux-and-mysql-1f0518818ff6\n\n##### Swagger Go\n\nhttps://www.ribice.ba/swagger-golang/\n\n\n### Microservice frameworks\n\nhttps://medium.com/seek-blog/microservices-in-go-2fc1570f6800\n\n[3 main choices](https://www.quora.com/What-are-some-of-the-most-well-known-Go-Golang-Microservice-frameworks-libraries-out-there):\n\n* https://github.com/micro/go-micro\n* https://github.com/nytimes/gizmo\n* https://github.com/go-kit/kit (complex! https://www.reddit.com/r/golang/comments/5tesl9/why_i_recommend_to_avoid_using_the_gokit_library/)\n\nor do it without a Microservice framework\n\nhttps://outcrawl.com/go-microservices-cqrs-docker/\n\n\n\n\n# Microservice(s) with go-micro\n\nhttps://github.com/micro/micro\n\nhttps://micro.mu/docs/toolkit.html\n\n### Install micro CLI\n\n__Don't do__ `brew install micro` - this will install an text editor.\n\nInstead, install go-micro incl. CLI via\n\n```\ngo get -u github.com/micro/micro\n```\n\n\u003e This isn't everything! You'll get $ micro --version  -bash: micro: command not found errors, so please also do:\n\nAnd then make sure to add the bin directory to your path inside your `.bash_profile`:\n\n```\nexport GOPATH=/Users/jonashecht/dev/goworkspace\nexport PATH=$PATH:$GOPATH/bin\n```\n\n```\nbrew install protobuf\n```\n\n### Generate project skeleton\n\nInside your `GOPATH` (for me this is `/Users/jonashecht/dev/goworkspace`), execute:\n\n```\nmicro new github.com/jonashackt/microservice-example-go/weatherservice\n```\n\nThis will give something like:\n\n```\n$ micro new github.com/jonashackt/microservice-example-go/weatherservice\nCreating service go.micro.srv.weatherservice in /Users/jonashecht/dev/goworkspace/src/github.com/jonashackt/microservice-example-go/weatherservice\n\n.\n├── main.go\n├── plugin.go\n├── handler\n│   └── example.go\n├── subscriber\n│   └── example.go\n├── proto/example\n│   └── example.proto\n├── Dockerfile\n├── Makefile\n└── README.md\n\n\ndownload protobuf for micro:\n\nbrew install protobuf\ngo get -u github.com/golang/protobuf/{proto,protoc-gen-go}\ngo get -u github.com/micro/protoc-gen-micro\n\ncompile the proto file example.proto:\n\ncd /Users/jonashecht/dev/goworkspace/src/github.com/jonashackt/microservice-example-go/weatherservice\nprotoc --proto_path=. --go_out=. --micro_out=. proto/example/example.proto\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonashackt%2Fmicroservice-example-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonashackt%2Fmicroservice-example-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonashackt%2Fmicroservice-example-go/lists"}