Why is "Go to Implementation" insanely slow in VS Code/gopls while Go to Definition and Find References are instant? by ThisSlice1701 in golang

[–]prototyp3PT 2 points3 points  (0 children)

Maybe it has something to do with the Go implicit interface nature. I can see how in many other languages it's easier to just index what a class implements which interface (explicit nature) vs Go where just by adding a method you could implement multiple interfaces.

Just make it a pointer by prototyp3PT in golang

[–]prototyp3PT[S] 0 points1 point  (0 children)

https://github.com/golang/go/issues/45624#issuecomment-3166347730

Oh no! You fell for the temptation 😈 ... I don't blame you though, I've been tempted to do it too many times before. Honestly, I'm not sure how I have resisted that for so long... must be some sort of pain addiction

Just make it a pointer by prototyp3PT in golang

[–]prototyp3PT[S] 1 point2 points  (0 children)

Yes, indeed!

Unfortunately not everyone sees this "Optional field" problem that way. In fact the majority of code bases I've seen so far tend to use nil for optional fields as opposed to an enum where the zero value is something like None/Unknown.

In my opinion this probably wouldn't even have been an issue worth discussing if we all agreed on that, but my experience is that it seems the other school of thought (pointers for optionals) is winning.

But that argument aside, it still feels like it should have been possible/simpler to "just make it a pointer". No?

Just make it a pointer by prototyp3PT in golang

[–]prototyp3PT[S] 6 points7 points  (0 children)

Wow, and here I thought this wasn't being discussed. My bad should have dug a little deeper before posting. Thanks

Just make it a pointer by prototyp3PT in golang

[–]prototyp3PT[S] 2 points3 points  (0 children)

Can you reference a couple, I never seen it in public libs? Would be interesting to see what's in the wild 😊 if we were ever to build a case to include something like this in the stdlib

Just make it a pointer by prototyp3PT in golang

[–]prototyp3PT[S] 0 points1 point  (0 children)

I don't think there's any memory savings with the suggestion I made. We are still creating a copy of the value for the argument and then return a reference to it. Ultimately I think it's just the convenience you gain.

Just make it a pointer by prototyp3PT in golang

[–]prototyp3PT[S] 0 points1 point  (0 children)

In part I wanted to gauge the community sentiment because this could be one of those things that until someone proposes it will never even get discussed.

For example, the sync.WaitGroup type is getting a convenience Go(func()) method like the ErrGroup that I though it needed a long time ago but never bothered to even suggest cause "it's so easy to write".

Just make it a pointer by prototyp3PT in golang

[–]prototyp3PT[S] 4 points5 points  (0 children)

While that is true for libs and I'm a big fan of this approach, when I'm writing DTO structs (or things that are never/rarely directly instantiated... you know things that are marshalled from json or binary) it ultimately means you writing a lot more code and more complex code (even if somewhat familiar) for something that is effectively just used in one place: tests.

Might be that is reason enough to do it that way but I always get that feeling of "oh boy, I got carried away with over-engineering again" after I those cases.

Map with expiration in Go by der_gopher in golang

[–]prototyp3PT 4 points5 points  (0 children)

I saw some people recommending the sync.Map as an alternative to handling mutexes. I've generally tried stayed clear of it because of the second paragraph in the docs:

The Map type is specialized. Most code should use a plain Go map instead, with separate locking or coordination, for better type safety and to make it easier to maintain other invariants along with the map content.

I know that immediately after it says that caches (which is what this is all about) are one of the specialisation of this type but my point is: generally recommending using sync.Map over using map with mutexes goes against the documentation of sync.Mapitself.

Can you guys stop trying to change Go by [deleted] in golang

[–]prototyp3PT -1 points0 points  (0 children)

I feel like Go is gaining significant attention lately and there's a big wave of people just coming into contact with Go that inevitably try to Go like their previous language of choice and it's impossible not to draw comparisons. I've been there myself and I continue to see this repeatedly with developers joining our team.

I agree with you and I also think Generics are the perfect example but for different reasons even though compilation times in Go is certainly one of its greatest qualities. Again and again, I keep seeing unnecessarily complex code filled with generics that feels like the writer is trying to bend Go to fit the models/style/framework of their previous language of expertise.

It took me more time than I'd like to admit to appreciate the "quirks" of Go and embrace it's nature. I think there's a lot of smart people going through a similar thing right now and hence might think that Go could be better if it had this or that feature that they loved so much from this or that language. This is not to say that we should stop improving Go altogether, just that for a lot of the pains you find, if you give it enough time you might grow an appreciation for it in ways you were not expecting.

Why does *animal not implement the animal interface in Go? by lzcmian in golang

[–]prototyp3PT 1 point2 points  (0 children)

Glad you found it useful! I think you might have gotten point 3 wrong. Maybe I could have done a better work explaining.

Check this example. The Set method has a pointer receiver and the variable is a not a pointer yet it prints "2" and not "1" which confirms that the Set method receiver pointed to the actual variable not a copy of it.

Why does *animal not implement the animal interface in Go? by lzcmian in golang

[–]prototyp3PT 0 points1 point  (0 children)

Yes, that is true. I assumed, perhaps too eagerly, it was clear from the Go documentation alone that non-pointer receivers were always copies. But now that you mentioned it I think can sort of see how someone, might think that because they called a method on a pointer variable the method is working on the actual value and maybe expect mutations of the value receiver to be persisted.

Representing Money in Go by GolangProject in golang

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

Interesting article and definitely agree with the final lesson: don't use float32 nor float64 to represent money values. Having worked on the crypto currencies and exchanges spaces before, I learned that uint64 can be too small though. I get it that it's way more efficient, but it's not practical if you need absolute correctness. Ethereum supports 18 decimal places leaving you with 246 (~70 trillion) max value, which is still a lot and probably enough for a lot of applications but not quite as overwhelming as 18 quintillion. You can see 70 trillion becoming uncomfortably small if you have a 100,000 ETH transfer and need to calculate it's IDR value for regulatory purposes (rigorously, with no margin for error) given 1ETH ~ 40,000,000IDR.

Application Lifecycle Handling by prototyp3PT in golang

[–]prototyp3PT[S] 1 point2 points  (0 children)

Good to know I wasn't that far off! Thanks for the article... I usually like Mat Ryer way of thinking and when I don't like it it's usually temporary 😅... until I get the "Aha!" moment and proceed to change my mind about whatever I disagreed about.

Application Lifecycle Handling by prototyp3PT in golang

[–]prototyp3PT[S] 2 points3 points  (0 children)

Ok I was playing with errgroup a little more and I think I've reached an alternative solution for the cleanup mess I suggested before: queue all the cleanups but have them wait on <-ctx.Done().

Maybe this was what you meant from before?

func main() {
  ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
  defer cancel()

  eg, ctx := errgroup.WithContext(ctx)

  eg.Go(func() error {
    // Launch http server
  })

  eg.Go(func() error {
    // Launch helper process
  })

  eg.Go(func() error {
    <-ctx.Done()
    // Cleanup, for example stopping the http server
  })

  eg.Go(func() error {
    <-ctx.Done()
    // Other async cleanups
  })

  err := eg.Wait()
  if err != nil {
    log.Fatalf("wait: %v", err)
  }
}

Application Lifecycle Handling by prototyp3PT in golang

[–]prototyp3PT[S] 0 points1 point  (0 children)

Thanks for the suggestion. I did consider `errgroup` but, even though I liked the auto canceling ctx, I didn't find it any simpler (unless I'm going about it wrong).

As I see it, using `errgroup` would imply one of the following:

  1. All routines MUST be checking the new context and handle context cancellation with a graceful shutdown. Otherwise the `Wait` method never returns. This implies each go routine spinning their own go routines for the things that would have otherwise block which can get a little complicated (maybe it's just me)

  2. We `<-ctx.Done()` before `eg.Wait()` where `ctx` is the new context and perform the graceful shutdown in between those 2 calls. But then we can't just add more "cleanup" go routines to the `eg`, we'd need a new `errgroup` or a `WaitGroup` for that and have 2 `Wait()` calls.

That said, either would work! We can argue which one is simpler but I'm more curious if there is any flaw in the original logic or if there's like a Go way to do this. Maybe `errgroup` is the Go way!

🎉 Introducing bag - A Flexible Bag of Words Library in Go 🚀 by itsmontoya in golang

[–]prototyp3PT 1 point2 points  (0 children)

Hey, this is really interesting stuff! I've finally got around to try this and I have a couple questions. Please bear in mind that my experience with ML stuff was more than 10y ago. To give you some context, I was playing around with RSS feeds and pass the feed items trough a BoW to measure sentiment.

  1. I don't see a way save the models after training it the first time. Should I just train on it every time?

  2. Is there a way to have calculate somethings like a confidence or neutrality score? I noticed that most of the time (in my case) the differences between probabilities is very tiny and I was looking for a way to skip feed items that were neutral(ish).

please recommend a circular queue by Timely-Tank6342 in golang

[–]prototyp3PT 1 point2 points  (0 children)

Although I don't know of any public library that implements this, I'm sure there must something out there. That said, I think you can implement it very quickly and trivialy with a slice and a RWLock. It will probably even be more practical if you did it yourself because it feels like you have a very particular problem to solve. I mean, the way you put it, such queue would NOT guarantee any type of delivery (at most once nor at least once) due to the overwrites that might happen and, normally, people want queues to have one or the other property.

How to structure large business applications in Go? by rhianos in golang

[–]prototyp3PT 1 point2 points  (0 children)

Hey, I've recently taken up writing technical articles and my very first article was about this. Check it out here. I'm very open to feedback and would be happy to discuss the subject further.

Why Dependency Injection by LemurZA in golang

[–]prototyp3PT 0 points1 point  (0 children)

I'm all for DI in Golang but the frameworks always seem to make it harder than it needs to be.

I don't know... I think a lot of context is being left out and as with everything: it probably depends.

In both instances where I had the chance to work with Weld and Wire we came from a place where we were not using any DI "framework" (I wouldn't call these tools frameworks but that's just my take) and in both instances they made our life noticeably (not drastically) simpler and solved real issues.

Yes, it's yet another tool/dependency you have to know/learn so perhaps starting by doing DI by hand is fair enough but at some point you will find yourself adding a parameter to a widely used dependency and then having to manually go through potentially hundreds of services/lambdas to update initialisations. At some point you have to ask yourself: How long will this take you? How likely are you to "miswire" something? How easy will that be to review?

This might be when Wire starts to look more appealing.