Live data from Hacker News

Go in Production – Lessons Learned

tdom.dev

51–60 of 109 posts

Re: Go in Production – Lessons Learned

#51
post #4

The more you get to know Go's stdlib the less and less youll think a web framework is necessary. Youll find that utilizing http Round Tripper along with the Handler interface in the http library will make middleware easy. Youll eventually dig into filepath and path methods for extracting path parameters from url paths. And logging and recovery will be a concept youll need to extend outside of just http and into the r…

I see this sentiment a lot in the Go community. I think it is reasonable in some cases, but there are many use cases (vanilla CRUD web apps) where a web framework is really helpful.

The standard library is very low level. Want sessions? DIY. Want user auth? DIY. Want CSRF protection? DIY. The list goes on.

It feels like a waste of time implementing these "solved problems" from scratch, but the biggest problem is how easy it is to introduce security vulnerabilities when implementing from scratch, or forgetting to do so.

It’s nice to learn concepts from first principals by using the standard library. But once I know how these things work, I’d rather rely on someone else’s battle tested code and best practices.

Yes, you can add in separate libraries to solve these specific problems, but they are less likely to compose as well as they would in a framework. On top of this, each time you pull in a new library you have to spend time evaluating it. When I use a framework I don't have to think.

Re: Go in Production – Lessons Learned

#52
post #40
post #4

The more you get to know Go's stdlib the less and less youll think a web framework is necessary. Youll find that utilizing http Round Tripper along with the Handler interface in the http library will make middleware easy. Youll eventually dig into filepath and path methods for extracting path parameters from url paths. And logging and recovery will be a concept youll need to extend outside of just http and into the r…

Here is the thing, I have been doing Web development alongside native for a couple of decades now. This Go enlightment seems to only touch those that don't realize that programming to interfaces was already a thing back in Objective-C and WebObject days, or using Smalltalk categories (later formalized as traits in Pharo). Also that languages like Java and .NET also have a similar Http server on their standard library…

> The reason we don't use them beyond toy examples, is that they don't scale when things start getting hard and something like IIS, ngix or similar is called into action.

Hmm? You seem to be mixing two things here. Nobody is suggesting not using NGINX/Caddy etc. The comment was about being able to go very far with just the standard library.

Re: Go in Production – Lessons Learned

#53
post #48
post #43

Earlier quoted context omitted.

404 is literally the correct response for this behavior, per the HTTP spec. There was no server-side error. The requested resource was unable to be located because it no longer existed. You should return a 404 here, and not just for non-HTML API clients. Application-side fatal errors are in the 500 block. So yes, you absolutely can distinguish this case.

The requested resource was unable to be located because it no longer existed. I should have mentioned that the API was behind a reverse proxy. This leads to the following questions: Which requested resource is missing? The API itself or the item requested from the API? How does a client distinguish between these?

I can’t imagine any way a reverse proxy would generate a 404 or indeed any 4xx error within itself. Any such error would be coming from the upstream application server.

If the API itself was not found that’s one of 502, 503 or 504.

200 responses with an error property is an antipattern precisely because of things like reverse proxies. They have no way to unpack and interpret every developers pet error format. They _do_ understand http status codes and can act accordingly, like retrying requests, not caching responses, etc as appropriate.

Re: Go in Production – Lessons Learned

#54

Earlier quoted context omitted.

Another reason to use GraphQL. No more endless discussion about which HTTP codes to use, which HTTP action to use, how to send in data, how to format your response, ...

And adds a bunch of other endless discussions: how to cache data (POST is not cacheable), how to auth data (anyone has access to everything), how to...

I don't feel like this is added by GraphQL because you'll have these questions regardless of using GraphQL.

how to cache data (POST is not cacheable) -> You can use GET requests and GET requests are cacheable.

how to auth data (anyone has access to everything) -> Authentication or authorization? What do you mean with anyone has access to everything?

how to... -> yes?

Re: Go in Production – Lessons Learned

#55
post #4

The more you get to know Go's stdlib the less and less youll think a web framework is necessary. Youll find that utilizing http Round Tripper along with the Handler interface in the http library will make middleware easy. Youll eventually dig into filepath and path methods for extracting path parameters from url paths. And logging and recovery will be a concept youll need to extend outside of just http and into the r…

There's a lot of non-obvious stuff to cover, like getting all the caching related headers right, vary headers, relationships between proxy headers and logging, thwarting path traversal, dealing with file uploads, and so on.

Re: Go in Production – Lessons Learned

#56

Earlier quoted context omitted.

How does GraphQL allow you to not worry about those things?

GraphQL only uses two HTTP methods (GET and POST). But they actually don't differentiate in their function: you can do any type of reading/writing kind of queries in both GET and POST requests[1]. POST requests are used because they allow for larger bodies. GraphQL defines the format of the reponse in case of errors[1] GraphQL doesn't use HTTP status codes to communicate out-of-the-ordinary conditions. You can expect…

And when intermediate proxies happily retry your small “delete the most recent record” request because it was a GET which is, in the rest of reality, guaranteed not to alter state on the receiving server except in the corner of the internet you’ve defined as your own it’s destructive?

Re: Go in Production – Lessons Learned

#57

Earlier quoted context omitted.

GraphQL only uses two HTTP methods (GET and POST). But they actually don't differentiate in their function: you can do any type of reading/writing kind of queries in both GET and POST requests[1]. POST requests are used because they allow for larger bodies. GraphQL defines the format of the reponse in case of errors[1] GraphQL doesn't use HTTP status codes to communicate out-of-the-ordinary conditions. You can expect…

And when intermediate proxies happily retry your small “delete the most recent record” request because it was a GET which is, in the rest of reality, guaranteed not to alter state on the receiving server except in the corner of the internet you’ve defined as your own it’s destructive?

You can use GET for read queries and POST for write queries.

Edit: actually you made me think a little bit more about this, if you can make your mutations idempotent, spurious retried POST requests shouldn't be a problem at all. However "delete the last record" is not an idempotent operation by definition but also one you wouldn't use in the real world - usually you delete by ID.

Edit 2: it's easy to make the server reject mutations sent via GET.

Re: Go in Production – Lessons Learned

#58

> I recently got a DevOps job that mostly involves writing a new backend system in Go completely from scratch. If this wasn't on the front page of HN I'd have stopped reading here, but it is, so I didn't, then I regretted it.

What offends you in that statement? FWIW, I, who is usually writing JVM apps in Java/Kotlin occasionally Scala, had an app to write that that extensively used K8s APIs, and I found that the best client API was (naturally, considering the makeup of the K8s ecosystem) the Go one, so I wrote the app in Go. I had to overcome some common Go issues (use a map[t]interface{} when you need "is x in a list of unique elements",…

> Naming a return, but then assigning nothing to it, will compile.

This, I believe, comes down to Go having sane default values i.e. if you name a return of type string and assign nothing to it, you'd get "", which is a valid string value and something you can check against.

But I agree it should at least be a lint warning.

Re: Go in Production – Lessons Learned

#59
To those who say frameworks are needed because the stdlib is not enough: No, the stdlib defines very clear interfaces that libraries can implement. The result is that you can drag and drop middlewares from multiple packages into your codebase, because they all conform to the universal middleware signature `func(http.Handler) http.Handler`. Want CSRF? Want Sessions? Want Auth? They all exist as separate packages (check out the Gorilla toolkit), but the beauty is that they all work without needing to know the existence of each other.

Frameworks like Echo and Gin eschew the universal middleware signature `func (http.Handler) http.Handler` for their custom built ones, and as a result cannot tap into the ecosystem of middlewares that target Go's net/http. Between a stdlib package and a third party package, which do you think is more stable?

You are not constrained to net/http's router. Chi is a good example of a third party router that implements features not in net/http but still conforms to the `func(http.Handler) http.Handler` interface, and as a result middlewares that work for net/http will also work for Chi.

https://justinas.org/embrace-gos-http-tools

Re: Go in Production – Lessons Learned

#60
post #2

This article has almost nothing to do with Go in particular. Just...general stuff to follow when writing code. What is it here that talks specific things about "Go" + "in production"?

I think it's stuff you need once you move beyond basic learning go projects.

I found it pretty useful, the tip about sqlx, echo, and a quick docker file example were useful reminders, the rest ive seen elsewhere but yea.

I get what your saying but I found this useful.

Post reply on HN