Oddbean new post about | logout
 I Agree very much. Knowing how bug prone most of our C/C++/Java bases are and adding AI on top of these Swiss cheese fundamentals is in my nightmares. This is why I would never give AI control access to my environment. LLMs are just too prone to instruction injection. 

I love golang so much. The only reason I wouldn't call myself a golang maxi is because if I had to do embedded devices and things that must hook into C, i would reach for odin. But odin is essentially a go-like with lower level control of memory. Check it out if curious.

- https://odin-lang.org/ 
 you have my attention 
 yeeah just to make a more nuanced comment

i think it was an error in Go's design to not make memory management more explicit

i tend to think of every var statement as an allocation instruction, but i don't think that's how it works actually

the trickiest thing is what to do when you produce values that you need to send outside of a function scope, and specifically when they are pointers, pointers make such a mess, but are neccessary, and at the same time extremely troublesome because it's nearly impossible to deduce until you actually execute it in every possible condition what actually happens to the memory

odin looks interesting but i'm too committed to Go tbh

it's just annoying the piss out of me new quirks in the modules system causing me a headache

i honestly wish there was an opt out for modules, i miss the old days, oh, there was problems with mangled gopaths if you worked on more than one unrelated project in the same gopath but tha could have been fixed so much more simply than modules, i still hate modules, took me a year to finally bend to them and i still regret it 
 > pointers make such a mess, but are neccessary

ikr! I've shot myself with pointers and nil interfaces countless times. I try to write in a more pure functional style to be more aware of pointers and mutability but Go is really designed with interfaces in mind. So it's always easier to put state inside a struct and attach methods to it. Makes extending and refactoring very easy, but it also leads to more pointer receivers and heap allocs. Oh yeah the heap! Wish it was easier to deduce if a var will escape to the heap. Just read a good article about it, but it's never straight forward:

https://medium.com/eureka-engineering/understanding-allocations-in-go-stack-heap-memory-9a2631b5035d

The modules are very powerful if you're the downstream and upstream follows strict SemVer. I understand the need. The things I have headaches around is the change in behavior  from v0 to v1 and the change in import path with every major version bump.

But I have very few grumps about Go as a whole and continue to love using it day to day.

> odin looks interesting but i'm too committed to Go tbh

That's why it caught my eye. I've been programming in Go almost exclusively for almost a decade. Odin has taken a lot of the good ideas and lessons of Go and has some really nice ergonomics like the explicit context, or_return operator and really the best error handling I've seen so far. Even the package names they use are sometimes the same as in go's stdlib, so it's very easy for a gopher to read odin once you know the small syntax changes. Look at the hello world:

```odin
package main

import "core:fmt"

main :: proc() {
    fmt.println("Hellope!")
}
``` 
 there was a nice language called V but to be honest it was a bit too close to Rust in it's base principles and syntax

i actually proposed an extension of the return syntax to allow it to be used  to directly break out in error condition but i forget reasons ian lance taylor said nein

i personally have very few problems with managing state and pointers anymore for the type of thing you describe - it just takes a little experience to know - most of the time you want to use a mutex, sometimes an atomic is better when it's just a single value

the issue of values escaping to the heap is a pretty pesty one, but only really matters in so much as if your code might suffer from the STW GC pause that happens when it has to be reorganised or allocated in the first place

for sure, if at all possible you try to accurately allocate slice capacities when you make new slices, and for those situations when you have a lot of memory being rewritten, new data stored and old data quickly forgotten about 

yeah, this is the one annoying thing, you really have to do freelists sometimes and you really need to be careful about allocating memory for things in go, it's too easy to just forget and wind up blowing the stack and bloating the heap and having GC pauses and that's just not ok if you are trying to keep latency down

honestly, all things considered these are small inconveniences  compared to the memory hell of C or the OOP hell and compile time of C++ or the fucking smarmy attitude of "wustatshins" god i hate rust god i hate mozilla *breathe* 
 ah yeah, also, don't do pure functional... pass by value is ok for small things but it quickly blows out into a data copy problem and when the data contains pointers as well, then you have knotty puzzles for the GC to deal with as well

there's a reason why the two languages that are most notorious for blowing up your memory and dying due to OOM are C++ and Haskell, one is nasty OOP/template/variant syntax disambiguation, and haskell is constantly copying memory instead of allowing it to be mutated

neither approach are optimal for the hardware, you'll get better at knowing what approach to use with problems as you solve more problems :D don't worry! and do always keep reading those good texts about internals like memory management, that's really important shit, i probably need to do more of this kind of study but i did a lot over the years already