{"id":15067776,"url":"https://github.com/thisdougb/cleango","last_synced_at":"2026-01-02T09:38:53.448Z","repository":{"id":47766149,"uuid":"516297643","full_name":"thisdougb/cleango","owner":"thisdougb","description":"A GoLang template for web projects.","archived":false,"fork":false,"pushed_at":"2023-03-17T10:55:00.000Z","size":77,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-22T18:24:18.106Z","etag":null,"topics":["development","golang","golang-examples","templates","web","webapp"],"latest_commit_sha":null,"homepage":"","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/thisdougb.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-21T09:00:17.000Z","updated_at":"2023-03-14T09:26:48.000Z","dependencies_parsed_at":"2024-06-21T02:09:21.221Z","dependency_job_id":"00f05595-20fd-4744-ba54-c0011a951e4b","html_url":"https://github.com/thisdougb/cleango","commit_stats":{"total_commits":28,"total_committers":2,"mean_commits":14.0,"dds":0.1071428571428571,"last_synced_commit":"a2c2945b72ac3206604bcd9b1862d373a390b858"},"previous_names":[],"tags_count":8,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisdougb%2Fcleango","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisdougb%2Fcleango/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisdougb%2Fcleango/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisdougb%2Fcleango/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thisdougb","download_url":"https://codeload.github.com/thisdougb/cleango/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243830912,"owners_count":20354850,"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":["development","golang","golang-examples","templates","web","webapp"],"created_at":"2024-09-25T01:27:16.092Z","updated_at":"2026-01-02T09:38:53.409Z","avatar_url":"https://github.com/thisdougb.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cleango\n\n[![release](https://github.com/thisdougb/cleango/actions/workflows/release.yaml/badge.svg)](https://github.com/thisdougb/cleango/actions/workflows/release.yaml)\n\n#### Goal\n\nA re-usable GoLang template for a web/api server, that saves me time and ensures I start projects with a good structure.\n\n#### Strategy\n\n- a runnable app as a template, so we start from a known-good\n- include features most likely to be used, to avoid masses of boiler-plate code\n- an easy method to create releases\n- focus on making development easier and simpler\n\nUse the button above \"Use this template\".\n\n#### Get Started\n\nWhen you template this repo it will contain 'thisdougb/cleango' in the pkg paths.\nHere's how to reset those paths, using sed on Mac OS (at least), after you've cloned your new repo.\n\nSubstitute your GitHub name for _mygithubname_, and your repo name for _myproject_:\n```\n$ git clone git@github.com:thisdougb/myproject.git\n$ cd myproject\n$ find . \\( -type d -name .git -prune \\) -o -type f -print0 | xargs -0 sed -i '' -e 's/thisdougb/mygithubname/g'\n$ find . \\( -type d -name .git -prune \\) -o -type f -print0 | xargs -0 sed -i '' -e 's/cleango/myproject/g'\n```\nThen run (assumes a local Redis instance):\n```\n$ go run -tags dev main.go\n2023/03/14 08:40:01 main.go:32: Datastore connecting, host: 'localhost:6379', username: \n2023/03/14 08:40:01 main.go:39: Datastore connected.\n2023/03/14 08:40:01 main.go:55: webserver.Start(): listening on port 8080\n```\nYou can test everything works:\n\n```\n$ curl http://localhost:8080   \n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n    \u003chead\u003e\u003c/head\u003e\n    \u003cbody\u003e\n        \u003ch4\u003eHello World!\u003c/h4\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nand \n\n```\n$ curl -X POST http://localhost:8080/thing/enable/ -H \"Content-Type: application/json\" -d '{\"thing_id\": 1}'                                                                             \nOK\n\n$ redis-cli\n127.0.0.1:6379\u003e keys *\n1) \"app:thing:1:status\"\n127.0.0.1:6379\u003e get \"app:thing:1:status\"\n\"1\"\n127.0.0.1:6379\u003e\n```\n\n#### Release Packages\n\n A GitHub action uses goreleaser to automatically build [release packages](https://github.com/thisdougb/cleango/releases).\n The release includes the README file, and the LICENSE file.\n\n```\n$ git checkout main   \nSwitched to branch 'main'\nYour branch is up to date with 'origin/main'.\n\n$ git tag -a v0.1.0 -m \"initial release\"\n\n$ git push origin v0.1.0                                                                        \nEnumerating objects: 1, done.\nCounting objects: 100% (1/1), done.\nWriting objects: 100% (1/1), 191 bytes | 191.00 KiB/s, done.\nTotal 1 (delta 0), reused 0 (delta 0), pack-reused 0\nTo github.com:thisdougb/cleango.git\n * [new tag]         v0.1.0 -\u003e v0.1.0\n ```\n\n#### Emedded Files\n\nUsing the _embed_ module we can include the static template files in the resulting Go binary.\nThis means a deployable Go app that uses html templates will work.\n\nOn startup the following is printed to help understanding:\n\n```\n2023/03/14 08:40:01 env.go:87: dir .\n2023/03/14 08:40:01 env.go:87: dir templates\n2023/03/14 08:40:01 env.go:90: file: templates/footer.gohtml\n2023/03/14 08:40:01 env.go:90: file: templates/header.gohtml\n2023/03/14 08:40:01 env.go:90: file: templates/index.gohtml\n2023/03/14 08:40:01 env.go:80: embed FS file: templates/footer.gohtml\n2023/03/14 08:40:01 env.go:80: embed FS file: templates/header.gohtml\n2023/03/14 08:40:01 env.go:80: embed FS file: templates/index.gohtml\n```\n\nThe _embed_ module can be hard to figure out from the docs.\nThe key thing is to know the FS contains file paths.\n\nBut we use the templates using the template name (string), which is coincidentally the file name.\nThe template name (string) is used in the define statement within the template file.\nThese two strings must match, otherwise a blank html page is served.\n\n```\n2023/03/14 08:40:02 handle_homepage.go:47: templates: ; defined templates are: \"index.gohtml\", \"header.gohtml\", \"footer.gohtml\"\n```\n\nLogging shows us the file and line that prints the above output, so it can be followed for understanding.\n\n#### Logging\n\nIn [log.go](https://github.com/thisdougb/cleango/blob/refactor_logging/api/log.go#L7) we have a simple init() which sets the formatting for log statements.\nIt is easier and quicker to troubleshooting problems when you know where the log statements are from.\n\nEnsuring filenames are descriptive, rather than main.go, helps here:\n```\n2022/07/21 11:33:12 enablething.go:27: error, ostrich 43723 has 8 legs.\n```\n\n#### Build Tags\n\nI use build tags.\nAll test and mock files are _dev_, so excluded in the final build.\n\nThis also makes switching templating easy between environments.\n```\n$ go run -tags dev api/server.go\n2022/07/21 11:33:12 server.go:46: webserver.Start(): listening on port 8080\n```\n\n#### Passing Datastore Reference\n\nSo [here](https://github.com/thisdougb/cleango/blob/main/api/handlers/env.go) I use an Env struct to reference Service pointers.\nThis allows seamless passing of the datastore connection (or mock) to the handlers.\n\nI mashed up the Clean Architecture style with [this](https://www.alexedwards.net/blog/organising-database-access) blog post.\nThat's where my Env struct came from.\n\n#### Use Case\n\nUsecase is a core Clean Architecture idea, and a little vague.\nI think of it as, 'an action that happens, like making a coffee.'\nThere's often multiple steps to produce an outcome.\n\nAn http handler depends on a usecase, but the usecase knows nothing about the http handler.\n\n#### File Numbering\n\nI use file name numbering for files that are part of the templating pattern.\nThis is purely to make scanning dirs and finding what you expect to always be there much quicker.\n\nFor example:\n```\n$ ls -l pkg/usecase/enablething\ntotal 56\n-rw-r--r--  1 thisdougb  staff  209 21 Apr 20:13 1_interface.go\n-rw-r--r--  1 thisdougb  staff  181 21 Apr 20:14 2_service.go\n-rw-r--r--  1 thisdougb  staff  179 21 Apr 19:43 3_mock.go\n-rw-r--r--  1 thisdougb  staff   77 21 Apr 19:43 4_mock_reader.go\n-rw-r--r--  1 thisdougb  staff  378 21 Apr 20:17 5_mock_writer.go\n-rw-r--r--  1 thisdougb  staff  433 21 Apr 20:57 enablething.go\n-rw-r--r--  1 thisdougb  staff  899 21 Apr 20:15 enablething_test.go\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthisdougb%2Fcleango","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthisdougb%2Fcleango","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthisdougb%2Fcleango/lists"}