Found myself trying to debug an issue with memory not being garbage collected in a program. It turns out go comes with a tool that shows you the different memory allocations and resource hogs between different goroutines. Super useful so far from what I’ve found on some basic debugging, but still trying to understand how the flamegraph, the visualizations when writing to a png, and some other utilities in there work.
Overall was happy to learn that there was included tooling for that purpose within go itself.
Go’s tooling is second to none; it’s one of the things I like best about it. The sheer number of debugging, benchmarking, live and static analysis tools is enterprise-level.
I will say, while having unit testing as a first-class supported function is fantastic, the test package is a big anemic. I had been using Ruby a lot when I first got into Go, and it was almost harder to write Ruby without doing test-driven development; it was so fantastically easy, it changed my entire vie perspective on unit tests. Go is… harder. There are no assertions built into the test package, mocking is a PITA, and all of those great Go language safety features make writing tests harder. Yes, there are a lot of this party tools to address these things, but honestly I wish
testing
had been a bit more built-out. Many of the defacto standard testing practices still dominant today were already well established by the time Go was released; there really was little reason not to provide more tools to make writing tests easier, and thereby encourage test-driven development.But, really, it’s a fairly minor grievance, and far too late to address.
I always get thrown off by ruby, mainly because of rails magic though whenever I look at it. Convention over configuration hurts my brain some days. My only experience with testing there was rspec and cucumber. Wasn’t great at either of those, but loved pytest a lot
For testing I end up putting things in a docker container and running pytest through it for sanity checks. May have to update my testing approach soon though to cover more low-level validation. My memory error looks to be from closing a channel before a child goroutine could write to it. My working theory solution I’m trying out tomorrow is just wait for a second write to the channel from the other child routine before letting the function end. Seems a little hacky to me but it should hopefully work
It also had the added benefit of teaching me that goroutines will hold memory from fmt.Sprintf calls in cases where they were used only as a function argument in a logger.
mainly because of rails magic though whenever I look at it. Convention over configuration hurts my brain some days.
I agree. Ruby has waaaay too much magic which makes it impossible to follow (dynamic typing makes it even worse).
And convention over configuration definitely has huge advantages in terms of consistency and terseness, but it is also way less discoverable because instead of a config file say “the stuff is in
foo
” you have to already know that everything infoo
is automatically treated as stuff.I often wonder if it would be crazy to have both: you have a configuration file that says where things go, but the values must be set to constant well-known values. Sounds kind of crazy so I’ve never done it but you would get consistency and discoverability. I expect people would complain about the redundancy though.