A new Go API for JSON
Posted by olexsmir 7 hours ago
Comments
Comment by asim 6 hours ago
So yea hopefully a nice new addition but only my prompts now matter. So need to make sure they pickup on the new API.
Comment by dofm 6 hours ago
I am using local LLMs and Go has a bunch of strengths where smaller contexts are concerned; less complicated flow of control being one of them.
Comment by calvinmorrison 5 hours ago
Comment by dofm 5 hours ago
And the things that we do to manage this, that are symbolic or based on visceral real-world analogy, are good for us and bad for them.
Go is kind of in the middle, in the way that many vaguely Wirth-like and CSP-like languages possibly are, I guess.
Comment by hoppp 1 hour ago
Comment by egnehots 4 hours ago
If you code in Go, the code is more high level, prettier, simpler.
If you code in Rust, the code is more robust, efficient, faster.
Both are important for LLM, why can't we have a high level, simple language that is also robust, efficient and fast? =)
Comment by andriy_koval 4 hours ago
I think many variants from Rust can be stripped to make it simple, especially in type system, which is way more complicated than go.
Comment by nonethewiser 4 hours ago
Comment by andriy_koval 3 hours ago
LLM can generate very cryptic rust code.
Comment by rTX5CMRXIfFG 1 hour ago
Comment by TheChaplain 4 hours ago
Comment by jimbob45 3 hours ago
Comment by coldtea 20 minutes ago
Comment by procaryote 3 hours ago
Comment by alexfortin 11 minutes ago
It's really great fun to build stuff in Crystal, I don't have anything prod-grade yet to say how it scores there but the community seems to be happy about that too.
Comment by jimbob45 3 hours ago
Comment by metaltyphoon 53 minutes ago
Comment by biztos 4 hours ago
First, I like programming and don't want to stop doing it just because a machine can do it too. Second, I'm pretty sure atrophied coding skills will make me worse at directing the machines, thus worse at what seems to be "the job" these days.
Comment by nonethewiser 4 hours ago
In theory wouldn’t atrophied coding skills not matter if models are sufficiently good at coding? I mean isn’t whats left just design and architecture and testing?
Sure, if LLMs are producing shit code you need to have an understanding of what it should do instead. But I think that day is already gone.
Its hard to think of a skill that you’d need to build with an LLM that requires writing meaningful amounts of code by oneself. From my end all the complexity is business logic and system design.
Comment by cyphar 3 hours ago
No, because good understanding of design comes from programming experience. Atrophied skills mean you lose touch with the actual nuts and bolts of what you are building.
This is also the worst kind of lock-in you can imagine, by outsourcing all of your understanding of a codebase and your skills you are now completely at the mercy of LLM providers. Even if you switch to open weight models you're at the mercy of graphics cards producers and scalpers.
> Sure, if LLMs are producing shit code you need to have an understanding of what it should do instead. But I think that day is already gone.
Maybe your standards are too low. By my standard, they still produce shit code and require lots of iterations to get reasonable designs (I often end up just rewriting the bits that are obviously wrong rather than trying to figure out how to "prompt engineer" the right output).
They do often produce passable code but my experience is the longer you spend reading the code the more things you find wrong with it, almost like an uncanny valley.
At least that's my experience with Opus and Fable. Maybe it's too old-fashioned at this point to complain about code quality, but I find it very strange how many people have started proclaiming that their code quality is good.
Comment by nonethewiser 1 hour ago
“Programming” is a bit loaded. Do you mean thinking through and typing everything out yourself?
What design skills specifically can you only develop from continually programming in this way? I fully grant that you need to know how to code yourself to build things with models but what specific ability to use models atrophies alongside your no AI coding abilities?
Personally I’ve found the opposite to be true. As writing out code myself has shrank to nearly 0, I now do way more designing. There is a much shorter feedback loop on design now. You get a lot better at design when thats basically all you are doing, and seeing feedback on your design in minutes rather than weeks or even months.
Comment by swatcoder 3 hours ago
You don't expect everyone to stop wanting to do those just because they can be automated more or less effectively, right?
Comment by nonethewiser 3 hours ago
Please reread my comment and the one im replying to. That’s not what I’m addressing.
Comment by xgulfie 4 hours ago
I am begging HN users to understand that some people enjoy writing software themselves
Comment by nonethewiser 3 hours ago
Comment by nilamo 3 hours ago
Comment by jacobgold 4 hours ago
The few times I've needed a language without a GC and used Rust and C as target languages, I've reviewed the code less and enjoyed it less.
Comment by da02 1 hour ago
Comment by citizenpaul 5 hours ago
However it kind of makes me feel like my professional life was wasted and I don't really know what kind of future I have. One of Go's main points was you can pick it up in a weekend. What career moat do people like us have?
Comment by simlevesque 4 hours ago
Comment by pjmlp 4 hours ago
Comment by bayindirh 4 hours ago
Considering it just pulls and remixes blocks, this is a very tall order for today's LLMs, and maybe a couple of generations as well.
Calling GCC/clang at the back and emitting ASM is both cheating and has no advantages whatsoever as well.
Comment by pjmlp 4 hours ago
This isn't futurology, besides a few projects that already came up on Phoronix and around here, with Assembly generation, there are enough SIGPLAN papers on ML driven compilers already.
Comment by brunoborges 3 hours ago
Clearly it isn't, otherwise every language would have sorted it out by... a long time ago.
Comment by yubblegum 1 hour ago
Comment by kccqzy 2 hours ago
Comment by layer8 2 hours ago
A JSON parser MAY accept non-JSON forms or extensions.
An implementation may set limits on the size of texts that it accepts. An implementation may set limits on the maximum depth of nesting. An implementation may set limits on the range and precision of numbers. An implementation may set limits on the length and character contents of strings.
Add to that things like duplicate keys being allowed by the spec. There’s a lot of implementation choices to decide on.
And then things can get really complex with JSON Schema.
Comment by kccqzy 1 hour ago
A lot of specs contain these optional limitations. The C standard allowed implementations to truncate variable names to 31 characters if they have external linkage and 63 if internal linkage. Would you be happy if your implementation actually does that? Of course not. Neither LLVM nor GCC does that. That’s because people writing compilers also hold themselves to a higher standard. Now imagine this kind of attitude being pervasive.
Comment by ncruces 2 hours ago
You can still use it though, and I built my tiny decimal library around it: https://github.com/ncruces/decimal
Comment by ivanjermakov 1 hour ago
Comment by jayd16 3 hours ago
Comment by CamouflagedKiwi 6 hours ago
I wish they'd left `MarshalIndent` in there though. The equivalent code is super complicated and non-obvious, so it's a pain to migrate, and it's a pain when you're banging out some quick code and want to dump some readable JSON. I suppose these days the LLMs can write the complicated version for us, of course.
Comment by athorax 6 hours ago
v := jsontext.Value(b)
v.Indent()
fmt.Println(string(v))Comment by irq-1 5 hours ago
func WithIndent(indent string) Options
https://pkg.go.dev/encoding/json/jsontext#WithIndentComment by arccy 6 hours ago
json.Marshal(v, jsontext.WithIndent(" "))
?Comment by lifeisloving 6 hours ago
Comment by modulovalue 6 hours ago
Or more concretely, if we had a parser generator + json parser specification that can generate efficient simdjson style parsers, then we should be able to parse json restricted to a subset of json based on a schema at least as efficiently as simdjson can parse general purpose json.
That way we could have the best of both worlds, a (potentially lazy) statically type-safe model and simdjson performance!
I still think that this is definitely doable, it's just that a lot of infrastructure needs to be built for it.
I remember reading that Meta is doing something similar with binary formats. I find it weird that there's nothing like that for json yet.
Comment by weitendorf 5 hours ago
I think most people who use JSON don't want strong typing or to use schemas. If you do, you just use a different serialization format: JSON is designed to be a generic, human-readable way to basically represent any kind of data structure (since it deserializes to JS objects). So everything about JSON is working against you if you do try to enforce type/schemas on it.
A grpc-like protocol with more prescriptive type registries/discovery (over the network) and better interop with http (like grpc-gateway) would be the best approach IMO. Definitely not JSON schema
Comment by thayne 3 hours ago
Not necessarily. It's biggest advantage is probably that it has very good interoperability. Basically every language has a readily accessible library for json, and even if you don't, it isn't that hard to write a parser and/or generator for it. And being human readable isn't something to sneeze at either.
Comment by lightandlight 5 hours ago
Comment by dofm 6 hours ago
I'm just getting the neuron-band back together where Golang is concerned. I have done some in the past for little system tasks, but I am switching away from interpreted languages entirely for web stuff, and initially to Go, as I switch away from hand-coding to at least LLM-supported coding.
So I am a bit out of date on the pain points (I never really felt pain points when I last used it, because the jobs I was doing had very small, quite Go-friendly shapes).
Comment by cbarrick 5 hours ago
I'm not entirely surprised, and I'm glad the Go team is carefully considering their interfaces before launching. But 6 years seems like a lot of work to land a JSON API.
Comment by awesome_dude 5 hours ago
JSON processing, quite markedly, is renown in Go for being slow, so I don't really understand why it took so long
Comment by hnlmorg 5 hours ago
I kind of like that the standard library doesn’t move fast. It makes it easier to fit the ecosystem into my head (unlike, for example, the JavaScript ecosystem where I find code doesn’t survive 2 years before failing to compile).
But I do agree that slow and steady produces its own problems. Your example of generics is a good one. But think the example of Go modules is another, perhaps even better, example of how sometimes the Go team really should have accelerated their efforts on.
Comment by awesome_dude 3 hours ago
Dependency management is a freaking nightmare, nobody has managed to create something that is bulletproof, not cargo, npm, apt, yum, nix, homebrew, nothing.
The key issue is that you're managing 3rd party software that may or may not adhere to the prescribed lifecycle/versioning
The Linux variants do it by each having dedicated teams watching upstream sources, taking what they believe to be whatever they feel is right, building for their nominated target(s), then testing, before deploying (on top of that, all of these steps vary in importance and rigor depending on numerous variables)
For programming libraries (which is what depmod, goose, vgo, and modules are managing) it's just as bad, if not harder, because their very nature is to provide a base upon which other developers can turn into whatever their imagination.
Add to that, modules was (initially) written by people who were dealing with a slightly different ecosystem; Google rather famously has a monorepo, making their lives a little easier when it comes to managing dependencies.
So, with those things in mind, dependency management is always going to be a hard problem that is opinionated (eg. I have a firm opinion that there should be an easier way to "pin" a dependency, other than vendoring - note that this isn't an invitation to every junior Go developer to come and claim go.sum does that. It doesn't. go.sum is a log of what dependencies were used for the last build by whomever wrote to it)
Comment by Philip-J-Fry 2 hours ago
Within our company I saw people in other teams writing their own optimised JSON libraries for whatever hellish reason. I always reiterated the point that as soon as that app made a single IO request all those nanosecond savings are invisible. Yes, it affects your total CPU time for processing a request but compute was never ever a limitation for us and it's likely not a limitation for most people. And if the trade off is your app needs scale slightly larger versus writing custom JSON code or pulling in a third party dependency, then I'm accepting the larger scaling.
The biggest benefit of encoding/json/v2 isn't the speed, it's the improved API.
Comment by win311fwg 5 hours ago
Only about a year from when the Haskell guys lent their expertise in designing it and it landing in a release. That's actually fairly quick given that it was a pretty significant change under the hood and constrained by only two releases annually.
The Go team was always clear that they didn't have the necessary capabilities internally, despite a lot of failed efforts trying anyway, and were relying on the open source community to lend a hand. Unfortunately, open source doesn't mean open willingness to contribute. It turns out that for all the experts on HN, posting "go doesn't have generics lol" was preferable to helping out.
Comment by enneff 4 hours ago
Comment by 0x696C6961 4 hours ago
Comment by enneff 3 hours ago
Comment by txomon 2 hours ago
There is no introspection and speed is superb. I would definitely recommend jsontext as a parser for anything non-straightforward.
Comment by hoppp 2 hours ago
I'm happy it's getting fixed!
Comment by 0xmattclark 2 hours ago
Comment by SkiFire13 4 hours ago
I feel that is the kind of broken default that will come back and bite a bunch of people, and will eventually need to be fixed in a v3.
Comment by travisd 4 hours ago
type ListUsersResponse struct {
Users []User `json:"users"`
}
in Go. It's pretty common have code like userRows := db.Query(...)
var users []api.User
for _, user := range userRows {
users = append(users, api.User{...})
}
where you don't _really_ intend for the default nil-ness to leak out. (Apologies for any broken syntax, I'm realizing in real time that it's been a while since I've written Go)Comment by devmor 4 hours ago
Comment by wiseowise 5 hours ago
Comment by gosen 3 hours ago
Comment by troupo 5 hours ago
Completely unrelated: can anyone tell me why language authors introduce in/out/inout function parameters (see also C#).
It feels like this is some rather bad workaround for something that breaks assumptions about parameters being passed into the function.
Comment by hxtk 4 hours ago
If the allocation is owned by the calling function which uses it internally and then doesn’t return it, it can be a stack variable. Or the same allocation can be reused many times in a loop. Or an array of allocations can be made all at once with foreknowledge of the total number.
Comment by jayd16 3 hours ago
But you might be conflating that with in/out for Contra/Co-variance when specifying a generic.
Comment by metaltyphoon 47 minutes ago
They are one way to implement multiple return values. For multiple returns, tuples can be used. In fact, async methods can’t declare out params
Comment by ahmedtd 3 hours ago
Comment by duskwuff 4 hours ago
Comment by CharlieDigital 4 hours ago
Comment by troupo 3 hours ago
Comment by metaltyphoon 45 minutes ago
if (int.TryParse(str, out var value) && value == 5)
{
// value is available
}
// value also availableComment by lolpanda 6 hours ago
Comment by duskwuff 5 hours ago
Not necessarily. Among other things, MarshalJSON methods called during marshaling can return an error for whatever reason the developer sees fit - one possibility that comes to mind is that part of the object tree being marshalled is lazily loaded, and failed to do so.
And, as others have mentioned, there are types like "any" whose marshalability can't be determined at compile time. Those types aren't necessarily at the top level, either; they could appear anywhere in the object tree.
Comment by sgsjchs 6 hours ago
Comment by hnlmorg 6 hours ago
Plus the point of the marshal interface is that it’s reusable.
Comment by thayne 6 hours ago
Comment by hnlmorg 6 hours ago
If you wanted type safety with JSON in Go then don’t use the marshal interface. Period.
Comment by thayne 5 hours ago
And even for unmarshalling you could get a compile time error if you try to unmarshall to a type that doesn't support it.
Comment by hnlmorg 5 hours ago
Go has this concept baked into the language. For example read and write interfaces so you can write data to an endpoint without having to worry about whether it’s a file system object, TCP/UDP socket, gzip achieve, and a plethora of other options too.
It’s a nice convenience feature and makes up considerably for the restrictions that the Go type system places.
And if you need higher performance code, or compile time safety, or have any other constraints that limit your ability to use these generalised interfaces, then you can use different APIs from the Go standard library to achieve the same thing.
You don’t need to call json.Marshal() if you don’t want to. It’s an option, but it’s just one API into the JSON toolbox.
Comment by thayne 4 hours ago
Secondly, other languages like rust, haskell, scala, etc. Have json APIs that are typesafe and give you compile time errors if you try to use a type that doesn't support (de) serialization . In the case of rust at least, the API is also general and can be used for other data types as well.
Even in go, you could have some more type safety if Marshall took an interface (such as MarshallerTo) rather than `any`. Although then you have the problem of how you implement that interface. So I guess you probably want some kind of "derive" functionality, or macros that can approximate it for a convenient and type-safe API.
P.S. gophers like to talk about how explicit being better than implicit, but using reflection for marshalling is very implicit.
Comment by awesome_dude 1 hour ago
Compile time cannot check for runtime values (not even in Rust) - is your position that fields can only be populated at compile time?
Comment by bicarbonato 5 hours ago
Because they are common types, makes sense to precautionary have the error return.
Comment by 0x696C6961 6 hours ago
Comment by jeremyloy_wt 6 hours ago
Comment by hnlmorg 5 hours ago
Comment by leetrout 6 hours ago
Comment by lolpanda 6 hours ago
Comment by iaaan 6 hours ago
Comment by NoDodgeQuestion 6 hours ago
Comment by slopnt 4 hours ago
Comment by blenser4 1 hour ago
Comment by birchcove 5 hours ago