{"id":16516234,"url":"https://github.com/aphistic/go-examples-api-versioning","last_synced_at":"2026-05-10T13:05:03.808Z","repository":{"id":136842692,"uuid":"284759672","full_name":"aphistic/go-examples-api-versioning","owner":"aphistic","description":"This is an example of how I like to lay out versioned (or even unversioned) APIs.","archived":false,"fork":false,"pushed_at":"2020-08-04T23:29:17.000Z","size":19,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-13T05:22:02.682Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aphistic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2020-08-03T17:09:59.000Z","updated_at":"2020-08-04T23:29:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"3203f75b-8717-45d9-afd8-baf25f695001","html_url":"https://github.com/aphistic/go-examples-api-versioning","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/aphistic%2Fgo-examples-api-versioning","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aphistic%2Fgo-examples-api-versioning/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aphistic%2Fgo-examples-api-versioning/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aphistic%2Fgo-examples-api-versioning/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aphistic","download_url":"https://codeload.github.com/aphistic/go-examples-api-versioning/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241549117,"owners_count":19980476,"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-11T16:20:12.088Z","updated_at":"2026-05-10T13:05:03.709Z","avatar_url":"https://github.com/aphistic.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# API Versioning\n\nThis is an example of how I like to lay out versioned (or even unversioned) APIs. This example\nis centered around a RESTful, versioned HTTP API but the ideas can be used elsewhere.\n\nThe general idea is that each \"domain\" of the API doesn't need to be aware of any other domain,\njust itself. The top level API, for example, doesn't need to know about the structure of the code\nOR the routes for another package. It follows a pattern similar to MVC... but just the C part. The\nMV part is up to you. :)\n\nFor the code from a v2 api that is the same as the v1 API (it hasn't changed and functions exactly\nthe same) I haven't really come up with a pattern that I'm super happy with. The best idea I've had\nso far is to pass an instance of the previous version to the next version and having the next version\ncall the previous version. You'll see this in `internal/app/api-example/api/v2`.\n\nThe models of the data returned from the API are shown in a couple different example variations\ndepending on how you'd like to handle it. The `v1` models are in a subpackage of the `v1` package\nand the `v2` models are in files next to the controllers themselves. I've found both these patterns\nwork as long as you're consistent. Having the models in a separate package can help organize things\nif you have many of them.\n\nThe goal of the API models is to separate the representation the users see from the internal\nrepresentation coming from the data/service layers. This way we can update the internal models\nin potentially breaking ways without needing to change the models returned to the users for previous\nversions of the API, as long as we update those when the internal models change. This becomes much\neasier than some other languages because we can take advantage of Go's type checking (and unit tests!)\nto alert us at compile time.\n\nHere's a layout of the API itself:\n\n```\n+ /api\n  + /v1\n    + /users\n      - GET\n      - POST\n      - GET /{id}\n    + /groups\n      - GET\n      - POST\n      - GET /{id}\n  + /v2\n    + /users\n      - GET\n      - POST\n      - GET /{id}\n    + /groups\n      - GET\n      - POST\n      - GET /{id}\n```\n\nThe repo is laid out similar to [golang-standards/project-layout](https://github.com/golang-standards/project-layout)\nas I find it's the most extensive, well-documented and accepted example of laying out a Go\nbinary project.\n\nThe best place to start reading this code is `cmd/api-example/main.go` because that's where the\ninitial API and HTTP server are started.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faphistic%2Fgo-examples-api-versioning","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faphistic%2Fgo-examples-api-versioning","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faphistic%2Fgo-examples-api-versioning/lists"}