Jump to page: 1 2 3
Thread overview
Reflections on using Go instead of D
Jul 12, 2022
jfondren
Jul 12, 2022
AnimusPEXUS
Jul 12, 2022
Siarhei Siamashka
Jul 12, 2022
user1234
Jul 12, 2022
user1234
Jul 12, 2022
Adam D Ruppe
Jul 12, 2022
ryuukk_
Jul 12, 2022
jfondren
Jul 12, 2022
Adam D Ruppe
Jul 12, 2022
SealabJaster
Jul 12, 2022
SealabJaster
Jul 12, 2022
SealabJaster
Jul 13, 2022
jfondren
Jul 13, 2022
jfondren
Jul 13, 2022
Paulo Pinto
Jul 13, 2022
Bienlein
Jul 13, 2022
ryuukk_
Jul 13, 2022
ryuukk_
July 12, 2022

Howdy,

I've been using Go recently, for the following reasons:

  1. I want to quickly deploy and run a program across an excessively diverse
    range of Linux systems and also Windows, without needing a build farm.

  2. I'd like the program to be a completely static binary.

  3. I'd like the program to make HTTPS connections and maybe query a local sqlite database.

  4. I'd like it to not be Rust (because: my previous choice was Rust; this is a program that cares a lot about potentially malicious filenames; Rust's string type zoo was exhausting to deal with and I caught myself wasting tons of time on Rust micro-problems that didn't benefit the program).

That's it. The previous-previous choice was D, because I was aware that cross-compiling to Windows was possible, and because I'd already worked out how to use Docker and Alpine's ldc to build static binaries.

So, what happened with D?

Take static binaries: they're the default in Go, they're what the community expects, so not only does most everything work normally in a static build, but when dynamic linking seems to be required you can find that someone's already put the effort in to avoid it: for example, there's a Go port of sqlite: https://pkg.go.dev/modernc.org/sqlite

And in D?

RUN apk add ldc dub alpine-sdk openssl-dev zlib-dev llvm-libunwind-static curl-static

buildType "static" {
    dflags "--static" "-L--eh-frame-hdr"
}

That's part of the Dockerfile and part of the dub.sdl that already represent several problems overcome--I didn't know about that 'eh' frame flag until I was searching the forum for build errors. This gives me a static binary with

??:? <ERROR: Unable to retrieve function name> [0xffbeef]

spam on an uncaught exception, and I still couldn't get std.net.curl to not complain about being unable to dynamically load libraries despite it clearly having code for a static build.

There are a couple of different lessons to be taken from this, but the one I suggest is that D could use something like an application support tier list. D's a general-purpose programming language so you can technically do anything at all in it, so call "you can technically do that" tier 4 and start elaborating on higher tiers where a kind of program in a kind of environment is kind of reasonably done with some specific libraries.

e.g., want to make https requests?

  1. std.net.curl is in Phobos and only needs system libcurl, libssl, etc.
  2. vibe.vibe.requestHTTP can work with system libssl or the D port of Botan
  3. arsd-official:http can work with system libssl, with a caveat about 32-bit windows

The value I would've gotten out of some clear information like this is that I would've started with vibe+botan and maybe not have had any problems at all. As it was, when I realized I hit a wall, I'd already wasted tons of time and didn't want to risk wasting any more time even seeing if vibe would work. The value of such information for users of D is that it alleviates that fear, so that other languages are no longer the safe option.

The value of such information for D devs or D advocates is

  1. it encourages use of D where D is already a pretty good option
  2. it encourages users to be more prepared to help advance the language if they're consciously doing something that D has little support for
  3. (repeating #2) it saves users from trying to do something that D has little support for, getting burned by the lack of support, and going away
  4. it highlights support gaps as room for improvement that isn't DIPs or fixing bugs

With all that said, I don't think I've seen any language produce such a thing. My actual inspiration was Zig's release tierlist which is only about the compiler and standard library's suitability for different architectures.

Another lesson is obviously "you should have multiple languages in your toolbox and Go is just super good at this one thing and you can use D or other languages for other things", but this perspective doesn't leave much room for D in the end.

July 12, 2022

On Tuesday, 12 July 2022 at 02:42:00 UTC, jfondren wrote:

>

Howdy,

I've stopped using Go somewhere at middle 2021 and I used it from 2016. and I think Go code generation (templating/go generate) is awful and I'm won't going back. If I'll go somewhere from D , it will be Rust or C++ in both cases because of job opportunities.

As for topic "Go vs D", well, Go's basic interfacing strategy (like IO interface) is somewhat more unified and channels, select{} blocks are also makes life much easier.

also, maybe, ImportGo in D would be fun :D

July 12, 2022

On Tuesday, 12 July 2022 at 04:52:33 UTC, AnimusPEXUS wrote:

>

I've stopped using Go somewhere at middle 2021 and I used it from 2016. and I think Go code generation (templating/go generate) is awful and I'm won't going back.

Have you stopped using Go before or after the 1.18 release, which introduced generics? Something like https://blog.boot.dev/golang/how-to-use-golangs-generics/

>

If I'll go somewhere from D , it will be Rust or C++ in both cases because of job opportunities.

Are you generally trying to use a single language for everything or do you switch between multiple languages depending on the task? Is your current use of D a paid job?

I agree that when the job requires some specific programming language, then not much can be done about it. We can't just pick a single language and stick with it. Being familiar with multiple programming languages is a practical necessity nowadays.

July 12, 2022

On Tuesday, 12 July 2022 at 05:23:12 UTC, Siarhei Siamashka wrote:

>

On Tuesday, 12 July 2022 at 04:52:33 UTC, AnimusPEXUS wrote:

>

I've stopped using Go somewhere at middle 2021 and I used it from 2016. and I think Go code generation (templating/go generate) is awful and I'm won't going back.

Have you stopped using Go before or after the 1.18 release, which introduced generics? Something like https://blog.boot.dev/golang/how-to-use-golangs-generics/

From what I've read Go generics are not fully monomorphic. I've read there's a layer of indirection for non-basic types. Maybe that's what AnimusPEXUS meant by "aweful" ?

July 12, 2022

On Tuesday, 12 July 2022 at 02:42:00 UTC, jfondren wrote:

>

Another lesson is obviously "you should have multiple languages in your toolbox and Go is just super good at this one thing and you can use D or other languages for other things", but this perspective doesn't leave much room for D in the end.

Most popular languages are good for some specific purpose. D has some of the same issues as C++/C, but those languages are best when used with other languages, which makes them versatile ( by adoption frequency ). D and Go try to be versatile on their own, but that requires a significant effort. Go has succeeded for some domains by putting in that focused effort. If being versatile and productive are the most important metrics then Python is hard to beat...

In reality, most application software could be done in Python + TypeScript + C with good user satisfaction, but bridging between langages feels tedious so developers look for that one solution...

July 12, 2022

On Tuesday, 12 July 2022 at 07:16:59 UTC, user1234 wrote:

>

On Tuesday, 12 July 2022 at 05:23:12 UTC, Siarhei Siamashka wrote:

>

On Tuesday, 12 July 2022 at 04:52:33 UTC, AnimusPEXUS wrote:

>

I've stopped using Go somewhere at middle 2021 and I used it from 2016. and I think Go code generation (templating/go generate) is awful and I'm won't going back.

Have you stopped using Go before or after the 1.18 release, which introduced generics? Something like https://blog.boot.dev/golang/how-to-use-golangs-generics/

From what I've read Go generics are not fully monomorphic. I've read there's a layer of indirection for non-basic types. Maybe that's what AnimusPEXUS meant by "aweful" ?

Source : https://planetscale.com/blog/generics-can-make-your-go-code-slower

July 12, 2022
On Tuesday, 12 July 2022 at 02:42:00 UTC, jfondren wrote:
> 2. I'd like the program to be a completely static binary.

This generally isn't worth the effort. Just using the oldest glibc you want to support and dynamic loading openssl will generally achieve the same task - newer glibcs tend to work with programs built against older ones, but not vice versa. So building something on a new distro makes it look really incompatible, but building on an old one works fine.

I've also never actually seen a Go program be a static build...

> Take static binaries: they're the default in Go,

idk maybe it is just my system but this is an out-of-the-box go install with all the default settings:

me@arsd:~/test$ go build hello.go
me@arsd:~/test$ ./hello
hello world from go
me@arsd:~/test$ ldd ./hello
        linux-vdso.so.1 (0x00007ffe1fff6000)
        libgo.so.14 => /usr/lib64/libgo.so.14 (0x00007fdee7566000)
        libm.so.6 => /lib64/libm.so.6 (0x00007fdee7419000)
        libgcc_s.so.1 => /usr/lib64/libgcc_s.so.1 (0x00007fdee73ff000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fdee721a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fdee8cb5000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fdee71f8000)


That's nearly identical to D:


me@arsd:~/test$ dmd hellobasic.d
me@arsd:~/test$ ldd hellobasic
        linux-vdso.so.1 (0x00007fff4bdd0000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f52dcb50000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f52dca03000)
        librt.so.1 => /lib64/librt.so.1 (0x00007f52dc9f9000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f52dc9f4000)
        libgcc_s.so.1 => /usr/lib64/libgcc_s.so.1 (0x00007f52dc9da000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f52dc7f5000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f52dcbce000)



Can you do that test on your computer? Maybe it is just a config thing in my setup.

> 3. arsd-official:http can work with system libssl, with a caveat about 32-bit windows

Oh that's actually an obsolete note, I should remove that. I fixed it last year so it just works now.


BTW one of the problems with ssl is you also need the certificates... it is unlikely to work correctly with a self-contained static build anyway. I wonder just how Go does it...
July 12, 2022
On Tuesday, 12 July 2022 at 12:42:50 UTC, Adam D Ruppe wrote:
> BTW one of the problems with ssl is you also need the certificates... it is unlikely to work correctly with a self-contained static build anyway. I wonder just how Go does it...

Are you sure about this?

I static link openssl on windows, and i have no problems dealing with HTTPS/WSS urls, i'm not an expect there, but to me it just works (server has free letsencrypt certificates, maybe that's why, i still have no clue how all this works today lol)
July 12, 2022

On Tuesday, 12 July 2022 at 12:42:50 UTC, Adam D Ruppe wrote:

>

This generally isn't worth the effort. Just using the oldest glibc you want to support and dynamic loading openssl will generally achieve the same task

This is very fair, but with Go my effort is minimal enough that it's worth it to not deal with the problem at all, and it's not zero-effort either to use the oldest glibc I want to support. If I had a legitimately old system I'd have to find an old enough dmd to work on it, and building an old glibc on a new system sounds like a pain: https://www.lordaro.co.uk/posts/2018-08-26-compiling-glibc.html

Still, this probably would've worked out a lot better than trying to work with static D.

>

idk maybe it is just my system but this is an out-of-the-box go install with all the default settings:

Is that OpenBSD? On some platforms Go gave up on static builds because the ABI was too unstable (OpenBSD) or wrong for other reasons (macOS). On Linux the default is "not a dynamic executable", and you'd have to pull in a C library dependency to break that.

>

BTW one of the problems with ssl is you also need the certificates... it is unlikely to work correctly with a self-contained static build anyway. I wonder just how Go does it...

It cheats and grabs system certs from standard locations.

July 12, 2022
On Tuesday, 12 July 2022 at 13:31:56 UTC, jfondren wrote:
> If I had a legitimately old system I'd have to find an old enough dmd to work on it

Yeah, I hit that once, it is a bit of a pain. But just keeping around a thing from a few years ago tends to work pretty well most the time.

> Is that OpenBSD?

Slackware Linux. Maybe they did a different configure flag but their general policy is to closely follow upstream.

But even Go applications I've downloaded from other sources follow the same pattern...

oh well. I do know someone was using the musl libc with D (they sent me bug reports about cgi.d i had to fix to be compatible with it), idk the details though. Maybe we should make an article about that.

> It cheats and grabs system certs from standard locations.

Yeah, I added support for pulling Windows certs out of the system to my http2.d somewhat recently too... I think that was this year. So it can use both the openssl bundles and the separate Windows set. Worked really pretty well.

My lib also dynamic loads and detects incompatible versions, so it can adapt to 1.0 or 1.1 and such at runtime and just work.

But then openssl put out a 3.0 which has more random troubles. Ugh. But I'll prolly be able to adapt to that at some point too.

Still, I've found dynamic loading openssl is the best way to use it - static versions get outdated and websites move on to different algorithms, load-time linking hits incompatibilities. So runtime branching, while more work, gives best results.
« First   ‹ Prev
1 2 3