![]() |
|
![]() |
|
An Enum type has to be on the core Go team's radar by now. It's got to be tied with a try/catch block in terms of requested features at this point (now that we have generics).
|
![]() |
|
It baffles me that so many developers are unable to use pre-comit hooks for their code formatting tools, that exist since the 1990's, to the point go fmt became a revelation.
|
![]() |
|
It’s not simply a common pattern. It is a way of doing things in the community. The stdlib uses it, the libraries use it, and if you do not use it, people will not use your software.
|
![]() |
|
You have the same PL preferences as me. I haven't tried Rust yet, but Kotlin, modern C#, and F# all fit your requirements. Kotlin is closest because it uses the enormous Java ecosystem.
|
![]() |
|
I nearly wrote "you are holding it wrong" to nod to that quote. But it is really true - most errors in long running services are individual and most applications I've worked in ignore this when (ab)using exceptions. In our Go codebases, the error reporting and subsequent debugging and bug fixing is night and day from our Python, Perl, Ruby, PHP, Javascript, and Elixir experiences. The one glaring case where this is untrue is in our usage of Helm which, having been written in Go, I would expect better error handling. Instead we get, "you have an error on line 1; good luck" - and, inspired, I looked at their code just now. Littered with empty if-err-return-err blocks - tossing out all that beautiful context, much like an exception would, but worse. https://github.com/search?q=repo%3Ahelm%2Fhelm%20%20if%20err... |
![]() |
|
> but all the information you need to perform such analysis is there. No, it isn't, unlike C, in which it is. The C compiler can actually differentiate between an enum with one name and an enum with a different name. There's no real reason the compiler vendor can't add in warnings when you pass in `myenum_one_t` instead of `myenum_two_t`. They may not be detecting it now, but it's possible to do so because nothing in the C standard says that any enum must be swappable for a different enum. IOW, the compiler can distinguish between `myenum_one_t` and `myenum_two_t` because there is a type name for those. Go is different: an integer is an integer, no matter what symbol it is assigned to. The compiler, now and in the future, can not distinguish between the value `10` and `MyConstValue`. > Just like it isn't in C. You will notice this compiles just fine: Actually, it doesn't compile "just fine". It warns you: https://www.godbolt.org/z/bn5ffbWKs That's about as far as you can get from "compiling just fine" without getting to "doesn't compile at all". And the reason it is able to warn you is because the compiler can detect that you're mixing one `0` value with a different `0` value. And it can detect that, while both are `0`, they're not what the programmer intended, because an enum in C carries with it type information. It's not simply an integer. It warns you when you pass incorrect enums, even if the two enums you are mixing have identical values. See https://www.godbolt.org/z/eT861ThhE ? |
![]() |
|
>the error handling was one of the many positive features. sounds good on paper, but seeing "if err!=nil" repeated million times in golang codebases does not create positive impression at all |
![]() |
|
> sounds good on paper, but seeing "if err!=nil" repeated million times in golang codebases does not create positive impression at all Okay, but other than exceptions, whats the alternative? |
![]() |
|
The ability to quickly parse, understand and reason about code is not superficial, it is essential to the job. And that is essentially what those verbose blocks of text get in the way of.
|
![]() |
|
I find that knowing where my errors may come from and that they are handled is essential to my job and missing all that info because it is potentially in a different file altogether gets in the way
|
![]() |
|
The huge volume of boilerplate makes the code harder to read, and annoying to write. I like go, and I don’t want exceptions persay, but I would love something that cuts out all the repetitive noise.
|
![]() |
|
> try/catch for more than one call that can throw an exception or including arbitrary lines You generally need to skip all lines that the exception invalidates. That's why it's a block or conditional. |
![]() |
|
> I think something like when a variable type in an enum was an interface it would destroy the galaxy or something, Hah :-) > Here you Go: https://go.dev/doc/faq#variant_types Not quite the same: Variants are a constrained list of types. Enums are a constrained list of values. Let's assume that I agree with the reasoning for not having a constrained list of types. It still doesn't tell me why we can't have a constrained list of values. |
![]() |
|
While I have no particular beef with Rust deciding to call its sum types "enum", to refer to this as the actual enum is a bit much. Enumerated types are simply named integers in most languages, exactly the sort you get with const / iota in Go: https://en.wikipedia.org/wiki/Enumerated_type Rather than the tagged union which the word represents in Rust, and only Rust. Java's enums are close, since they're classes and one can add arbitrary behaviors and extra data associated with the enum. |
![]() |
|
Checked the definition. An enum is defined as a set of named constants. Id argue that a set by definition needs to be constrained. If it lacks the constraints/grouping id argue it no longer is a set.
|
![]() |
|
Sounds like JavaScript and typescript would be a good fit for you. Highly expressive, dynamic and strongly typed, and highly performant both on server side and within the browser.
|
![]() |
|
py2many does python-esque to both Go and Rust. The larger problem is building an ecosystem and a stdlib that's written in python, not C. Use ffi or similar instead of C-API. |
![]() |
|
> are not as performant as Go. Ymmv, you might be surprised if you actually bothered to benchmark. Depending on the workload, either JS or erlang can ultimately turn out on top. They're all optimized to a degree that each has a niche it excells at and leaves the others in the dust. even with heavily scewed benchmark like techempower fortunes (https://www.techempower.com/benchmarks/#hw=ph&test=fortune&s...) you end up with JS getting ahead of Go with raw requests. And not just slightly, but by 1.5 times the throughput. In other benchmarks, Golang does indeed win out with similar or even bigger advantages... so the only thing you can ultimately say is ... that it depends. Its a different story if you chose other languages though. But JS, Golang and Erlang are all extremely optimized for their ideal usecase. |
![]() |
|
Well hold on a second. The JS impl that you're talking about uses a minimal custom runtime (https://github.com/just-js/just) that you would never use—it barely implements JS. It's basically only used for this benchmark. It doesn't make sense to compare that to Go when we're talking about Javascript vs. Go performance. Scroll down to the "nodejs" entry for a more realistic comparison. |
![]() |
|
It looks like something was lost in the middle of your comment. You open with something about it be objectively bad, but then it jumps to something about how it is subjectively bad. What was omitted?
|
![]() |
|
I don't really think the sarcastic tone was called for, but the previous poster is right. "I can't name variables in my native language" is objective, but whether or not that's bad is subjective.
|
![]() |
|
So if you have a concept that doesn't have an equivalent in English you just kinda translate it and add a comment for other people of your language to understand what it is?
|
![]() |
|
For simple JIT-based but fully self-contained binaries, without adding any properties to .csproj, the command is a bit mouthful and is as follows
(you can put -p: arguments in .csproj too as XML attrs in This will give you JIT-based "trimmed" binary (other languages call it tree shaking). You don't need to specify RID explicitly unless it's different from the one you are currently using. For simple applications, publishing as AOT (without opting in the csproj for that) is
Add -p:OptimizationPreference=Speed and -p:IlcInstructionSet=native to taste.Official docs: https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-p... |
![]() |
|
The sibling comment pretty much sums it up. But if you want more detail, read on: Generally, there are three publishing options that each make sense depending on scenario: JIT + host runtime: by definition portable, includes slim launcher executable for convenience, the platform for which can be specified with e.g. -r osx-arm64[0]. JIT + self-contained runtime: this includes IL assemblies and runtime together, either within a single file or otherwise (so it looks like AOT, just one bin/exe). This requires specifying RID, like in the previous option, for cross-compilation. AOT: statically linked native binary, cross-OS compilation is not supported officially[1] because macOS is painful in general, and Windows<->Linux/FreeBSD is a configuration nightmare - IL AOT Compiler depends on Clang or MSVC and a native linker so it is subject to restrictions of those as a start. But it can be done and there are alternate, more focused toolchains, that offer it, like Bflat[1]. If you just want a hello world AOT application, then the shortest path to that is `dotnet new console --aot && dotnet publish -o {folder}`. Otherwise, the options above are selected based on the needs either via build properties or CLI arguments. I don't know which use case you have - let me know if you have something specific in mind ("Just like in Go" may or may not be optimal choice depending on scenario). [0] https://learn.microsoft.com/en-us/dotnet/core/rid-catalog [1] https://github.com/bflattened/bflat (can also build UEFI binaries, lol) |
![]() |
|
I'm not sure what exactly you mean by acknowledgement, but here are some counterexamples: - A proposal for sum types by a Go team member: https://github.com/golang/go/issues/57644 - The community proposal with some comments from the Go team: https://github.com/golang/go/issues/19412 Here are some excerpts from the latest Go survey [1]: - "The top responses in the closed-form were learning how to write Go effectively (15%) and the verbosity of error handling (13%)." - "The most common response mentioned Go’s type system, and often asked specifically for enums, option types, or sum types in Go." I think the problem is not the lack of will on the part of the Go team, but rather that these issues are not easy to fix in a way that fits the language and doesn't cause too many issues with backwards compatibility. |
![]() |
|
> transpiler just typically means it goes from one language i could write, to another i could write. What possible compiler target couldn't you write? Compilers are not exactly magic. |
![]() |
|
> Humans hand wrote binary for a while too hah. Like, as in flipping toggle switches? Isn't that just an input device? They were still producing machine code from that switching. |
![]() |
|
Thanks, I'd always thought targeted transformations -> transpiler, but it makes sense it's really a subset of general compiler functionality, sans binary output.
|
![]() |
|
Thanks for your response, but the Go spec asserts that Go source is represented as UTF-8. UTF-8 is a binary encoding. We're talking about compilers that produce something other than binary output. |
Some of the design decisions seem to me to be a bit more driven by being Rust-like than addressing Go's thorns though. In particular, using `impl` to define methods on types (https://borgo-lang.github.io/#methods), the new syntax for channels and goroutines (https://borgo-lang.github.io/#channels), and the `zeroValue()` built-in (https://borgo-lang.github.io/#zero-values-and-nil) seem a bit out of place. Overall though, if I had a choice, I would still rather write Borgo by the looks of it.