Hacker News new | ask | show | jobs
by burntsushi 3049 days ago
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.)