https://julialang.org/
MORE TIPS:
MORE TIPS:
Go is not just a slightly better version of C.
In fact, Go is a completely different language and has very little similarities to C.
- C and Go approach memory management in totally different ways: Go is garbage-collected while C is manually managed. This difference alone is already humongous since these approaches require totally different techniques of writing code. GC makes Go much easier to write than C but adds overhead compared to carefully written C code. C takes much more effort, time and knowledge to get right in terms of memory management. It’s also much easier to get a memory leak in C than it is in Go, and if you happen to run into a segmentation fault - C won’t tell you where it happened by default (only a debugger will) while Go will always give you a detailed stack trace.
- Go is inherently concurrent and non-blocking, C is not. A Go program is executed by a so-called “goroutine” and can spawn millions of other goroutines which are all multiplexed through an internal pool of system threads. C is inherently single-threaded and while you still can use system threads in a C program - the techniques of writing asynchronous and concurrent code in Go and C are totally different!
For example, it’s fine to block a goroutine with a blocking operation like an HTTP request, a filesystem operation or a database query because under the hood the goroutine scheduler will swap it out for another goroutine preventing the program from blocking a system thread, but you can’t do this with C because you’d block an actual system thread which you can’t create many of, so you’ll have to use totally different techniques like work-stealing pools, event loops, callbacks etc.
Creating system threads in C is also much more expensive than creating a goroutine in Go. Go allows you to write a server where each connection is handled by a separate goroutine and it’s going to be non-blocking and multi-threaded by default while equivalent C code is going to be much more complicated! - Go is strongly statically typed, while C is rather loosely statically typed. For example, you can’t just cast pointer types to any other pointer type in Go, the compiler won’t let you, but in C that’s easily done and I’ve seen people do it a lot. In Go, you’d have to use unsafe.Pointer and it’s there for very rare cases, it isn’t used often (the package isn’t called “unsafe” without a reason).
- Go has much better tooling than C, it has built-in testing, benchmarking, linting (go vet for example), a race detector, different built-in profilers, gofmt etc. and it feels like it’s cast in one piece. C, on the other hand, doesn’t have all that by default making it harder to work with.
- Go is much easier to cross-compile than C. Cross-compiling a Go program to ARM Linux on an x86 Windows machine (and vice-versa) is as easy as
GOOS=linux GOARCH=arm go build
, C, on the other hand, requires a rather complicated setup in order to cross-compile properly. - Go isn’t just “slightly” easier to read and write, it’s significantly easier to write than C and it’s also much easier to read and make sense of!
For example, Go doesn’t have a preprocessor, which adds a hell of a lot of complexity in C because it generates confusing compilation errors and sometimes makes C code incredibly hard to read and understand.
Go has interfaces, struct “constructors”, methods, type-switches, channels, and much much more. All this makes C feel like Assembly code. - Compared to C, Go has rather sophisticated dependency management.
Go programs are made of packages, some of which can easily be included with go dep from 3-rd party Git sources (Go Modules will make dependency management even better, yet they’re currently experimental but will be coming soon). C has an outdated and cumbersome header-based dependency management approach, where the preprocessor first concatenates the source files and then compiles them. If you, for example, happen to include a header file multiple times in C then you’ll have a problem! Or if two headers define a similar macro - you’ll have another problem! Working with 3-rd party libraries is usually much harder in C than it is in Go. - C is much more interoperable than Go. Go has an unusual stack design where each goroutine has a ~4 kb stack by default which grows as needed to allow large amounts of goroutines to exist at the same time and this makes Go much harder to interoperate with languages like C/C++, Rust etc. C FFI, on the other hand, makes C much easier to get working with other languages and platforms.
C compilers also target a much wider list of platforms and CPU architectures than current Go compilers. - C compilers are much better at optimizing the hell out of your code, while Go compilers tend to compile your code much faster. The official Go compiler doesn’t do heavy optimizations as of now because that extra 5-10 % of raw computing power isn’t really worth the effort of complicating the compiler and making it slower since in Go’s usual use cases it makes more sense to scale both vertically and horizontally.
Finally, I’d like to add, that C and Go not only originate from different epochs, they’re also designed for completely different purposes. While Go, in fact, is a general-purpose programming language, C is rather more general purpose than Go (which is neither better nor worse) because Go was originally designed to replace C++ for writing networking software at Google. This is also the reason why Go doesn’t have user-space generics (actually, Go does have generics, they’re just built-in to types like
maps
, slices
, and channels
), it didn’t really need generics that much so the authors decided to not further complicate the language as well as the compiler to implement a feature they didn’t need back then (although now they're considering to add generics in Go 2 since Go gained much greater attention than its authors initially expected).
Go is “glorified” for its rather unique combination of a great concurrency model, great tooling, and minimalistic language design that helps engineers get problems solved fast and easy. It’s great for writing automation tools, CLI apps, networking software, APIs and web services, writing a device driver in Go instead of C though - probably isn’t a good idea.
P.S. Go and Python, are humongously different as well, but that’s a-whole-nother story.
No comments:
Post a Comment
Коментар: