Hi, I am the author of gopher-os. It started as a fun research project to learn more about the Go runtime internals and I didn’t really expect it making it to HN.
If you take a look at the Go runtime sources you will notice that all the low-level arch/os-related bits have been split into separate files which usually invoke some syscalls (e.g. the memory allocator eventually calls mmap)
The idea I am currently investigating is to first provide an implementation for things such as physical memory allocation and virtual memory mapping which would ultimately allow me to bootstrap the Go allocator. From that point onwards the plan is to incrementally add more features and gradually initialize the rest of the runtime.
This is much more difficult than it sounds as all code must be written in such a way to prevent the compiler from calling the runtime allocator (no variables allowed to escape to the heap).
I started writing a kernel in Go a while ago (and since abandoned it due to not having time.. I got as far as having a simple built in shell that let you do ls and cat on a FAT filesystem). The part about memory allocation and virtual memory wasn’t much more difficult than it would be if you were implementing your kernel in C or some other low level language.
The hard part is once you get memory and paging working, you’ll need a syscall interface. If you want to be able to run Go userspace programs, that means you need to implement the syscall interfaces for an OS that’s already supported, and can’t just go out and design your own, and at that part it starts getting a lot less fun.
Could you instead write your own syscalls but also your own $GOOS target for the compiler?
That’s possibly more work but it’s the approach I would have taken as it seems more fun than just replicating Linux (or whatever) syscalls.
Sure, you could, but then you need to fork the Go compiler too (and hopefully eventually get your GOOS target mainlined, which seems unlikely unless your OS gets popular) or you could do your userspace in something other than Go and implement what you need for that.
My point was just the memory allocation and paging isn’t significantly different than it would be writing an OS in any other language, it’s once you get to the part where you need to implement other people’s interfaces/standards to make a viable product that it starts bogging down (if you go that route. If you go your route, then you have two major projects instead of one: writing an OS, and adding a new OS target to an existing toolchain.)