rollulus
8 days ago
As the article also mentions: instead of checking if your program has a dependency on something that contains vulnerabilities, govulncheck checks if vulnerable code is actually reached. I find that so awesome. (And I know, someone is going to point out that hipster language foo does this too and better — it’s not the norm).
zelphirkalt
8 days ago
If the code cannot be reached, what is the point of having it as a dependency?
Does it know which part of a dependency has a vulnerability and check, if the execution reaches _that_ part? Then it would make sense.
FiloSottile
8 days ago
> Does it know which part of a dependency has a vulnerability and check, if the execution reaches _that_ part?
Yes, govulncheck does symbol-level reachability static analysis, and the vulndb is manually annotated with affected symbols for each vulnerability.
(So glad to see a comment about this at the top, I have sometimes feared we made a mistake in designing a low-noise vulnerability scanner, because I've often seen complaints that "it doesn't work" because it doesn't show as many vulnerabilities as its more popular, less accurate alternatives.)
chucky_z
8 days ago
My understanding is that the primary goal is to determine that if a program is pulling in a dependency, and only using a small part of it, to determine if that part is vulnerable or not. This allows a program owner to know if they need to do an emergency version bump in the face of a CVE or something like that. For some businesses doing emergency deployments is a massive deal.
lynx23
8 days ago
> hipster language
Funny, I always considered Go a hipster language for Google fanboys.
Cthulhu_
8 days ago
It kinda is if you're thinking about the manual-coffee-grinder-french-press hipster who eschews automatic coffee makers. Rob Pike doesn't believe in syntax highlighting and to date the Go website / interactive editor doesn't have any. "When I was a child, I used to speak like a child, think like a child, reason like a child; when I became a man, I did away with childish things."
Anyway, that's fine, I like Go and I like grinding coffee manually on occasion.
lynx23
8 days ago
Funny, I have a similar analogy when it comes to mice: Small children lacking verbal communication skills can only point at things, which is the equivalnet of using a"pointing device". When they grow up, they learn to speak meaningful sentences to express themselves. Which is equvalent to learning to use the command line...
timeon
7 days ago
> french-press
How is that hipster? Did you mean aero-press?
bccdee
7 days ago
A lot of people see anything other than a Black & Decker drip coffee pot or a Keurig pod machine as "hipster coffee," somehow. But being perceived as hipsterish is the only thing that makes something hipsterish, so they can't really be wrong.
silverliver
8 days ago
Perhaps, but all I really care about is having a complied, strongly-typed language with a fully-featured modern stdlib and good cross-compilation support that includes wasm. If that comes with an automatic admission to the Google Fanboy Club, then sign me up.
What other well-established languages do we have that meet this criteria? I know .net is a strong contender but do we have other options?
vlovich123
8 days ago
Rust & Java also come to mind (yes, Java can be AOT compiled). Erlang too if you want more fearless concurrency if you’re OK with JIT languages. There’s lots of alternatives to Go in its space but it does have mindshare and there’s nothing wrong with staying on the well trodden path even if it’s full of if err != nil instead of sane error chaining built into the language.
johnisgood
8 days ago
I have nothing against "if err != nil", in fact, I like it.
As for a replacement of Go, I would have to say Erlang or Elixir. I use Go code for non-serious distributed software, and Erlang and Elixir for more serious ones. That is not to say that Go cannot be used for serious stuff though.
pjmlp
8 days ago
Regarding Java, since early 2000 to be more precisely, although it required paying for commercial JDKs like Excelsior JET.
Nowadays besides the more well known GraalVM, there is OpenJ9 and its cousin Android since version 5.
PTC and Aicas remain as two well known commercial Java vendors, with AOT toolchains, alongside bare metal and real time GC support, although their focus is embedded deployments.
fmbb
8 days ago
Erlang is not strongly typed and cross compiling apps with native dependencies is not straightforward. Running it on WASM is not common (is it possible?). It does not have a comprehensive standard library like Go.
It is compiled though.
vlovich123
8 days ago
Erlang is most definitely strongly typed [1]. Perhaps you confused static & dynamic typing? Easy mistake to make. Similarly, from what I could find Erlang is typically run on BEAM [2] which is an interpreter virtual machine that executes BEAM byte code (with a JIT option).
Since I’m not an expert on either language, here’s my take of how ChatGPT summarizes Erlang vs Go on various options.
Go’s standard library is primitives driven for general purpose programming while Erlang’s is purpose driven for distributed programming. So it depends on what you mean by “comprehensive”. For example, out of the box Erlang provides an environment for writing correct, robust distributed programs. If comprehensive means having a bunch of knives & start juggling that’s a different use case.
[1] https://learnyousomeerlang.com/types-or-lack-thereof#:~:text....
neonsunset
8 days ago
Erlang is interpreted. It is in the same class of performance as Python and Ruby. If you want a relatively high-level and performant alternative with great concurrency support your options are C#/F# (you are likely find the tooling pleasant) and perhaps JVM languages once they adopt structured concurrency (but you are likely to find the tooling less pleasant).
Graal Native Image support is very niche and does not provide the same level of experience as .NET’s NativeAOT nor has tricks up its sleeve like static linking with native libraries.
igouy
8 days ago
> Erlang is interpreted.
neonsunset
8 days ago
Thanks! I was briefly aware that BEAM has JIT capability but performance numbers usually put it next to other languages with interpreted bytecode so I assumed it was either not enabled or used in some specific scenarios. I should update my knowledge.
SirGiggles
7 days ago
It's possible your previous knowledge was based on HiPE, which to my understanding was kind of sucky.
The new JIT in Erlang/OTP 26 is called BeamASM and is based upon asmjit
shakna
8 days ago
Really...? In my experience, whilst Erlang is slower than most AOT languages, its an order of magnitude faster than Python or Ruby. Most benchmarks I've seen also back that up.
neonsunset
8 days ago
Unlike Python it scales with cores perfectly, which makes sense given that’s what BEAM is designed for, but the baseline cost of operations is in the same group.
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
It’s a bytecode-interpreted language. If it were JIT and statically typed we would have seen drastically different results. Also JIT output being slower than static compilation is a myth. When compilation happens does not dictate the kind machine code the compiler can produce (mostly, compiler throughput and JIT-time optimizations do influence this, but are not a strict limitation).
jhogberg
8 days ago
Erlang is JIT compiled since 2021.
Grandparent is also correct in that it tends to be faster than Python et al. If we have a deeper look at the benchmarks [1][2], as long as there is no significant amount of bignum arithmetic (where both call C code) or standard IO involved [3] it's consistently faster than Python, and often by a large margin.
[1]: https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
[2]: https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
[3]: Standard IO goes through several indirections to make it work with remote REPLs; other forms of IO do not suffer from this.
igouy
8 days ago
For your convenience:
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
> no significant amount of bignum arithmetic
There is none shown in the charts. There is none shown elsewhere apart from where aribitrary precision arithmetic is shown explicitly: pi-digits.
mike_hearn
8 days ago
You can statically link with native libraries if you have static versions of them in GraalVM:
https://www.graalvm.org/latest/reference-manual/native-image...
neonsunset
8 days ago
Does it let you bring your own .a/.lib and statically link it into the final product? In .NET you can pass DirectPInvoke + NativeLibrary build properties and link with anything provided the imports don't conflict (because at the final step it's the system-provided linker that statically links together the components nativeaot binaries comprise of, so you are effectively just adding another compilation object).
For example, I can take a mimalloc.lib/.a, link it into the binary and the pinvokes into its mi_malloc, mi_realloc, etc. will all be just direct calls + branch checks for GC poll if applicable (well, you need to suppress gc frame transition but it's still about three steps in total). It will be just a single static bundle at the end.
I know that conceptually GraalVM Native Image and NativeAOT are similar tools, but they mostly seem that way at a distance and at closer inspection they only partially overlap, much like C# and Java themselves do.
mike_hearn
8 days ago
You can yes although the docs don't make that obvious.
https://www.blog.akhil.cc/static-jni
You can also use the FFI to avoid JNI.
I tend to feel that static linking is overrated. The moment you want easy upgrades of your app you need extra infrastructure anyway, and every tool for distributing such programs can handle directories as well as files.
neonsunset
8 days ago
> I tend to feel that static linking is overrated.
I agree. My response was just meant to indicate that NativeAOT has comparatively more effort and focus in .NET ecosystem than GraalVM's Native Image in JVM's, and as a result is an option that is easier to opt into where it makes sense. There's an intention to make it play as nicely as possible with most common scenarios and ideally not require user input when enabling it even with difficult to analyze reflection scenarios.
mwcampbell
7 days ago
> I tend to feel that static linking is overrated.
For me, the big win of static linking is startup time. Just mmap the executable and go. No need to slow down the startup process with the very branchy process of resolving and loading DLLs.
mike_hearn
7 days ago
That's true, although pre-linking means the bad old days of apps spending most of their time in the dynamic linker during startup are mostly behind us even when a program uses a reasonable number of libraries.
mjevans
8 days ago
Go / golang added https://pkg.go.dev/errors
Which includes nested / stacked errors and helper functions for checking them.
It doesn't implement error classes, but you can create a stacked chain of errors which achieves the same sort of 'Handle a classification of error' (anything which includes that class).
Older libraries don't use these features, as far as I know. So it's sort of like the half-baked enumerate everything sort of generic functions that older stable versions (like on hacker rank) ship.
euroderf
8 days ago
The %w printf verb. It yields much more than a stack dump. Get meaningful error annotations from every step back up the callstack.
vlovich123
8 days ago
I think you missed my complaint was that unlike more modern languages like Rust, Go has way too much boilerplate for error handling and not only does it not have error chaining via a `?` operator, it doesn’t even force you to check the error meaning I’m sure there’s plenty of missed error checks in production code leaving all sorts of vulnerabilities lying around. The package you linked in no way addresses what I wrote.
gwd
8 days ago
> have error chaining via a `?` operator
Although I do frequently find typing in the boiler plate of _every_ _single_ _error_ a bit of a faff, it does prompt me each time to really think "what if an error really happened here". I'm inclined to think that something like the ? operator makes it much easier to just toss in the ? and not consider the implications of an error.
> even force you to check the error[,] meaning I’m sure there’s plenty of missed error checks in production code
Something the equivalent of "#[must_use]" would certainly be an additional aid, (as would const pointers).
EDIT but one of the tools mentioned in the blog post, golangci-lint, will warn you of unchecked errors.
vlovich123
8 days ago
You’d really like the C community. They like to say things like “although I do find the setfaults annoying, it really makes me think carefully about memory ownership and layout”. The problem is that if you don’t have a consistent way to accomplish a task correctly, something like errors that could happen a nearly every function call, then you’re very likely to make a mistake. Coupled with that, most people ignore testing for error conditions or simulating errors, so the error handling has a very high likelihood of having bugs.
gwd
7 days ago
> Coupled with that, most people ignore testing for error conditions or simulating errors, so the error handling has a very high likelihood of having bugs.
Er, is Rust any different in that regard? As I said, I tend to think the `?` operator would make that worse, as the error path is so much less visible. In Golang if you don't test your error path, at least it will be listed as having no coverage -- is the same thing true in Rust?
randomdata
6 days ago
The `?` operator is even worse than that as it leaks implementation details by default (the default you are undeniably going to lean on if testing/simulating error cases is more than you can handle), which is going to make someone's life a miserable hell when requirements change in the future.
But it seems most programmers here are only around for the MVP and are content to let the future of maintaining their garbage be someone else's problem. Which, I expect, is also the fundamental aversion they have to Go, which is trying to create a world where you still want to work on the same codebase in 30 years.
Not that Go is perfect. It most certainly isn't. But you are going to spend more time obsessing over things that aren't even all that important in practice when your "launch and dash" lifestyle is being threatened.
lenkite
6 days ago
Rust: this `Result` may be an `Err` variant, which should be handled.
I am not at all a fan of Rust but dissing the `?` operator and the compilers error/warning messages regarding error handling and somehow thinking Go is superior here when its objectively not is "inconsistent with reality"
randomdata
6 days ago
> The problem is that if you don’t have a consistent way to accomplish a task correctly
I know of no programming language that provides a consistent way to deal with values correctly, if the venerable if statement (or whatever is equivalent) is not it.
What is this magical fairy language that you speak of or envision?
mjevans
8 days ago
I've been interested in learning more about Rust, but so far haven't had a project that seemed like it'd be worth learning a whole new language structure.
So, I was responding to my _understanding_ of what you had written, which apparently didn't adequately explain what you sought to those who haven't seen the thing you were trying to reference.
I do occasionally use a helper function in golang like 'nilOrPanic()' which if it's given an Error type that isn't nil causes a panic(); which isn't so useful outside of development or toy exercises.
vlovich123
8 days ago
A language like Rust makes the Error and Option types first-class. It’ll be a compiler warning (or error? Don’t remember right now) if you ignore the return from a function that returns one of these. Go requires a separate linter and relies on uncaught variables. Minor distinction but important one because defaults matter.
If you want to panic on error/option (i.e. you don’t think it’s going to happen), you add an exclamation mark after the error. If you want to unwrap but propagate the error effortlessly, add a question mark. This syntactic sugar is a pretty common ideas at this point not unique to Rust. What is a bit more unique is that Error and Option are sum types. This means that you can’t just access the value without unwrapping them somehow and unwrapping requires you to either handle the error by a match or conditional statement, propagate (?), or panic (calling .unwrap() function). But you have to make that decision and can’t ignore it so while you have to think about what you want the error handling to look like, you can’t ever accidentally forget (& since mostly you forward, ? Makes things easy even if you need to bridge different error types).
nitely
8 days ago
They are going to add boilerplate free error handling sooner or later. There are many proposals for "Go 2" already.
ozgrakkurt
8 days ago
Zig is pretty good
paulddraper
8 days ago
You either die a hipster or live long enough to become mainstream.
Cthulhu_
8 days ago
Go is a retro nostalgia language, taking programming languages back to basics, removing syntax highlighting and advanced concepts like exceptions and function shorthands because that's what it was like in the 70's.
rob74
8 days ago
Pray tell, what is it about Go that stops editors from using syntax highlighting when displaying Go code?
Seriously, IMHO Go is less "retro nostalgia" and more trying to stick to proven concepts (e.g. there was no test driven development in the 70s, and Go has testing/documentation/examples built into the language) while leaving out things like exceptions and inheritance that, while widespread, have significant disadvantages.
euroderf
8 days ago
I'll give up my Go when you pry this PDP-11 emulation from my cold, dead hand.