[HN Gopher] Go 1.21
___________________________________________________________________
 
Go 1.21
 
Author : pk2200
Score  : 221 points
Date   : 2023-06-21 20:04 UTC (2 hours ago)
 
web link (go.dev)
w3m dump (go.dev)
 
| silisili wrote:
| These new packages, like slices and maps, were a long time
| coming. So glad it's finally here.
| 
| I cannot even begin to tell you how many different itemInSlice
| functions I've written over the years.
 
  | throwawaygo wrote:
  | tbh whenever I write one of these it makes me wonder if I can
  | accomplish the same logic in a better way.
 
| throwawaygo wrote:
| Can we get arenas yet?
 
| monocasa wrote:
| Nice, my push for actually using the sha256 instructions on amd64
| finally got released. 3x-4x increase in hash speed on most x86
| which is really nice for content addressable storage use cases
| like handling container images.
 
  | candiddevmike wrote:
  | Got a link to the PR? Curious to see how this is implemented.
 
    | jeffbee wrote:
    | It looks like https://go-
    | review.googlesource.com/c/go/+/408795
 
      | xyst wrote:
      | Seems like these changes only benefit you if you have an
      | Intel processor. If you have an AMD or Arm processor, you
      | won't see any difference.
      | 
      | Also, interesting to see assembly again after many years.
      | Haven't touched that since college during a compilers and
      | assembly course.
      | 
      | Edit: never mind, amd has implemented these "sha-ni"
      | instructions since "Zen" [1]
      | 
      | [1] https://en.wikipedia.org/wiki/Intel_SHA_extensions
 
        | monocasa wrote:
        | And adding that they already had support for ARM sha256
        | instructions https://github.com/golang/go/blob/master/src
        | /crypto/sha256/s...
 
  | jeffbee wrote:
  | Huh, that is interesting how they do that. They are enabling
  | SHA instruction support based on CPUID and without respect to
  | the value of GOAMD64. I did not realize Go was doing that.
 
    | monocasa wrote:
    | AFAIK, the sha256 extension isn't a part of any of the x86_64
    | microarchitecture levels, so a cpuid check is most
    | appropriate here at the moment.
 
      | jeffbee wrote:
      | Fair point. But what surprised me was the way HasAVX2 is
      | getting set. It is set on the hardware that has AVX2, even
      | if you set GOAMD64=v1.
 
        | als0 wrote:
        | In case anyone else was wondering what this is about,
        | here's some useful background
        | https://github.com/golang/go/issues/45453
 
        | burntsushi wrote:
        | Yup, that's standard, including in other ecosystems. It's
        | what I do in ripgrep for example when your target is just
        | standard `x86_64` (v1). GNU libc does it as well. And I
        | believe Go has been doing it for quite some time. (The
        | specific one I'm aware of is bytes.Index.)
        | 
        | This was especially important back before the days of
        | v1/v2/v3/etc of x86_64, since Linux distros distributed
        | binaries compiled for the lowest common denominator. So
        | the only way you got fast SIMD instructions (beyond SSE2)
        | was with a CPUID check and some compiler features that
        | let you build target specific functions. (And I'm not
        | sure what the status is of Linux distros shipping
        | v1/v2/v3/etc binaries.)
 
| bbkane wrote:
| I love the new stdlib additions- I've been pulling in these
| dependencies since generics arrived and it'll be nice to have
| them built-in.
 
| cube2222 wrote:
| I'm a bit surprised that the slog package was added to the
| stdlib, but it does seem to use the API that I think is the most
| ergonomic across libraries I saw in Go (specifically, varargs for
| key values, and the ability to create subloggers using .With), so
| I guess it's nice most of the community will standardize around
| it.
| 
| If all goes well, you won't have different libraries using
| different loggers anymore, in some not too distant future, which
| should improve easy composability.
 
  | resonantjacket5 wrote:
  | I think it's pretty exciting. Don't have to keep using regex or
  | weird parsing to get the key values from logs that one wants.
  | 
  | Also a bit surprised how fast it was added to the stdlib, but
  | perhaps there was a lot more consensus on the api compared to
  | other golang proposals.
 
  | chrsig wrote:
  | I have mixed feelings about it. if nothing else, the
  | name..."slog" isn't exactly the word i want repeating to myself
  | as I'm working.
 
    | tomjakubowski wrote:
    | A little honesty is a good thing
 
  | vl wrote:
  | I wonder if it's possible to use slog in 1.20 already, is there
  | a back-port?
  | 
  | I'm changing logging on the service right now and it just makes
  | sense to use it _now_ , but entire service can't move to pre-
  | release version of go.
 
    | onionisafruit wrote:
    | Indeed it's in "golang.org/x/exp/slog"
 
      | mdaniel wrote:
      | https://pkg.go.dev/golang.org/x/exp/slog#hdr-Levels seems
      | to fall into the same trap that drives me _starkraving_
      | about the 18,000 different(!) golang logging packages:
      | there doesn't seem to be a sane way of influencing the log
      | level at runtime if the author doesn't have the
      | foresight/compassion to add a command-line flag or env-var
      | to influence it. A similar complaint about the "haha I log
      | json except this other dep that I import who logs using
      | uber/zap so pffft if you try to parse stdout as json"
 
  | fourseventy wrote:
  | I literally just updated all of my golang logging to use
  | zerolog so i could get severity levels in my logs. Bad timing
  | on my part! I guess ill re-do it all with slog, i prefer stdlib
  | packages to third party packages.
 
    | d1str0 wrote:
    | Tomorrow we will see a blog post titled "Why I always use 3rd
    | part dependencies instead of stdlibs"
 
    | philosopher1234 wrote:
    | ideally an slog handler is built for zerolog, so that you can
    | use slog BE and keep the zerolog FE
 
| H1Supreme wrote:
| The new built in functions for slice manipulation are a welcome
| addition!
 
| galkk wrote:
| So copy-pasting min/max into every program isn't that a good of
| an idea?
| 
| I didn't like the way how opinionatedly those things were
| presented in past and how silently/half baked (bolted in into
| language) they are creeping their way in. Feels like somebody in
| go team just had some spare cycles and decided to push that
| thing.
| 
| Yes, it's a bit funny to have another argument against people
| whose position earlier was "yes, you can copy-paste max, not a
| big deal, go is small language", but at the same time, it
| should've been done much earlier. This is basic programming
| language ergonomics, that go (still) lacks with many other
| features.
 
| openasocket wrote:
| Glad to see the crypto performance improvements, I noticed a
| major regression in the performance of some auth code with 1.20
 
| throwaway5959 wrote:
| Why is map copy "dst, src" vs "src, dst"?
 
  | klodolph wrote:
  | Copy operations in Go are normally destination first, source
  | second. This includes builtins like copy() and library
  | functions like io.Copy(). Making it "src, dest" would make this
  | one case the opposite of all the others.
  | 
  | Note that the order mimics variable assignment. You copy an
  | integer with:                   var src, dest int         dest
  | = src // dest first, src second
  | 
  | I appreciate the consistency.
 
    | Xeoncross wrote:
    | Thanks, "mimics variable assignment" is a good way to
    | remember it
 
    | thisarticle wrote:
    | Ah gotcha, thanks!
 
  | kinghajj wrote:
  | It's not that uncommon.
  | 
  | https://en.cppreference.com/w/cpp/string/byte/memcpy
  | 
  | https://en.cppreference.com/w/cpp/string/byte/strncpy
  | 
  | https://en.wikipedia.org/wiki/X86_assembly_language#Syntax
 
| synergy20 wrote:
| really hope Go has something like MERN for node.js or Django for
| Python, so I can use it for ready-to-go backend framework. There
| are gin and echo etc, just not as widely adopted as MERN or
| Django.
| 
| in some of my use cases, I need make sure source code is fully
| protected, neither Node nor Django can do that well, Go will be
| perfect as it is compiled, however there is nothing like MERN or
| Django in Go(yet). Another option will be Java, but I do not know
| Java.
 
| pizzafeelsright wrote:
| Was there a push to get it released today?
 
  | racingmars wrote:
  | No, release candidate 2 was released today; Go 1.21 is not yet
  | released.
 
| Hakkin wrote:
| Huh, I'm glad to see generic Min/Max functions, but the fact that
| they're built-ins is a little odd to me. I would have expected
| them to put a generic math library into the stdlib instead. The
| fact the stdlib math package only works with float64s has always
| struck me as a poorly thought out decision.
 
  | tinco wrote:
  | What sort of use case do you see for non-float64 math
  | operations in a Go application?
 
    | tedunangst wrote:
    | Float32 is pretty popular in graphics.
 
  | klodolph wrote:
  | Making them builtins allows them to work as you'd expect with
  | cases like,                   func clamp(x float64) float64 {
  | return max(0, min(1, x))         }
  | 
  | With ordinary functions, the arguments are assigned types too
  | soon, and you get integer types for 0 and 1 in the above code.
  | In C++ you might make the types explicit:
  | template         T clamp(T x) {             return
  | std::max(0, std::min(1, x));         }
  | 
  | That's not meant to be exactly the way you'd write these
  | functions, but just a little bit of sample code to show how the
  | typing is different.
 
    | Hakkin wrote:
    | That doesn't seem to be true, unless I'm misunderstanding
    | something. https://go.dev/play/p/ymM0tD3aGYg?v=gotip
    | 
    | Obviously these sample functions don't take into account all
    | the intricacies of float min/max functions.
 
  | tjalfi wrote:
  | The proposal[0] gives a rationale. Using builtin functions lets
  | them be variadic without allocating a slice.
  | 
  | [0] https://github.com/golang/go/issues/59488
 
| 29_29 wrote:
| This is a big release. Lots of new packages. The language is
| changing
 
  | benhoyt wrote:
  | It is a big release, and the number of new stdlib packages (4)
  | is relatively high for a Go release. That said, apart from the
  | addition of some minor builtins (min, max, clear), the
  | _language_ isn 't changing. That happened back in 1.18 with the
  | introduction of generics.
 
| Karupan wrote:
| _Release candidate_
 
| philosopher1234 wrote:
| Seems like a really substantial release to me. The new built in
| functions min, max, and clear are a bit surprising, even having
| followed the discussions around them. The perf improvements seem
| pretty great, I'm sure those will get much love here.
| 
| Personally, I'm most excited about log/slog and the experimental
| fix to loop variable shadowing. I've never worked in a language
| with a sane logging ecosystem, so I think slog will be a bit
| personally revolutionary. And the loop fix will allow me to
| delete a whole region of my brain. Pretty nice.
 
  | saghm wrote:
  | Am I reading it correctly that `clear` does different things
  | for maps and slices? Why doesn't it remove all the items from
  | the slice like it does with the map, or set the values in the
  | map to the zero value like it does for slices? That seems like
  | an easy thing to get tripped up on
 
    | arp242 wrote:
    | You can't "remove all items from the slice"; you can only
    | change the length to 0: "slice[:0]".
 
  | anyoneamous wrote:
  | As a non-developer who has only gone as far as "hello world" in
  | Go, I'm baffled by the idea that the log/slog thing is new -
  | that seems like an absolutely basic language feature. TBH I'd
  | say the same about min/max, but could forgive those being
  | absent since Go isn't known for being numerically-focused...
 
    | tick_tock_tick wrote:
    | > that seems like an absolutely basic language feature
    | 
    | Most languages have no logging "system" built in at all.
    | Honestly it's really quite rare.
 
    | ilyt wrote:
    | > As a non-developer who has only gone as far as "hello
    | world" in Go, I'm baffled by the idea that the log/slog thing
    | is new - that seems like an absolutely basic language
    | feature.
    | 
    | Then you'd be even more surprised when you learn that the
    | vast majority of languages _do not_ have standard logging
    | library in core.
    | 
    | Most have one or few common libraries that community
    | developed instead, but they are not in stdlib, and if stdlib
    | has one it's usually very simple one (Go had standard logger
    | interface that was _too_ simple for example)
 
      | anyoneamous wrote:
      | I have evidently been spoiled by Python and it's abundance
      | of batteries.
 
    | arp242 wrote:
    | There's been a "log" package since forever, but slog adds
    | structured logging with fields and some other things. I don't
    | think many standard libraries have that built in?
 
    | sa46 wrote:
    | Most languages include unstructured logging libraries in the
    | standard library, including Go. Structured logging is usually
    | provided by third party libraries.
 
      | metaltyphoon wrote:
      | The only other one I know would be C# with
      | Microsoft.Extensions.Logging. Its so ubiquitous that 3rd
      | party libraries work with its abstractions. Slog is a
      | really good thing for Go
 
  | ilyt wrote:
  | > The new built in functions min, max, and clear are a bit
  | surprising, even having followed the discussions around them.
  | 
  | Was that discussion pre-generics?
  | 
  | Most of functions and libraries introduced in Go 1.21 is stuff
  | people already put in community libraries (lodash being
  | probably most popular, despise utterly nonsensical name not
  | relating to anything it does) so it is just potentially cutting
  | extra dependencies for many projects.
 
    | tomjakubowski wrote:
    | You mean samber/lo? What is nonsensical about the name?
 
    | philosopher1234 wrote:
    | No, it was a recent discussion, here:
    | https://github.com/golang/go/issues/59488
 
| nasretdinov wrote:
| I am honestly surprised nobody mentioned the intention of Go team
| to make multipath TCP the default in later releases
 
  | kkirsche wrote:
  | Can you elaborate on why this is surprising for those who don't
  | fully understand the differences?
 
    | nasretdinov wrote:
    | I don't think Multipath TCP has been tested in enough
    | environments to become the default yet. It's compatible with
    | TCP, yes, but it's mostly useful for e.g. mobile devices that
    | have multiple links like Wi-Fi and 4G, and it lets users to
    | maintain TCP connection to a certain service even when moving
    | across networks. Go seems to be server-oriented first, and
    | there are some potential downsides to multipath TCP in a
    | datacenter environment (e.g. potentially higher CPU usage,
    | etc).
 
      | arp242 wrote:
      | "In a future Go release we may enable Multipath TCP by
      | default on systems that support it."
      | 
      | This could be five years from now. Or maybe never.
 
| ubavic wrote:
| I enjoy Go so much. It is almost perfect language for getting
| things done, but I still can't understand some design choices.
| 
| Does someone knows why Go uses env variables (like GOOS and
| GOARCH) instead command line arguments?
 
  | superb_dev wrote:
  | It could make it easier for build systems to be multi platform.
  | You don't have to keep track of custom args and add them to
  | every call, you can just set the environment once.
 
  | abalaji wrote:
  | I assume so that it can be sticky across invocations and is
  | easy enough to debug using `go env`
 
  | francislavoie wrote:
  | Env vars make it easier to automate in CI. The actual script to
  | build for each os/arch is the same but only the vars change.
  | It's convenient. You can always prefix the command with the env
  | vars on the same line if you want a one-liner.
 
  | Cthulhu_ wrote:
  | I guess so you can configure them on e.g. a build server
  | instead of tweak your build command, but then, neither is
  | particularly portable.
 
| earthboundkid wrote:
| An extremely generic release.
 
  | evacchi wrote:
  | GOOS=wasip1 is pretty cool IMO (disclaimer: I work on
  | wazero.io)
 
  | kernal wrote:
  | hiyo
 
  | [deleted]
 
  | candiddevmike wrote:
  | > New slices package for common operations on slices of any
  | element type. This includes sorting functions that are
  | generally faster and more ergonomic than the sort package.
  | 
  | > New maps package for common operations on maps of any key or
  | element type.
  | 
  | > New cmp package with new utilities for comparing ordered
  | values.
  | 
  | Pun intended? =D
 
| WhereIsTheTruth wrote:
| > New built-in functions: min, max and clear.
| 
| What a mistake.. reserved keywords are words I can no longer use
| for myself...
| 
| Zig does it better by requiring a prefix @ for most their builtin
| needs
 
  | throwawaygo wrote:
  | _breaks all my variables named min and max_
 
  | philosopher1234 wrote:
  | They're not reserved keywords. Existing/package defined min/max
  | functions would take precedence. They have the same semantics
  | as `append`
 
    | WhereIsTheTruth wrote:
    | You refactored your code, you think you wrote your ``min``
    | function, but no, it'll call the builtin one, without warning
    | you..
    | 
    | I don't like this design..
 
      | bananapub wrote:
      | if you have so few tests and so little code review that
      | this matters then I am not sure what to suggest
 
      | vito wrote:
      | The compiler will tell you if the types aren't compatible,
      | and this is only for primitive comparable types. What
      | `min()` implementation could you have that even does
      | something different?
 
        | KRAKRISMOTT wrote:
        | A heap?
 
      | Chiron1991 wrote:
      | Not too familiar with go toolchains, but I bet there's a
      | linter that will warn you about shadowing builtins.
 
      | dgfitz wrote:
      | Qt uses qMin and qMax, it may have been nice if go went
      | with like gMin and gMax
 
  | pjmlp wrote:
  | For anyone that misses their Objective-C days.
 
  | Dudester230602 wrote:
  | They did not expect a simple language created for faster
  | onboarding of graduates to catch on. Now that community is
  | pushing for features the language might evolve in strange
  | ways...
 
  | BarkMore wrote:
  | min and max are predeclared identifiers in the universe block,
  | not reserved words.
  | https://go.dev/ref/spec#Predeclared_identifiers
  | 
  | You can continue to declare your own entities with these names.
 
| panzi wrote:
| Wait is this now heap allocating a value in every iteration of
| every loop? I hope that allocation is optimized out in every case
| where there isn't a closure over the loop variable?
 
  | doctor_eval wrote:
  | Regardless of how the compiler is optimising this, I 100% agree
  | that the old behaviour is unexpected and it's caught me at
  | least once. Really happy to see this (until recently)
  | unexpected change.
 
    | panzi wrote:
    | I don't actually use Go, but I have used many other languages
    | where it is like the old behavior. I learned once that I have
    | to build the closure correctly to get the value I want and
    | know now to do it. Don't have any statistics on whether I
    | made that mistake again, but anecdotally I can't remember a
    | case where I have. In their analysis they have found a lot of
    | cases with that mistake, though. So I guess fair enough.
    | 
    | However, I wonder what it will mean if someone who mostly
    | writes Go will now use another language? Will they be more
    | prone to make that mistake?
 
  | collinvandyck76 wrote:
  | I didn't see this optimization when I read the overview. I also
  | hope that the compiler is smart enough to avoid this.
 
  | vbezhenar wrote:
  | Of course it'll be optimized. It's just semantics that's
  | changed. Compiler will make sure to copy variable value to new
  | address.
 
  | quacker wrote:
  | They discuss this here:
  | https://github.com/golang/go/wiki/LoopvarExperiment#will-the...
  | 
  | In fact, you can enable warnings/logs that indicate whether
  | code that is affected by the loopvar experiment results in a
  | stack-allocated or heap-allocated loop variable:
  | https://github.com/golang/go/wiki/LoopvarExperiment#can-i-se...
  | 
  | I imagine that the current workarounds for this issue also end
  | up with heap-allocated variables in many cases.
 
  | xh-dude wrote:
  | Generally it is optimized out.
  | 
  | The fine details resemble the analysis of correctness - all the
  | evidence shows people expect per-iteration semantics with
  | considerable frequency, and don't rely on per-loop semantics
  | with measurable frequency. But it's impossible to completely
  | automate that assessment. Likewise, it's impossible to
  | automatically detect code that will spuriously allocate because
  | of the semantic transition.
 
| throwawaygo wrote:
| So I guess with new builtin functions we will be breaking
| backwards compatibility?
 
  | racingmars wrote:
  | If you already have your own functions or variables named max,
  | min, or clear in-scope, they will shadow the new built-in
  | functions and your code will continue to use your own version
  | of the functions. No breakage to existing identifiers that
  | match the new function names.
  | 
  | (This is the same behavior as the append built-in function
  | today, for example. These things in Go are _not_ reserved
  | keywords, they are simply global functions that can be
  | overridden at other scopes.)
 
    | metaltyphoon wrote:
    | Lets be honest, its a terrible choice
 
      | racingmars wrote:
      | In what way? Overall as a language, identifier shadowing is
      | a feature of the language in nested scopes. Are you saying
      | built-in identifiers (that aren't language keywords) should
      | be treated specially and work differently than user-
      | declared identifiers?
 
| w10-1 wrote:
| Overall, a release more for engineering than language. Even the
| new API's are mainly optimizations, and optimizations are netting
| ~10% (pretty good for an mature toolset).
| 
| The WASI preview shows Google is committing engineering resources
| to WASM, which could grow the community a touch.
 
| Cybergenik wrote:
| Wrote a blog explicitly asking for some of these changes last
| year: https://www.lremes.com/posts/golang/
| 
| Nice to see their going in a good direction.
 
| colesantiago wrote:
| Hmm.
| 
| Not really an interesting Go release here unless I am missing
| something.
| 
| Has Go peaked already?
 
  | Cthulhu_ wrote:
  | What big thing are you expecting? Go is more of a stable
  | language, a reliable and boring language for building software
  | now that in ten years you can still maintain. Go isn't peaking,
  | Go isn't an exciting or cool or hype language, it's just...
  | there. And that's just fine.
  | 
  | Too many languages just started borrowing features from others,
  | saying "yes" to every suggestion, until they got out of control
  | and all over the place. Go says "no" more often than not. Which
  | isn't always a good thing, mind; generics took a long time
  | because they wanted to understand the problem and not add more
  | like what happened to Java. The builtin min/max features up
  | until this release only supported float64. Lots of small
  | annoyances like that.
 
    | jjice wrote:
    | > ...generics took a long time because they wanted to
    | understand the problem and not add more like what happened to
    | Java
    | 
    | Just out of curiosity, can anyone regale me with that history
    | with Java's generics?
 
      | jrockway wrote:
      | "type erasure" is the search term you're looking for.
 
| nu11ptr wrote:
| It is interesting to see them add things like the "clear"
| function for maps and slices after suggesting to simply loop and
| delete each key one at a time for so long. Is this a result of
| the generics work that makes implementation easier vs. the extra
| work of making a new "magic" function (like "make", etc.)?
 
  | skybrian wrote:
  | From the spec [1], it was because the loop doesn't work to
  | clear a map with a NaN key.
  | 
  | [1] https://github.com/golang/go/issues/56351
 
  | Waterluvian wrote:
  | It might also be that they've worked their way down the
  | priority list and are getting to these features that are
  | largely just to tidy up code.
 
    | stefan_ wrote:
    | Clearing a container is usually a much simpler and faster
    | operation than looping through all and removing them
    | individually. That's not a question of tidying something up.
 
      | onionisafruit wrote:
      | There were compiler optimizations for clearing by
      | iterating. I haven't looked at the code, but I suspect this
      | won't be much more efficient than iterating was with the
      | optimizations.
 
  | alex_lav wrote:
  | > It is interesting to see them add things like the "clear"
  | function for maps and slices after suggesting to simply loop
  | and delete each key one at a time for so long.
  | 
  | Slowly walking back dogmatic positions is just how the Go team
  | works.
  | 
  | I say this as a person that wrote Go full time for a handful of
  | years.
 
  | maximilianburke wrote:
  | That `clear` on a slice sets all values to their type's zero
  | value is going to be extremely confusing especially coming from
  | other languages (Rust, C#, C++, Java, ...) where the same-named
  | function is used on list-ish types to set their length to zero.
  | 
  | Doubly-so when `clear` on a map actually seems to follow the
  | convention of removing all contained elements.
 
    | neonsunset wrote:
    | C#'s array/span.Clear() does exactly the same - it zeroes
    | them out.
 
    | klodolph wrote:
    | Sure, although as a Go user, the behavior described is
    | exactly what I'd expect. These new functions are no different
    | from functions that you could write yourself.
 
      | Jabbles wrote:
      | The builtin clear() will handle cases like deleting NaN
      | from a map.
 
      | maccard wrote:
      | I'm a go user, and think it's dumb that:
      | clear(f)         fmt.Println(len(f))
      | 
      | will have different results if f is a slice and a map.
 
    | 6D794163636F756 wrote:
    | It sounds like they're inheriting the naming from the calloc
    | command. Allocates then 0's the memory. It lines up with the
    | go devs' backgrounds
 
  | philosopher1234 wrote:
  | One aspect of this is that it was formerly impossible to delete
  | NaNs from a map[float64]T, unless you had the nan already.
 
| djsavvy wrote:
| The new experimental fix for loop variable capture [0] is huge;
| this is the biggest footgun with the language in my experience.
| 
| I hope the experimental fix makes it into the next version of Go
| by default.
| 
| [0] https://github.com/golang/go/wiki/LoopvarExperiment
 
| showdeddd wrote:
| I wonder if the new stdlib logger is featured enough to get rid
| of logrus/zerolog.
 
  | JyB wrote:
  | I'm wondering the same. Anyone already played for some time
  | with the pkg?
 
    | richieartoul wrote:
    | I've been using it for a few weeks now. Overall pretty happy
    | with it. Has good default API, and can be basically
    | arbitrarily extended as needed. We even have a custom handler
    | implementation that allows us to assert on specific logs
    | being emitted in our stress/fuzz testing.
 
___________________________________________________________________
(page generated 2023-06-21 23:01 UTC)