Live data from Hacker News

Go in Production – Lessons Learned

tdom.dev

81–90 of 109 posts

Re: Go in Production – Lessons Learned

#81
post #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 (chec…

> 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?

I think you're overstating the cost of using "proprietary" middlewares. I'm most familiar with Gin; it is trivial to wrap a "universal" middleware in a Gin middleware (gin.WrapH). It is not trivial to make a universal middleware that does the equivalent of gin.Context#AbortWithError.

I don't fully disagree either - obviously `gin.WrapH` everywhere is noise, but so is e.g. `chi.URLParam(req, "abc")` compared to `c.Param("abc")` in Gin, and Gin's parameters are much cheaper for a middleware to tweak. (I choose chi here because it's one I'm familiar with that tries hard to keep the standard Handler signature at the expense of interfaces to its own features.)

A lot of problems would go away if the standard signature was `func (Context, ResponseWriter, Request) error`. Sometimes a minimal universal option is nice because minimalism is also a virtue; but also sometimes it's just missing necessary features.

Re: Go in Production – Lessons Learned

#82
post #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 (chec…

> To those who say frameworks are needed because the stdlib is not enough: No, the stdlib defines very clear interfaces that libraries can implement.

Yeah, I'm not much into Go development but I've talked to a few devs who built real web apps with it and they rarely use any libraries, but do use "interface style" libs like Gorilla Mux.

Here's a snippet from my podcast where I talked to Jon Calhoun on using mostly the standard library and about 15k lines of code to build a video course platform in Go: https://runninginproduction.com/podcast/42-creating-a-video-...

Re: Go in Production – Lessons Learned

#83
post #82
post #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 (chec…

> To those who say frameworks are needed because the stdlib is not enough: No, the stdlib defines very clear interfaces that libraries can implement. Yeah, I'm not much into Go development but I've talked to a few devs who built real web apps with it and they rarely use any libraries, but do use "interface style" libs like Gorilla Mux. Here's a snippet from my podcast where I talked to Jon Calhoun on using mostly the…

> they rarely use any libraries... He mentioned some of the Gorilla packages that he used too, such as Mux for routing.

Gorilla is perhaps the most maximalist Go web library "system", and its mux is by far the most complex of common routers. Using Gorilla for a site is about as far as being outside the Go stdlib as you can be before reimplementing core protocol handling.

Re: Go in Production – Lessons Learned

#84

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…

AFAIK graphql does have response error codes. You should always have response error codes no matter the form of api. They are semantic info.

Re: Go in Production – Lessons Learned

#85
post #84

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…

AFAIK graphql does have response error codes. You should always have response error codes no matter the form of api. They are semantic info.

GraphQL does not have response error codes. It only dictates that any response that has errors, should have an "error" field. It is not defined what this error field should contain, it can be a string or an object with a code and text, etc...

Re: Go in Production – Lessons Learned

#86
post #84

Earlier quoted context omitted.

AFAIK graphql does have response error codes. You should always have response error codes no matter the form of api. They are semantic info.

GraphQL does not have response error codes. It only dictates that any response that has errors, should have an "error" field. It is not defined what this error field should contain, it can be a string or an object with a code and text, etc...

I could be wrong. Some of the graphql servers I have interacted with have given me useful error codes. E.g GitHub.

We do have nice wrappers around the request to raise a proper named exception regardless so it doesn’t matter.

Re: Go in Production – Lessons Learned

#87
post #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 (chec…

Came in here to say this.

I helped many teams move from Java to Go, and came across this so many times. Everyone wanted to find the Spring equivalent for Go (or Django, Ruby on Rails, etc) when it doesn’t actually exist. That’s by design.

No ill feelings toward the developers of Echo, or other similar frameworks (Go Micro specifically). However, touting their framework as the way to build APIs in Go is disingenuous and leads to software that is difficult to maintain.

Just my two cents.

Re: Go in Production – Lessons Learned

#88
post #19
post #17

Why would you want to serve a 200 with an error message in a JSON response body?

I've seen this pattern before, and one can argue that it is the correct one. Your options are your http status are your application's status, which I think is what most of us are used to. The other one is http status codes are http status codes. As in the http request was done correctly, but the application code wasn't. More specifically, http layer was executed successfully, but the application layer was not.

You're on the Internet. You are going to see all patterns and combinations you can think about.

But there's an rfc and that's what defines correct usage.

Re: Go in Production – Lessons Learned

#89
post #87
post #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 (chec…

Came in here to say this. I helped many teams move from Java to Go, and came across this so many times. Everyone wanted to find the Spring equivalent for Go (or Django, Ruby on Rails, etc) when it doesn’t actually exist. That’s by design. No ill feelings toward the developers of Echo, or other similar frameworks (Go Micro specifically). However, touting their framework as the way to build APIs in Go is disingenuous a…

>I helped many teams move from Java to Go, and came across this so many times. Everyone wanted to find the Spring equivalent for Go (or Django, Ruby on Rails, etc) when it doesn’t actually exist. That’s by design.

I'm not sure how it's "by design". Go, by itself, doesn't give much more than e.g. Java gives with its Servlet base libs, etc. And yet Java has Spring, and some popular framework could very well emerge as the "THE" framework for Go.

Whether that framework would conform to the stdlib interfaces / middleware is another question. It might not, if it's compelling enough (there are lots of popular Java non-servlet API conforming frameworks, e.g. Play, Vert.x, etc).

It's only because of fragmentation (and small still market, with lots of NIH) that one hasn't emerged as such, not some special Go design. Many/most Go-ers like to keep it simple, so they don't adopt any big framework lib (after all, if they didn't keep it simple, they wouldn't be using Go).

Re: Go in Production – Lessons Learned

#90

Earlier quoted context omitted.

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?

> You can use GET requests and GET requests are cacheable.

GET requests are a crutch added to GraphQL precisely because of limitation of POST requests.

And the backend still has to normalise the GET request, and possibly peek inside it to make sure that it is the same as some previous request.

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

Your schema is a single endpoint with all the fields you need exposed. Oh, but a person X with access Y might not have access to fields A, B, C, and D.

Too bad, these fields can appear at any level of the hierarchy in the request, deal with it.

> how to... -> yes?

A GraphQL query is ad-hoc. It can have unbounded complexity and unbounded recursion. Ooops, now you have to build complexity analysers and things to figure out recursion levels.

A GraphQL service usually collects data from several external services and/or a database (or even several databases). But remember, a GraphQL query is both ad-hoc and with potential unbounded complexity. Oh, suddenly we have to think how much data and at what time to we retrieve, how do we get the data without retrieving too much, and without hammering the external services and the database with thousands of extra requests.

That's just from the top of my head.

Ans so you end up with piles of additional solutions of various quality and availability on top of GraphQL servers and clients: caching, persisted queries etc. etc.

Post reply on HN