The big problem with errno is that it's a global: there's exactly one of them for your program. As soon as you start using threads you are screwed.
Go aims to make concurrency right. That means you can depend on a global variable for propagating error information.
errno in C is ultimately because C doesn't have multiple return values, and the alternatives (pointer arguments as implicit output) are sucky. Go has multiple return values, and so returning an error is natural.
errno is generally defined to be a macro like: (errno_location()), at least when you use the -pthread option with gcc.
The odd constructoin (the function returning an int which is dereferenced) allows the errno macro to work as an "lvalue", i.e. that you can still say "errno = 0" to clear its value.
Go aims to make concurrency right. That means you can depend on a global variable for propagating error information.
errno in C is ultimately because C doesn't have multiple return values, and the alternatives (pointer arguments as implicit output) are sucky. Go has multiple return values, and so returning an error is natural.