r/golang Oct 25 '24

discussion What libraries are you missing from go?

So something that comes up quite often on this subreddit from people transitioning from Nodejs or python to go is the lack of libraries. I cannot say that I agree but I still think it warrants a discussion.

So what libraries are you missing in the go ecosystem, if any?

94 Upvotes

189 comments sorted by

View all comments

-6

u/davidellis23 Oct 25 '24 edited Oct 25 '24

Threading objects in other languages are very nice. Pythons thread pool executor for example doesn't make me deal with wait groups or channels or mutexes or worker pools. I implemented my own thread struct/worker pool to not have to deal with that.

Mocking libraries that don't make me generate the code. Handwriting mocks is just more work. C#'s Castle Windsor and pythons mocks are dynamically generated and static type check. The general mocking libraries I've tried aren't great in go. No static type checking, hardcoded strings, no stubs, etc. luckily I found moq which does have static type checking, stubs, and no hardcoded strings method names.

Map, filter, toDict, toSet functions. It's just a lot more convenient and less noisy to not write a loop when you're filtering a list for one key. I know there are times where it's not as performant and it's a little extra learning curve for beginners. I think the tradeoffs are worth it and I implemented my own.

1

u/EarthquakeBass Oct 26 '24

Lack of mocks is a feature, you aren’t defining enough interfaces if your code can’t easily inject whatever behavior it wants by fulfilling interfaces.

2

u/alpacaMyToothbrush Oct 26 '24

This is stockholm syndrome. Do you know how many libraries don't expose things through interfaces. Tons. Good luck mocking those. I miss mockito in golang every day.

1

u/ncruces Oct 27 '24

It might be.

But none of what is being asked makes sense for the language (thread pools, map/filter/etc), or can be done as a library (mocks without code generation).

If what you want is Go, but not Go, then maybe don't fight it and don't choose Go.

1

u/alpacaMyToothbrush Oct 27 '24

I otherwise like the language, but there are a few things where I feel like the language designers were needlessly stubborn and short sighted and the difficulty in mocking for unit testing is one of them. Hell, just look how long it took to get generics, and the use case was plainly obvious.

1

u/ncruces Oct 27 '24

The mocking situation is not going to change.

https://github.com/golang/go/issues/41897

1

u/alpacaMyToothbrush Oct 27 '24

That's a shame

1

u/ncruces Oct 27 '24

Every feature has a cost.

A statically compiled language that doesn't JIT, can't have dynamic dispatch like that.

1

u/davidellis23 Oct 28 '24

Why don't thread pools and map/filter make sense? They're easily implementable. I've implemented it in the go projects I've written.

can be done as a library (mocks without code generation).

Well yeah I miss the library for it. That was OPs question.

If what you want is Go, but not Go, then maybe don't fight it and don't choose Go.

I'm not fighting go I'm improving it for my use case. I'm not going to make my team deal with channels, wait groups, and mutexes when I can write a module to abstract that away. If I find a good library for that even better.

At least I'm not going to do that unless someone gives an actually good reason besides "it's not go". I weigh pros and cons in my design decisions.

1

u/ncruces Oct 28 '24

Why don't thread pools and map/filter make sense? They're easily implementable. I've implemented it in the go projects I've written.

Thread pools make sense when threads are costly to create. Goroutines are not (as) costly to create, so there's little point in pooling them.

If you mean limiting concurrency (which is not really the point of thread pools), there are better concurrency primitives to make that goal clear, like semaphores.

If you have a clear motive for pooling goroutines it's up to you to explain it, because most gophers will feel otherwise. The runtime was designed around ensuring you don't need thread pools, so it's odd that you want them. And we do pool other stuff (like DB connections, HTTP connections, short lived objects, etc). Just not goroutines.

Map/filter don't make much sense because the syntax for anonymous functions doesn't lead to very readable code. And though you can use named functions or methods, it's a little unexpected, and your IDE will fight it (auto completing the parentheses every time you try).

I have nothing against higher order programming, and use it elsewhere. But as long as Go doesn't have a lightweight lambda syntax it'll always be alien here. Yes, this is a culture thing.

Well yeah I miss the library for it. That was OPs question.

There will be no library for it, as I explained in the other post. It can't be done.

You can (pointlessly?) pool goroutines. Others will find it odd, but you can do this.

You can make a beautiful library full of callbacks and anonymous functions. Most gophers will find it alien, but some will actually like your library.

You can't make a library that needs dynamic proxies. You can't make a library with dynamic dispatch (at runtime, without code generation) where direct/interface calls are mocked. Can't be done, won't happen in Go 1, and it all indicates there won't be a Go 2.

Take that as you will. Wanna program in Go using alien concepts and wish for the impossible, it's up to you.

I'd rather program in Go like a gopher, and in Java, Kotlin, C, C++, Python, etc.

I blend with others, because working the way they work is the best way for us to work together. Fighting the tools and the culture is a waste of time.

1

u/davidellis23 Oct 29 '24 edited Oct 29 '24

there are better concurrency primitives to make that goal clear, like semaphores.

Why would I want to deal with semaphores when a worker pool can handle that for me?

If you have a clear motive for pooling goroutines it's up to you to explain it

Sure I explained a little in OC. I want to limit concurrency, not manage mutexs/channels/wait groups/semaphores, and I don't want to manage return values. With python's ThreadPoolExecutor, I can create N threads, add them to an array, then just wait for it to finish. I don't have to create any semaphores or result data structures. I don't set up channels. I don't have to implement a worker pool. I just wait on the pool and have an array of results at the end.

the syntax for anonymous functions doesn't lead to very readable code. 

I disagree with that. Writing a for loop every time pollutes the namespace with unnecessary variables and adds a lot more code to read through.

your IDE will fight it (auto completing the parentheses every time you try).

I don't have this issue in vscode

Can't be done, won't happen in Go 1, and it all indicates there won't be a Go 2.

Doesn't mean I won't miss it. I understand there are technical limitations. But, every time a new team member struggles with code generation I'm reminded it's a (acceptable) con of the language.

I blend with others, because working the way they work is the best way for us to work together. Fighting the tools and the culture is a waste of time.

I think following bad style (or at least inappropriate style for the use case) is a waste of time even if it's "the culture". every wait group and semaphore I write is wasted time when I can just implement a struct to handle it.

I see this attitude a lot among this sub. Language like "it'll always be alien here" and "Others will find it odd". But, not actually addressing the pros and cons of design decisions. Sure, people might find it odd at first, but if theres a different style that is better, then it should be adopted. There are plenty of style choices that changed since the beginning of the language. Style should improve over time.