20 ms·
Go 1.21 Released
- mdaniel 3y agoseems the submissions for "Go $v Released" have been 50/50 pointing to the doc url versus the blog url: https://go.dev/blog/go1.21 https://go.dev/blog/go1.21
- hwc 3y agoI'm looking forward to the log/slog package. I might start switching over from our homegrown solution next week.
- thiht 3y agoWe’re currently using zerolog, I’ll also give a try to slog when I have an hour to kill. One less third party dependency is always good to take!
- dgunay 3y agoBe aware that there is a performance impact compared to using zerolog directly [0] (my uneducated guess is it is likely due to pointer indirection). [0]: https://github.com/rs/zerolog/issues/571#issuecomment-1662025492 https://github.com/rs/zerolog/issues/571#issuecomment-166202...
- j16sdiz 3y agoThe “Loopvar” experiment looks like backward compatibility nightmare. As confusing as the existing behaviour could be, the new experiment is asking for trouble.
- jjnoakes 3y ago> no programs will change behavior due to simply adopting the new Go toolchain Seems like they thought about that. I think it's a good change.
- philosopher1234 3y agoIt’s a breaking change, but rsc did very thorough testing of publicly available code and internal Google code and found essentially only bug fixes. But I think the risk is why this is an experiment and not a straight up change. Also, the new behavior would only be enabled on modules that are marked as Go 1.22 or above, not program globally, iiuc. So to me, this is very thoughtfully planned and unlikely to be any kind of nightmare
- deleted 3y ago[deleted]
- icholy 3y agoC# did the same thing in 5.0 https://ericlippert.com/2009/11/16/closing-over-the-loop-variable-considered-harmful-part-two/ https://ericlippert.com/2009/11/16/closing-over-the-loop-var...
- plorkyeran 3y agoWhen C# shipped this change I was working on a large C# codebase and we were very worried about this. After auditing the entire codebase and checking every for loop, we found two pre-existing bugs in code which expected the 5.0 behavior and zero places which relied on the old behavior. Everyone that I've ever talked to who went through the transition has a similar story. In practice no one even incidentally relied on the old behavior. Go rolling it out as an experimental opt-in feature is a good idea, but it'll probably turn out to be unnecessarily cautious and they could have gotten away with just unconditionally enabling it.
- tapirl 3y agoC# only did this on `foreach` loops, not on traditional `for` loops. Go plans to do this on both (`for-range` loops and traditional `for` loops).
- masklinn 3y agoIs it? The experiment is just that, a way to test your packages for breakage, the proposition to opt in via langfile is similar to Rust edition systems which work fine. Way back when C# actually went through that change unconditionally (LangVersion was not a thing yet), and there was barely any breakage.
- latchkey 3y agoForgetting to add `foo := foo` in a for loop tends to be bigger trouble. =)
- tsimionescu 3y agoThe existing behavior is extremely unlikely to be helpful, even accidentally. I will be shocked if anyone actually hits a problem related to this change. It may well fix more bugs than it introduces.
- tapirl 3y agoFor `for-range` loops, it looks the benefits of this change are more than the drawbacks. For `for ...; ...; ...` loops, personally, I think the conclusion is the inverse. One breaking case: func main() { defer println() for counter, i := 0, 0; i < 3; i++ { defer func() { counter++ print(counter) }() } } It will print 111 when the change is made. More surprising cases: https://github.com/golang/go/issues/60078#issuecomment-1544324607 https://github.com/golang/go/issues/60078#issuecomment-15443...
- tedunangst 3y agoWhy don't any of the examples of surprise breakage link to real code relying this behavior?
- tapirl 3y agowhy do you ask such a confusing question?
- masklinn 3y agoThe question seems completely straightforward.
- tapirl 3y agoIt is confusing that why such a question was asked. It shows the asker lacks of basic logical ability.
- yencabulator 3y agoThe experiment changes behavior, nobody's contesting that. Does it change behavior in any scenario that matters?
- tapirl 3y agoAs far as I know, no one has proved that it doesn't change behavior in any scenario that matters, including the proposal makers. Have you proved it?
- kristianp 3y agoFor those wondering: https://github.com/golang/go/wiki/LoopvarExperiment https://github.com/golang/go/wiki/LoopvarExperiment
- candiddevmike 3y agoStuff keeps moving out of the standard lib related to crypto. First was PGP, now elliptic. Why doesn't Go want to provide stdlib crypto stuff?
- kyrra 3y agoTwo reasons I can think of: 1) speed to update it in the case of a bug / security issue. 2) backwards compatibility. Getting a new Go release out is likely a lot more time consuming than bumping up the crypto library outside of there. And those libraries do not require full backwards compatibility compared to the Go standard library. So they can do breaking changes if need back without breaking the Go contract.
- chrsig 3y agomy bet is it has something to do with Filippo Valsorda having left google, but that's pure speculation on my part. https://github.com/FiloSottile https://github.com/FiloSottile
- FiloSottile 3y agoNope :) I'm still a maintainer, and actually happen to be the one that drove those two deprecations. https://words.filippo.io/full-time-maintainer/ https://words.filippo.io/full-time-maintainer/
- chrsig 3y ago
- h1fra 3y agoadding min/max to a language made 10 years ago is kinda crazy when you think about it. Really looking log/slog package, it seems neat and was deeply needed.
- jakear 3y agoHah, I just went down a whole rabbit hole on super-logarithms and tetration wondering why you found it so critical as to warrant standard-library inclusion.
- thiht 3y agoNote that min/max were already available in the math package, but they’re a bit inconvenient to use (lots of casting to do)
- dchest 3y agoWhile it's true that it had math.Min/Max, it's not just the inconvenience of castings that this solves. You can't cast uint64 to float64 and expect the function to return the correct result, e.g.: x1 := uint64(9007199254740993) x2 := uint64(9007199254740992) fmt.Println(uint64(math.Max(float64(x1), float64(x2)))) will print 9007199254740992. min/max and math.Min/Max are not equivalent. The correct way to write min/max before was to use comparison operators. math.Min/Max was there because it requires tricky special cases for handling -Inf, Inf, NaN, and negative zero.
- KolmogorovComp 3y ago> When printing very deep stacks, the runtime now prints the first 50 (innermost) frames followed by the bottom 50 (outermost) frames, rather than just printing the first 100 frames. This makes it easier to see how deeply recursive stacks started, and is especially valuable for debugging stack overflows. This is a very nice QoL improvement, I wish more languages made the change.
- michaeljx 3y ago100+ frames deep? I am a python dev, is that normal in Go? Sounds atrocious
- eyelidlessness 3y ago“This makes it easier to see how deeply recursive stacks started, and is especially valuable for debugging stack overflows.” Mistakes are normal in any language. Debugging an infinitely deep recursion can be challenging in most.
- cryptos 3y agoYou will never hear something again from developers trying to hunt down errors in infinite recursion ;-)
- masklinn 3y agoPython will also do something like that, specifically it snips out repeated lines in self-recursive calls: https://github.com/python/cpython/issues/71010 https://github.com/python/cpython/issues/71010 >>> a() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in a File "<stdin>", line 3, in a File "<stdin>", line 3, in a [Previous line repeated 894 more times] File "<stdin>", line 2, in a File "<stdin>", line 2, in b File "<stdin>", line 2, in c File "<stdin>", line 2, in c File "<stdin>", line 2, in c [Previous line repeated 97 more times] RecursionError: maximum recursion depth exceeded Sadly it's not smart enough to handle indirect recursion, so in those cases you get a thousand lines of garbage.
- predictabl3 3y agoHelloooooo riscv64-linux support! EDIT: lol this fickle site. Not my fault they didn't publicize the fact that they're now publishing riscv64 binary releases (allowing distros to bootstrap riscv64 targets now).
- mholt 3y agoNot sure why you're getting downvoted. We got a pull request to add this to our Caddy build process today: https://github.com/caddyserver/caddy/pull/5720 https://github.com/caddyserver/caddy/pull/5720
- rickette 3y agoThe backwards compatibility promise (as always) is really nice. Java/JVM is the only other language/platform that I can think of that does more or less the same. Using both extensively by the way.
- mseepgood 3y agoYes, I like to build my castles on solid ground rather than on quicksand.
- greggyb 3y agoCommon Lisp has been standardized for longer than Java's life. Also in the lisp world, Clojure has a fastidious dedication to backward compatibility. Perl 5 has maintained backward compatibility (though I am not certain if it is 100% compatible) by putting changes behind flags.
- germandiago 3y agoC++ takes compatibility very serious. Though it has ABI stuff here and there you need to deal with due to its fully native AOT compilation nature.
- deepsun 3y agoJust curious, isn't Go compilation fully native? Java I know, it's technically interpreted (transpilation not compilation), but Go?
- pjmlp 3y agoKind of, there are plenty of breaking changes as well, three that quickly come to mind, removal of exception specifications, std::auto_ptr<>() removal, and the new semantic changes due to the way <=> behaves.
- germandiago 3y agoFor the former two, breakages have replacements and are a vestige noone used for a long time. Besides that, compilers have switches to treat throw() as noexcept. As for the latter, those breakages are relatively rare.
- ydnaclementine 3y agoI'm a recent convert and enjoying it quite a bit for webdev. There's lots of books out there, but I found let's go and let's go further to be great project based books
- adrianmsmith 3y agoRe: https://github.com/golang/go/wiki/LoopvarExperiment https://github.com/golang/go/wiki/LoopvarExperiment I've mainly used Java which doesn't suffer from this particular problem. But I've often heard Java criticized on the grounds it captures values not variables, and that most other languages apparently capture variables. I remember learning Lisp at uni and being taught that it captured variables, for example. So do other languages suffer from this problem as well? How do they deal with it?
- kazinator 3y agoIn some cases, Common Lisp makes it implementation-defined. E.g. in (dolist (item list) ...) it is implementation-defined whether x is a freshly bound lexical, or a stepped variable. In Lisp, you can easily write macros that have whatever semantics you want. You can easily write a my-dolist which is like dolist but freshly binds the item variable for every iteration, and next to it write a my-dolist2 which assigns a single variable. In languages like Go, the providers of your language provide all the syntax from behind a wall, and make these decisions for you. Knights in shining armor duke it out on the rooftop of an ivory tower, while lower vassals blog incessantly about the important work being done and decisions being made. By the way, MacCarthy's ancient Lisp (Lisp 1, Lisp 1.5) didn't have lexical scope, so it would not have made any difference whether each iteration stepped the variable with setq or bound it with let. There would just be the one dynamic variable in all cases, not captured by any lexical closures (those being nonexistent). You'd want to bind it at least once with let so the prior value is restored when the loop is done. In Common Lisp, if we use a special variable as the loop variable, it likewise won't make a difference whether it is stepped or bound each time, since the binding isn't lexical.
- germandiago 3y agoMacros is exactly what makes Lisp a one-man only language for every person unless you are really careful. That, combined with the fact that things are often poorly documented is what IMHO ruins the language ecosystem. I want to like Lisp and I love its interactivity but I find the language a bit more "construction material" language than a ready-to-use immediately language. What is bad about that is exactly what you mention: everyone will come up with a set of macros that others cannot fully grasp.
- simonz05 3y agoFelix Geisendörfer did a bunch of work to improve continuous profiling performance [1]. [1]: https://blog.felixge.de/waiting-for-go1-21-execution-tracing-with-less-than-one-percent-overhead/ https://blog.felixge.de/waiting-for-go1-21-execution-tracing...
- aktau 3y agoIndeed, this is awesome work.
- badrequest 3y agoI am really excited to start using the new structured logger.
- iamcalledrob 3y agoYes! Logging always felt like something that (1) almost every project needs, and (2) there are too many 3rd party packages, with no "de facto" choice. This is particularly painful when working with 3rd party library code. There's a high chance that the consumer of library code uses a different logging package to the library author. Having structured logging in the stdlib is fantastic, because now there is a "go way" to this that libraries can use.
- eberkund 3y agoDoes this mean that all the third party logging packages will likely die out in the future? Or will they likely implement adapters to be compatible with the std interface?
- cratermoon 3y agoFrom the original proposal <https://go.googlesource.com/proposal/+/master/design/56345-structured-logging.md https://go.googlesource.com/proposal/+/master/design/56345-s...> 1 "We expect existing logging packages to coexist with this one for the foreseeable future." 2 "We expect that this proposal’s handlers will be implemented for all popular logging formats and network protocols, and that every common logging framework will provide a shim from their own backend to a handler"
- kiitos 3y agoEven after seeing the API, which is enormous and wildly non-intuitive?
- cube2222 3y agoCould you expand what you mean? When skimming it I mostly saw the common API structure that I usually see in libraries / write myself when I need a logger, so I generally welcome the standardization.
- lenkite 3y agoNo basic Map or Filter functions in the new slices pkg. Sadness.
- empath-nirvana 3y agoI think it's a reasonable first pass at implementing generic functions. I'd love to see Map/Filter/Reduce, but starting with the simplest set of generic functions and getting people comfortable with them is probably a good idea. Go idiomatically is very imperative and introducing a new programming style at the same time as introducing generics might be too much change at once. I'd also like to see an option and a result type at some point so we can stop doing nil checks all over the place.
- masklinn 3y agoMakes sense given the idea of getting some form of iterators support into the language, collection-specific HoFs means more duplication and worse composition as the intermediate collections generally need to be allocated on every step, and often can't be optimised away because you're stuck with your defined order of evaluation.
- morelisp 3y agoIf we're lucky they won't add them until they have some halfway decent fusion working in the compiler.
- 38 3y ago> Filter https://pkg.go.dev/slices#DeleteFunc https://pkg.go.dev/slices#DeleteFunc
- valzam 3y agoSo happy they called it delete. I can never remember if filter keeps or removes the values that evaluate to true when I use other languages.
- telotortium 3y ago> Go 1.21 now defines that if a goroutine is panicking and recover was called directly by a deferred function, the return value of recover is guaranteed not to be nil. To ensure this, calling panic with a nil interface value (or an untyped nil) causes a run-time panic of type *runtime.PanicNilError. > To support programs written for older versions of Go, nil panics can be re-enabled by setting GODEBUG=panicnil=1. This setting is enabled automatically when compiling a program whose main package is in a module with that declares go 1.20 or earlier. An explanation of why this change was implemented is contained in the description of the implementing change, https://go-review.googlesource.com/c/go/+/461956 https://go-review.googlesource.com/c/go/+/461956. In short, calling `panic(nil)` before would make `recover` return nil, which is what's returned when there is no panic. `recover` doesn't have a `panicArg, ok = recover()` return value variant, so they fixed it this way.
- 015a 3y agoThe log/slog package is huge. I'm super happy to see them start-again to express opinions and solve more problem with just the standard library; and I hope to see more of it. This was Go's Thing at 1.0; you could build a production ready, large scale HTTP service with nothing but the standard library; and, probably, a structured logging package like Zap. Now; looks like we may not need it! If anyone on the Go team is reading this; thanks! And, as hacker news must always be the armchair commentator, if I may ask for an addition in go 1.22: encoding/yaml. Build it in. Go and YAML are the languages of devops, and I've written so many scripts with JSON as a configuration file only because Go has a JSON parser built-in, but not YAML.
- liggitt 3y ago> if I may ask for an addition in go 1.22: encoding/yaml FYI, encoding/yaml was recently requested, and was declined in https://github.com/golang/go/issues/61023#issuecomment-1610605569 https://github.com/golang/go/issues/61023#issuecomment-16106..., for reasons I largely agree with. (I work for Google but not on Go)
- masklinn 3y ago> I've written so many scripts with JSON as a configuration file only because Go has a JSON parser built-in, but not YAML. Sounds like a feature. Less Yaml in the world is a good thing.
- renewedrebecca 3y agoHow comfy is go for general native performance coding tasks? Basically looking for a C/C++ replacement. (I don't really like how Rust looks syntactically, and prefer GC over manual memory management.)
- lytedev 3y agoI'm not an expert at all, but I wouldn't. I would reach for nim or even zig before go. But it depends on what you're building, I'm sure!
- repeekad 3y agoPersonal experience is great, though for large projects C++ is definitely more robust. Really like how go handles parallelism and creating threads.
- germandiago 3y agoI think Go is a really good fit to write async servers. Its set of features make it a killer language for that use case.
- assbuttbuttass 3y agoI'm curious what are some of the reasons C++ is better for large projects?
- stevemk14ebr 3y agoLook into Nim or Zig instead if you're coming from C++
- germandiago 3y agoI would also recommend to take a look at D.
- deleted 3y ago[deleted]
- 3y ago
- WhereIsTheTruth 3y ago> Go 1.21 improves build speed by up to 6%, largely thanks to building the compiler itself with PGO. Go already compile fast, and it still gets faster release after release, love it!
- pojzon 3y agoIm still looking for a language that will solve my biggest issue: - dependency hell.. Recently had to update unmaintained project by 5 dependency versions higher. It was so painful with GO.
- ParetoOptimal 3y agoI don't use Go a lot anymore, but I sometimes use Nix's buildGoModule: https://nixos.wiki/wiki/Go https://nixos.wiki/wiki/Go Oh wait... You mean because of breaking language changes?
- hu3 3y agoVendoring might help with building old code. It stores a copy of depencies in a directory which you can include in git. https://go.dev/ref/mod#vendoring https://go.dev/ref/mod#vendoring As for upgrading old libraries which might have broken backwards compatibility, I can't offer much.
- bananapub 3y agohow would that help with building old code? is old code often unavailable upstream?
- hu3 3y agoVendoring creates a copy of the dependency files. So no internet connection would be required to build it IF (and that is a big if) the project dependencies were vendored and versioned back then. Interestingly, commiting vendored files is a common point of contention between devs. Some argue that it adds bloat to the project repo. Unless I'm working with TB sized monorepos, I always vendor and commit, because hardware is cheap and my time valuable. I have 10 year old projects that build just fine without internet connection because all deps are commited with the project. As a bonus I get a free diff of every single line that changed when a depency is updated.
- randomdata 3y agoNeeding to change an entire dependency version (let alone four more versions) is a sign of human error. It is unlikely that software will fix a bumbling human. No matter how hard it tries, humans will always find some new way to do something stupid.
- febstar 3y agoSeems to be the smallest Go release yet (at least since 1.4). I wonder how the binary size was reduced in the recent two versions? 1.21 63MB 1.20 95MB 1.19 142MB 1.18 135MB 1.17 129MB 1.16 123MB 1.15 116MB 1.14 118MB 1.13 114MB 1.12 121MB 1.11 121MB 1.10 114MB 1.9 98MB 1.8 86MB 1.7 78MB 1.6 81MB 1.5 74MB (linux-amd64 archives from https://go.dev/dl/ https://go.dev/dl/)
- FiloSottile 3y agoLong term intentional effort: https://go.dev/issue/27151 https://go.dev/issue/27151
- tough 3y agoAll I could find for context about what caused it (which is not reflected in that issue) > Go command The directory $GOROOT/pkg no longer stores pre-compiled package archives for the standard library: go install no longer writes them, the go build no longer checks for them, and the Go distribution no longer ships them. Instead, packages in the standard library are built as needed and cached in the build cache, just like packages outside GOROOT. This change reduces the size of the Go distribution and also avoids C toolchain skew for packages that use cgo. https://tip.golang.org/doc/go1.20 https://tip.golang.org/doc/go1.20
- Someone 3y agoPossibly compiler/linker improvements. For example, FTA: “In Go 1.21 the linker (with help from the compiler) is now capable of deleting dead (unreferenced) global map variables, if the number of entries in the variable initializer is sufficiently large, and if the initializer expressions are side-effect free.” There also may be differences in debug symbols in the various binaries.
- 38 3y agoOther two comments are wrong. The correct answer is that the compiler now builds everything on demand if it's not already built. This now includes the standard library as well. Previously built versions of standard library modules were being shipped.
- rcme 3y agoIs it just me or is the new import initialization algorithm n^2 in the worst case? Surprised by that.
- morelisp 3y agoThat's just the easy specification of the algorithm, it's implemented by a heap and counter on each package so I assume it's more like n lg n.
- rcme 3y agoBut in the worst case, initializing one package causes the count in each of the remaining packages to update. Maybe they have a clever way of doing that. Or maybe this is very unlikely to happen in practice.
- morelisp 3y agoIf you take n as packages (vertices) you can have n² dependencies (edges), each of which needs to be looked at once no matter what. So if you count that way n² is unavoidable in any dependency sorting. (Usually for such algorithms I see n = |v| + |e|, or max(|v|, |e|), or just left as |v| and |e|.)
- levischoen 3y agowow this was a very "we made everything a little better", lot of thanks to the golang devs
- Zamicol 3y ago>crypto/ecdsa PublicKey.Equal and PrivateKey.Equal now execute in constant time. Glad to see this pushed. We went to look how Go was handling constant time comparisons and noticed it was not. This is not considered a serious security issue, as attacker controlled private key attacks are generally considered out of scope, but it's still nice for the library to be safe. (See https://github.com/golang/go/issues/53849 https://github.com/golang/go/issues/53849)
- favflam 3y agoIs anyone experimenting with the WASI feature?
- v7n 3y agoSure. For example serving TCP/HTTP with net.FileListener works, which really opens things up at least for me. https://stackoverflow.com/a/76711399 https://stackoverflow.com/a/76711399