Three Minor Features in Go 1.18
blog.carlmjohnson.net
blog.carlmjohnson.net
There is also a great post(See: https://tailscale.com/blog/netaddr-new-ip-type-for-go/) in Tailscale's blog which deep dives into why we needed a new IP type/library in Go.
Go espouses "Share by communicating, don't communicate by sharing" i.e. don't let goroutines communicate by mutating shared data, but then doesn't provide any effective immutable data structures to make this easy.
Being able to safely send pointers to immutable maps over channels would make go very nice to work with. Although I'll never use Go outside of work until they remove nullable pointers which seems unlikely.
You don't need immutable structures to communicate between goroutines. Value types are fine. Just think a bit about how to use channels as signal carriers, it eventually starts to make sense
V2 - Nehalem/Jaguar
V3 - Haswell/Excavator
V4 - AVX512
Those are be the sort of things that generics will enable.
It makes code harder to read and modify.
A straight for loop is infinitely better in every way.
> A straight for loop is infinitely better in every way.
A straight for, for-of, or for-in loop, as appropriate, is finitely better for imperative operations that don't naturally fit map/filter/reduce but need to be performed over some set of values.
Ah, and a map that performed side effects.
Other than that it's unreadable.
Then again, I learned BASIC first technically, so my brain probably isn't quite right :).
I don't really think it has much to do with you language path but rather with the field you are working most of the time.
People who are building Rails startups for sale will have opinion different from people who build some sort of integration systems.
I rediscovered imperative programming later and found it to be such a breath of fresh air.
DDJ had quite a few articles on how to do Lisp-in-C kind of thing.
So technically their post is correct
You can even plug a conservative GC for the full Lisp like experience.
In Ruby the map/filter/reduce handling is very smooth, readable and useful!
Mainly, IME, because of the combination of JS map, etc., passing extra, infrequently used parameters, and functions you might want to use often accepting optional less-frequently-used parameters, which can end up interacting horribly wrong when you do:
arr.map(func)
instead of: arr.map(v => func(v))
when you want a “simple” map application.https://github.com/golang/go/issues/45955#issuecomment-83235...
split_once() and similar split features in Rust are interesting because Rust doesn't have overloading, yet you can split on a string, or a character. This relies on a Trait, Pattern, that is Nightly, so you can't Implement it yourself in stable Rust today, but eventually this factors out the commonality which is cleverer than overloading (because it applies everywhere automatically)
The point is you can't implement Pattern, because it's a nightly feature. If you just make your own, that isn't Pattern and provides none of the benefits.
Yes, you can implement your own trait, and provide blanket implementations for it, but unlike Pattern yours is not part of the standard.
The nice thing about Pattern is that if Rust added say split_exactly_six_times() to the standard library that would take separator: Pattern too and so things which implement Pattern qualify, I can't see a way to get that benefit for my own traits.
would be neat to imagine a language where this was an optimizer feature rather than a decision the programmer made. many functions that return an array are ultimately using just one, or a few elements of it. the compiler can make a lot of decisions in the caller about how to reduce allocation or short-circuit array processing.
I think, but am not sure, this is what the experimental parsing language 'wuffs' is about https://github.com/google/wuffs -- the language itself is aware of array lengths as a first-class citizen and can make decisions accordingly
I said nothing of using one package per function.
From use, I concluded that the utilities package contained only two things: functionality that was substantial enough to clean up and publish as its own package on GitHub, and minor functionality that was better off being copy/pasted between projects. So I abandoned my utility package and published a few minor packages on GitHub.
No need to exclude that possibility. I once worked on a Go app that rendered React (in Typescript) server-side. The Javascript could call Go API functions directly when rendering server-side and those calls would turn into gRPC-web calls after it was loaded in the client. It worked really well.
Isn't the point of SSR to avoid needing to have the client make additional requests for the first render? If I return something like <div dangerouslySetInnerHTML={fetchWithGrpc(myGoFunc)} /> that's not SSR. Perhaps I'm missing something.
Yes, hence why it was able to call the Go functions directly during SSR, the results of which were bundled with the payload delivered to the client. gRPC played no role during initial render.
If the React app needed more information/updates as the user used the app then the function calls would transparently happen over gRPC instead.
Consider:
const MyReactComponent = () => {
const [things, setThings] = useState()
useEffect(() => {
// In-memory call to Go GetThings function during SSR render; gRPC call
// to Go GetThings function when running in the client.
GetThings().then(setThings)
}, [])
return <div>{things}</div>
}
Architecturally, not a whole lot different to how you might build a SSR React app on Node. The backend was just written in Go instead and that backend had a built-in Javascript runtime to execute the frontend code for SSR purposes.https://github.com/carlmjohnson/versioninfo/
The primary motivation curiousity to learn if this becomes "the [best/default] way" folks reach for when leveraging BuildInfo to implement binary versioning in Golang.
It could be a nice benefit to the entire go ecosystem if there becomes a widely-used, de-facto, and consistent automatic versioning scheme (for the common cases, e.g. minor point release lineage).
Build time injected into builds would absolutely break any reproducibility.
What do you mean? Under what circumstances is a Go build not reproducible? From what I’ve observed, if you build your binary with a set of input, the same binary is produced. Is it sometimes not true?
Compiler version must be identical (not a huge stretch).
cgo reproducibility is not a guarantee.
1. Care to elaborate?
2. What does this even mean?
3. It’s in the pending release notes with all the other new features and further information in the post you’re commenting on. https://tip.golang.org/doc/go1.18
Try to be more constructive if you want a conversation please.
Any chance of a reason?