quii/go-http-reference-impl là dự án Go với 27 sao.
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
VÌ SAO CHƯA CÓ REVIEW
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
This is my current state-of-the-art opinion on how I like to structure Go projects for how I, and how I want my teams to work.
High level-requirements
I want the team to practice Trunk-based development.
I write about some reasons here
minimumcd.org writes it's a prerequisite to Continuous Delivery
The system we work on, it's structure and its internal quality, has a huge effect on the way we work and our productivity. I am very-much subscribed to The DevOps Three Ways which emphasises flow, feedback-loops and a continuous culture of improvement and learning. Too many repos I've worked on impede flow and have poor and slow feedback loops.
It's important that developers can safely and confidently push small, positive, high-quality changes to the system frequently through the day
The process for making change should roughly be:
git pull -r
If it's a distinctly new feature, start with an acceptance test, otherwise, a unit test to drive a further iteration of an existing feature.
See the test fail.
Make it pass.
git commit -am "added new feature"
Refactor.
git add .
git commit --amend --no-edit
git pull -r
./build.sh && git push
Repeat as necessary. Always bear in mind the test pyramid.
What does it take to work that way safely?
Modular code. Each bit of code should have a clear purpose which is cohesive and loosely coupled. If a system has lots of inappropriate and tight-coupling then developers will tread on each other's toes.
Enough structure & convention to make it obvious where to start work, and where to put things.
But not so opinionated about a particular "way" that if a new requirement comes along that doesn't fit that model, that it requires extensive re-work.
Excellent observability
Tests. Manual testing is unacceptable.
Tests!!
Extremely fast unit tests. Developers should be re-running them constantly. In order to make small, frequent, positive changes to the system through a day you need a tight feedback-loop.
Integration tests, ideally running against real versions of the systems our code is working with. Use docker-compose and testcontainers to orchestrate spinning up containers for the test. No manual work required to run tests, they should work out of the box.
Acceptance tests.
Behaviour & domain focused.
Decoupled from implementation detail.
Can be executed against our local version, or against other environments, including live.
As we ship Docker images to be deployed, for the local run we should build our image and test against a running container that we intend to ship. This gives us huge confidence the system will work in production.
The tests should all be runnable locally. Having to push code to a "CI server" to get feedback on changes is too slow.
Implementation notes
Prereqs
Go
Docker
golangci-lint
Specifications & acceptance tests
Specifications should be decoupled from your implementation detail. For new features they should be seen as a starting point for work where you describe "the truth" in terms of what behaviour your system should exhibit.
type GreetingSystemDriver interface {
Greet(name string) (greeting string, err error)
}
func Greeting(t *testing.T, greetingSystem GreetingSystemDriver) {
t.Helper()
t.Run("greets people in a friendly manner", func(t *testing.T) {
is := is.New(t)
greeting, err := greetingSystem.Greet("Pepper")
is.NoErr(err)
is.Equal(greeting, "Hello, Pepper!")
})
}
To use this test, you create a driver which implements the interface you need to run the test. For the black-box acceptance tests that's a HTTP client which calls our API given a baseURL. This means we can run them locally but also against deployed environments like live with very little effort.
You can also re-use these specifications to test your domain code too, because the criteria and rules of the domain should hold true within your system too.
Using configuration to create the necessary dependencies for the application (calling NewFoo functions)
application
Within here should live what you could roughly call your "domain" or application code. It should contain most of your data models and business logic.
Specifics as to how to organise beyond that I don't have especially strong opinions about, but the code must be:
Modular & testable
Have a sensible separation of concerns
Cohesive
You should not have code that interacts with "the outside world" in here. For that you put them inside adapters.
adapters
This is where other users and systems interact with application. Think HTTP servers, message queues, databases e.t.c.
In terms of dependency directions, adapters should have dependencies on application, but not the other way around. If you find yourself having a circular dependency between adapters and application it's likely you've mixed up concerns somehow.
HTTP
One strong opinion I do hold is around to structure HTTP servers.
This means in main I can pass in configuration and real dependencies to create my server and then start log.Fatal(server.ListenAndServe()). It also means we can use httptest.NewServer(NewWebServer(...)) to test our web server at a unit level too.
This keeps handlers, skinny, simple to test, and means we can unit test our important business logic without HTTP causing noise and complexity. I've written more about this in Learn Go with Tests.
The responsibility of handling HTTP is with "HTTP handlers", but they shouldn't do much more beyond that.
Dockerfile and Docker-compose
The Dockerfile is a fairly standard, multi-stage build image which allows us to build our code and then ship very small containers
Docker-compose allows us to declaratively define what our app depends on, which is useful for the acceptance tests when running locally but also lets us spin up say Redis for our integration tests (in conjunction with testcontainers).
Telemetry
Using OpenTelemetry. Locally it will export to Jaeger for tracing.
Run the following Docker command to spin up a local Jaeger:
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/quii/go-http-reference-impl là nguồn chính thức.
quii/go-http-reference-impl có phải mã nguồn mở không?
TopGit chưa ghi nhận license cho quii/go-http-reference-impl. Phần lớn repo public trên GitHub là mã nguồn mở, nhưng điều khoản khác nhau từng repo — mở file LICENSE để xác nhận.
quii/go-http-reference-impl có tag gì không?
Bản đồng bộ chưa ghi nhận topic GitHub nào cho quii/go-http-reference-impl. GitHub topics hiển thị ở thanh bên phải trang repo — đó là nơi đáng kiểm tra nhất.
quii/go-http-reference-impl có website riêng không?
TopGit chưa ghi nhận URL trang chủ cho quii/go-http-reference-impl. Phần README ở tab phía trên thường có link demo, hoặc xem mô tả GitHub của repo.
quii/go-http-reference-impl còn đang phát triển không?
Commit gần nhất trên quii/go-http-reference-impl là 4.7 năm trước (theo timestamp GitHub). Repo có 5 fork — một chỉ báo về mức độ quan tâm của cộng đồng.
Đọc đầy đủ README ở tab phía trên.
Chưa chắc go-http-reference-impl có hợp với bạn?
Để ChatGPT, Claude hoặc Perplexity tìm hiểu giúp — bấm bên dưới và xem AI nói gì về go-http-reference-impl.