5 ms·
Almost all articles I've seen explaining the context pkg are done with net/http examples. That's fine but I feel like it might not be the best introduction for
by JyB 7y ago
Almost all articles I've seen explaining the context pkg are done with net/http examples.
That's fine but I feel like it might not be the best introduction for a novice as a lot of concepts are mixed together and they might miss the bigger picture. Context is not just for web servers. You don't have to know how net/http works.
You could simply demonstrate the usefulness of the context package with showing how to properly clean up your program on a sigterm. Or even gracefully stop a long running operation so you are not afraid to stop/start your program at the "wrong" time.
- K0SM0S 7y ago> “Almost all articles I've seen explaining the context pkg are done with net/http examples. That's fine but I feel like it might not be the best introduction for a novice as a lot of concepts are mixed together and they might miss the bigger picture. Context is not just for web servers. You don't have to know how net/http works.” Indeed. But I think the seminal blog post¹ on the matter has somewhat skewed perception initially. The first sentence reads: > In Go servers, each incoming request is handled in its own goroutine. Request handlers often start additional goroutines to access backends such as databases and RPC services. That pretty much sets a mental context (pun unintended) within the server paradigm. People then just overlook the fact that any Go app can (and often probably should) make use of `context` — CLI anyone? Unless I'm mistaken, `context` is fundamentally about the underlying machine, not network (it just adds to confusion that the latter is represented as "context" within the former, i.e. files and folders and variables in a POSIX environment). > You could simply demonstrate the usefulness of the context package with showing how to properly clean up your program on a sigterm. Very nice one! I never saw a book titled "Linux Mechanics" but this would be akin to applying F⁻¹ to some object whose inherent motion comes from F. Like, the basics, "how do I stop this thing?" This is a cultural approach to computers that I think is fading along with the desktop culture, which itself got blurred by tons of layers of abstraction (think 1980-2020). In that vein I think it's very interesting to experiment with Linux namespaces² (notably cgroups and network namespaces). Create elementary "container components" (i.e. network namespace, UTS..) with Go and see from there how context applies (or not). You'll be effectively clean-rooming³ Docker, in some abstract sense. Distribute it and you've got a skeleton for Kubernetes. It's a really logical conclusion/next step when diving deep into Linux in the current context — DevOps etc. You just see that culture emerging from the tech. I think Go is incredibly well-positioned to learn these things as we speak: simple, efficient, easy to read, asks you to consider every step carefully (error handling), fluent with OS calls, etc. [1]: https://blog.golang.org/context https://blog.golang.org/context [2]: http://man7.org/linux/man-pages/man7/namespaces.7.html http://man7.org/linux/man-pages/man7/namespaces.7.html [3]: Ignoring common licensing or business concerns atrributed this approach, playing with "clean room" work is excellent technical training to master topics beyond intermediary level, well into expertise — that which no one can really directly impart on you, that which you must build for yourself, quite literally so at times. Can you build it, given Search and enough time? https://en.wikipedia.org/wiki/Clean_room_design https://en.wikipedia.org/wiki/Clean_room_design
- morelisp 7y ago> gracefully stop a long running operation so you are not afraid to stop/start your program at the "wrong" time. This is one of my major pain points with Go's contexts. Where I work we do have an "application wrapper" that gets cancelled on various signals, and it's very handy for some things. But one thing it's not good at is shutting things down safely! Something we do pretty commonly is start multiple servers (e.g. a public and a private HTTP server, or an HTTP server and DB background task, etc.) When we get SIGINT, we want to cancel both's context (easy), then wait for both to stop before continuing with our exit process (hard). Yes, this is the canonical case for sync.WaitGroup, but those are hard to use correctly when you need to transition into and out of "acceptable" states rather than just count down (well, hard to use correctly period, to be honest - probably half the time I see a junior dev using them they increment within the goroutine). And hard to timeout waiting for the waitgroup when you want to continue despite unclean shutdown - WaitGroup.Done doesn't itself take a context. This is further complicated by the fact that for servers you often don't really want to use the "application context" as the parent of the request contexts. Rather you want the server to shut down cleanly when that context is cancelled, processing all pending requests to completion but without immediately cancelling them. So the base request context is ideally something like "cancelling X seconds after the application context" which is not part of the standard context toolbox. And of course different libraries are not really consistent in how they shut down - http.Server lets you close it with a timeout and so returns an error but also you need to check the error return of the Serve method (and you can't distinguish a graceful stop from a hard stop from try to restart a stopped server), grpc.Server offers only hard and graceful stops with no timeout and only the Serve method returns an error, and sarama.Client provides only a synchronous close that returns an error. I've not used them but I'm told C#'s cancellation tokens akin to Go context but are closely integrated with their async task state machine, such that it's easy to hand out cancellation tokens and wait for the tasks waiting for those tokens to finish.