Hacker News new | ask | show | jobs
by IshKebab 3045 days ago
They really very different but...

+ Static typing (extra safety, robust refactoring, code completion etc.)

+ Much much faster and less memory use

+ Compiles to a relatively standalone binary (not as good as Go though)

+ No Python 2/3 nonsense to deal with

- Much more complicated. You have to deal with lifetimes and borrowing and so on. It's really very difficult and we still don't know how to write some types of programs nicely (e.g. GUIs)

- Slow compilation times

- Can get pretty verbose and full of type boilerplate

Honestly if I was coming from Python I think I would switch to Go first. It is still way faster than Python, has a very nice "batteries included" standard library, static typing, very fast compilation and makes nice static binaries. The downside compared to Python is that it isn't very expressive at all - you'll find yourself writing out loops where you might have used a one-line list comprehension or something in Python.

2 comments

> No Python 2/3 nonsense to deal with

Instead you have the stable/nightly nonsense to deal with, like Clippy and Rocket only working on nightly for example.

> Compiles to a relatively standalone binary (not as good as Go though)

Whats the difference?

We use glibc by default, so while Rust statically links all Rust code by default, that's still dynamically linked. You can use MUSL to remove that, where appropriate, but it's not the deafult.
To add an additional clarification here for others (I know Steve knows this :P), by default, at least on Linux, whether Go produces a dynamic executable or not depends on which things you import. For example, a simple hello world program will produce a static executable:

    $ cat main.go
    package main
    
    import "fmt"
    
    func main() {
            fmt.Println("Hello, world!")
    }
    $ go build
    $ ldd scratch
            not a dynamic executable
But anything using the network, like a simple HTTP server, will cause the Go tool to build a dynamic executable:

    $ cat main.go
    package main
    
    import (
            "log"
            "net/http"
    )
    
    func main() {
            // Simple static webserver:
            log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("/usr/share/doc"))))
    }
    $ go build
    $ ldd scratch
            linux-vdso.so.1 (0x00007fff161f0000)
            libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f796b0e8000)
            libc.so.6 => /usr/lib/libc.so.6 (0x00007f796ad31000)
            /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f796b306000)

Now of course, you can set flags to force Go to always produce a static executable, but the difference here isn't too much different with Rust. With Rust, you do need to install MUSL, add the target and then rebuild with an extra flag, but it's all very simple.

(To be clear, I am not criticizing Go here! There are good reasons why they link to libc by default when network stuff comes into the picture.)

What's the problem with that? Do you use any of glibc's private API?
The problem is that you have to think about it at all. If you compile on a machine with a new libc, and then try to run it on a machine with an old libc, it won't work. So you end up doing what most people do, even outside of Rust, which is take the oldest CentOS box you can stand and do builds on that.
The Autopackage project had a solution for this problem years ago called apbuild. It would search for the versions of glibc symbols and use the oldest possible ones, which resulted in portable binaries. With some quick googling I found the code here: https://github.com/DeaDBeeF-Player/deadbeef-plugin-builder/t... Probably doesn't work anymore though :/

It's a bit sad that this is still unsolved, probably due to the GNU people's hatred for closed-source distribution.

It's the GNU way:

1. Refuse to do something properly because it will make it too easy... or something.

2. Wait until someone else gets fed up enough and makes a better version.

3. Fade into irrelevance.

See: GCC/Clang, glibc/musl, Bash/??? (someone please make something sane)