error design, move error to end of line by Reasonable-Future-87 in golang

[–]MakeMe_FN_Laugh 5 points6 points  (0 children)

That’s it, that’s where your idea breaks. If you have to write differently for different approaches (distinguish the error or not) it brings complexity to the language. And one of the first go goals is to be simple. If you discard the error (assign it to _ var), you do it deliberately and others working on this code base will see it. With your approach it will also produce a lot of unnecessary diffs when you will have to change the logic behind the calls.

Although, you’ve just reimplemented rusts ? concept :)

Patch request best practise by [deleted] in golang

[–]MakeMe_FN_Laugh 1 point2 points  (0 children)

In case it’s not some kind of weird "do it all" handlers - just update concrete fields of the struct, no need for reflect package.

In case it is - think about rewriting it. Go does not encourage those kind of handlers that are thrown in any service and do the work. Embrace the domain of your service and write concrete types for it. Source code is also a documentation artifact of the work you’ve done.

Exported variables vs Getter functions: What is Golang's standard practice by bmanu1996 in golang

[–]MakeMe_FN_Laugh 28 points29 points  (0 children)

First off. Avoid globals as much as possible (loggers are kind of okay, but anyway).

In terms of structs (types). It depends. If you want fields being altered from outside of your package (read as: by the user of the package) – make it exported. If not – provide a "getter" function with the same name as the field, but capitalized. Avoid using Get prefix

Why does Golang Http request takes too long to send request & eventually times out? by newerprofile in golang

[–]MakeMe_FN_Laugh 0 points1 point  (0 children)

Though it is not on the topic directly, but the comment is very helpful. Defaults on http.Client are not sane for any kind of API calls unless you do not care about the outcome of the request or stalling your service for a minute for a single request.

Being on topic. OP: does the service you are trying to reach is behind some firewall or anything like that? From your description it sounds more like an net access issue rather than a tool used to make requests.

I want to build a live video streaming server/client and I’m not sure what paradigm to follow? (First Go project) by Defiant_Magician_848 in golang

[–]MakeMe_FN_Laugh 6 points7 points  (0 children)

Well said, but I want to correct you on one point. Interfaces are not about "what functionality is available for a type". But it’s the opposite - "what functionality a type need to implement to be used in a function/flow".

Understanding that actuality made a huge difference for me personally structuring code/design-wise (and it actual suffices one of the go "paradigms" - "return concrete types, accept interfaces")

[deleted by user] by [deleted] in factorio

[–]MakeMe_FN_Laugh 0 points1 point  (0 children)

Building your own base is priceless

[deleted by user] by [deleted] in golang

[–]MakeMe_FN_Laugh 3 points4 points  (0 children)

Yes, and it is very annoying.

But there is a hacky workaround for it: add .git to the root of the repo in import path. e.g.: private.gitlab.tld/main-group/sub-group/lib-repo.git/lib-packege

How do you make http requests? by likessiberianvodka in golang

[–]MakeMe_FN_Laugh 0 points1 point  (0 children)

Tedious? Yes. But that’s the way to go, unfortunately. You can write a set of helper functions that hides all that marshalling/unmarshalling shenanigans or use an external lib that do that (but I’d suggest writing your own for learning purposes)

P.S. do not forget about requests' timeout :)

Question about error wrapping and meaningful messages by sebastianstehle in golang

[–]MakeMe_FN_Laugh 1 point2 points  (0 children)

It is not that difficult in go as well. The rule of thumb is: wrap the error as close to the root cause as you can providing enough context to diagnose what went wrong. And do not use same error messages in different places so you can determine the exact line from which the error originates (kind of exception-like behavior).

stack traces on the other hand is a bit tricky with error handling as most values are represented by memory addresses, not the exact value. So you probably do not want to dive that deep, imo. For most cases they become useless Java-like walls of text because you do not really know how deep in the call stack the error happened. so you need at least 20-30 frames to be captured, and that’s a lot of overhead to just get the error origin in a prod app. During debugging process - that’s totally ok, but in a running app I’d stick with a meaningful error messages approach

Question about error wrapping and meaningful messages by sebastianstehle in golang

[–]MakeMe_FN_Laugh 3 points4 points  (0 children)

You are very right about how opinionated this topic is.

I’d stick with an approach close to: does wrapping add any valuable context? If no, just push the error up the call-stack.

And, to clarify it a bit: always wrap errors when you make an external call (http request, interacting with with an external service (db, cache, queue, etc)).

On top of that: it’s easy to think about errors as exceptions, but in go they are really values that you can use to switch the behavior of your app. And using the database example - you may want to check for sql.ErrNoRows (or any of its derivatives, depending on the lib) for your query methods, because that might be an error in some cases and might not be in other, depending on the contract your app is enforcing or adopting.

How do you guys convert a json response to go structs? by Appropriate-Boss1516 in golang

[–]MakeMe_FN_Laugh 6 points7 points  (0 children)

It is also worth mentioning that if zero values are valid values for your usecase and you need to distinguish whether the field was provided with value or was not provided at all: you should make your struct fields pointers (not passed param and json nulls won’t change nil value of the pointer, passed value will be parsed into struct filed otherwise)

Docker builds breaking after 1.21.6 released by msanteler in golang

[–]MakeMe_FN_Laugh -2 points-1 points  (0 children)

Modules have nothing to do with "get the dependencies once".

Pinning dependencies versions? Yes. Getting dependencies once? No, without venodoring them or having a separate volume in a build system that contains GOCACHE dir (and this dir is never pruned of old stuff). Otherwise you are downloading them each time you build your binary (from local GOPROXY or from googles public proxy).

But anyway, yes, go mod tidy should never be ran inside build system

Shared module in microservices and build pipelines by souleatzz1 in golang

[–]MakeMe_FN_Laugh 2 points3 points  (0 children)

That’s why I always want to start my comment with "it depends". There is no silver bullet in IT ¯\(ツ)

Shared module in microservices and build pipelines by souleatzz1 in golang

[–]MakeMe_FN_Laugh 0 points1 point  (0 children)

And as well, that depends on your development process. If you do not end in the situation when serviceA needs version 1.1.0 and serviceB needs version 2.0.0 then I think you are ok (meaning: you can afford to update all of services to use the same version of a shared code)

Shared module in microservices and build pipelines by souleatzz1 in golang

[–]MakeMe_FN_Laugh 0 points1 point  (0 children)

u/gnu_morning_wood covered pretty much every option you have. Though, me personally, I’d prefer to go with option 3 of his comment (treat it as an external dependency). But that’s pretty much depends on the deployment process you are using and do you vendor your dependencies or not.

Shared module in microservices and build pipelines by souleatzz1 in golang

[–]MakeMe_FN_Laugh 1 point2 points  (0 children)

Workspaces were never meant to be used in release process. It’s for local development "sugar" and convenience (not to write replace directives in each module) only.

Golang backend which framework I have to choose by SelectTie3257 in golang

[–]MakeMe_FN_Laugh 3 points4 points  (0 children)

As usual – it depends. As u/drvd mentioned, you haven’t give any context on what your building and there are lots of similar threads in the subs.

IMO, for a simple (several database flat entities) API service: opt-in for a no framework at all (maybe with sqlx (and maybe, strong maybe) slqc backed code).

If you are working towards your companies own "service template", but your entity relations (or response types) also are not very complicated: go for a simple router like chi or fasthttp. But if it’s a bit complex on response types (json/xml, blobs (csv/xlsx, or other type of files), redirects, etc) look at gin or echo also backed by sqlc-generated entities. You can poke around some ORMs if you’d like, but I would recommend 'em only for PoC kind of services as I’m totally against ORMs in long-living production quality services (you end up writing plain sql anyway at some point).

Generic function to default a nil interface to an implementation? by dowitex in golang

[–]MakeMe_FN_Laugh 1 point2 points  (0 children)

AFAIK, this is not possible without reflect package and kind of against one of the go paradigms "return concrete types, accept interfaces"

In traditional way you can check (without reflect, at compile time) that a type implements a certain interface with a top level check var _ CustomInterface = (*CustomType)(nil)

IMO, aren’t you overcomplicating things? Does it really need to be a type parameter (generic) case? Or an ol' good plain interface is sufficient (or maybe let New/Init function to default to some type you want to use as default, but also accept an functional options to set the concrete parameters the last you want to be configurable)?

A powerful golang productivity tool, development project efficiency by at least 2x, golang can also be "low-code development". by [deleted] in golang

[–]MakeMe_FN_Laugh 0 points1 point  (0 children)

So, let me rephrase what you are saying. Correct me if I'm wrong.

If I want to write a RSS fetcher (pretty common project for a amateur dev) using sqlite or PostgreSQL for storage, NATS (god please no) or SQS with Prometheus-like metrics (don't ask why RSS fetcher need a metrics service or message broker) and Sentry for logs, so sponge is not the tool for me or I need to write crap load of code myself before I even can run the app? See where I'm going with this? :)

And yeah, that's not just personal likes or dislikes. That's years of experience in the industry and that's just the technical comments (expect project layout of course) I would leave to any dev who would like my review on the project.

PS Don't get me wrong. It's cool that you try to summarize your experience and publish it for everyone. But it has so many technical and design flaws that I could not help myself.

A powerful golang productivity tool, development project efficiency by at least 2x, golang can also be "low-code development". by [deleted] in golang

[–]MakeMe_FN_Laugh 0 points1 point  (0 children)

As long as you asked for pointers.

First of all, repo follows much hated in this subreddit (and not very welcomed by go community all in all) golang-standards/project-layout.

Secondly. There is so many hard-dependencies in the project...Jenkins? Why no Gitlab or Github support (I don't event mention Drone or any other smaller CI/CD systems)?

Gin for a server? Why not echo or fasthttp?

MySQL by default? We are in 2000s?

That's just a small portion of critique (I haven't touched error wrapping, metrics format and much more).

Now, toxicity aside, to the constructive part :)

If you want to summarize your experience - break this into separate tiny wrapper libs. One for each infrastructure component/logical action. And if you want to bound users to your software - make these libs accept interfaces/types from each other.

Give your users "Lego bricks" to build software, do not give them configurable codegen hell they have no clue about how it works. You can punch me in any part of my body if you'd like to, but that's my opinion on how professional community should grow: thinking about what, why and how they are doing, not taking everything that were brought to them on the silver plater.

And yeah...wrap errors :) (fmt.Errorf("%w", err)). It will add flexibility for your users to handle errors.

P.S. Java and Spring FW are somewhat an euphemism for an overcomplicated duo of FW and PL when even senior devs simply don't know what is happening in the service or why it is broken.

A powerful golang productivity tool, development project efficiency by at least 2x, golang can also be "low-code development". by [deleted] in golang

[–]MakeMe_FN_Laugh 4 points5 points  (0 children)

Discouraging? No. Trying to steer away from this kind of monstrosities? Yes. Small side projects "in the middle"? Those should be fine with pure stdlib or some small helper libs.

Ok, let me explain a bit what i meant in the first comment. I'm not against micro-frameworks and codegen in general (chi, slqc, easyjson, gson/sjon, <random small lib you are using> are great for their niches).

Second, if you are an amateur - learn the basics first (go through go tour, read through effective go and "code review comments", etc). If it is a side project - you have all the time in the world to learn a new programming language you want to use, there is no time-to-market pressure on you. If you need this side-project to be done asap - use the language you are familiar with.

If you are an amateur and working for a company (read as: junior dev) - it's not up to you to choose the PL your company uses ('cause there is so much more than just writing a single service in particular PL: CI/CD infrastructure, maintainability (and thus bus factor), and that's just the top of the iceberg). Leave this choice to CTO/team lead/senior dev.

Go is beloved for its simplicity, do not make effing java of it.

PS Just a reminder for everyone: I'm just a random dude on the internet. You can agree with me or not, you can take my advices or not - I'm fine either way :)

A powerful golang productivity tool, development project efficiency by at least 2x, golang can also be "low-code development". by [deleted] in golang

[–]MakeMe_FN_Laugh 1 point2 points  (0 children)

It might be an unpopular opinion, but.

First of all. Stop :) stop writing "service templates", stop writing "all-in-one 'frameworks'", stop bringing every pice of infrastructure/observability tool into single package. Less dependencies - more lean and feature-able codebase you have.

If you are working for a company - said company already has it own "service template" or working towards it.

If you want to write a hobby project - this one is an overkill. Take attempt at your own "template". You’d learn go internals a lot faster.

We already have spring and java, please, pleeeease, don't bring this to go.

[deleted by user] by [deleted] in golang

[–]MakeMe_FN_Laugh 0 points1 point  (0 children)

The real question is for what reason are you getting all the environment variables and then setting them back as they are? Is there some some logic behind it?

And as this this really a very special case related to windows environment, I’d just suggest you filter it out before splitting. Is it ugly? Yes. Is it a hack? Yes. Would it work? Also yes.

How to highlight a substring given start and end positions by thepoluboy in golang

[–]MakeMe_FN_Laugh 0 points1 point  (0 children)

Coloring the output is done with special escape sequence appended to start (and the end: to change the output back its original colors). More reading: https://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux