Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

He was basically saying A is an old problem, the new problem is B. However, there's no obvious way to solve B, so we don't solve B.

But why not solve A then? Unless.. A is not a problem anymore nowadays. (Is it, though?)

But if A is not a problem anymore, he could have just said struct field ordering was an old problem and not a problem anymore in 2010s, without mentioning the other problem.

Meanwhile the blog post suggests that struct field ordering is still a problem even in 2020s.



If Go tries to automatically solve A, it prevents a developer from solving B because there is no way to control field order.

By Go doing nothing, a developer can manually solve both A and B.


This is a strawman argument. It presents the two options as mutually incompatible, whereas they are not (as demonstrated by other languages that allow to do both).


But if I understand things correctly, go, the spec, doesn’t provide the developer a way to control field order. It’s only the (main) implementation that currently happens to keep field order matching the order in the source code.

So, currently, there is no way to force memory layout, other than, as https://github.com/golang/go/issues/10014#issuecomment-26346... says

“defining the type using [n]byte and modifying the fields using the encoding/binary package. On many processors the performance will be approximately the same.”

Seems unsatisfactory to me.


> But if I understand things correctly, go, the spec, doesn’t provide the developer a way to control field order.

The spec doesn't, but the actual compiler implementation does. If the compiler is not allowed to re-order fields, they remain in the order the programmer specified in the code. That's why the fix in the article works in the first place.


But the compiler isn’t “not allowed to re-order fields”. The spec allows it to do that. This fix works for the current compiler, but may not do so for next week’s.

Technically you could say it wouldn’t even be a breaking change if a compiler update changed that (practically people would have reason to be angry if they slipped something like that in without creating a major version and adding warning flags to the release notes)


> By Go doing nothing, a developer can manually solve both A and B.

In Rust, you can annotate a struct declaration with "#[repr(C)]" to prevent the compiler from reordering fields. I don't see why the Go compiler couldn't offer something similar.


Go’s philosophy seems to be a very minimal/low-feature language, that’s fairly low level, even if that means somewhat more awkward or mistake-prone code. Go’s current approach seems more Go-y than an annotation like this.


> Go’s philosophy seems to be a very minimal/low-feature language, that’s fairly low level, even if that means somewhat more awkward or mistake-prone code.

And that’s why it tells you to fuck off when you have an unused variable, a non-solution to a non-problem.


Yeah, keeps the code cleaner, no unwanted variable and imports as I have tonnes of these in my Java codebase. One can use IDEs to fix it but I am not gonna generate 1000 files changed PR for this and apparently neither did last 5-6 people who worked this project.

Maybe you have not worked in these enterprise type projects where Java/Go is most likely used. In these places anything that is not build failure / compiler error is not an issue to be fixed now or ever.


> Yeah, keeps the code cleaner

You may want to take context in account when reading comments, they don’t existing in a blank void.

> One can use IDEs to fix it but I am not gonna generate 1000 files changed PR for this and apparently neither did last 5-6 people who worked this project.

That really has nothing to do with the subject at hand, and linters exist (in fact for most actual errors go requires a linter because the compiler is so anemic); for projects which are already in the pits, incremental linting is a thing (where linter errors are only a hard CI failure when they’re part of the PR’s diff).


> You may want to take context in account when reading comments, they don’t existing in a blank void.

Agree.

But you do not have to ever understand others point of view because your opinion is a fact and absolute must on any programing language design.


Yeah - the tradeoff isn’t about the benefits in places where macros would solve problems, but the problem of having macros. It’s an opinion.


An annotation in Rust isn't a macro. The Go equivalent would be a directive in a comment. For example: //go:repr c

https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives


Is the situation for Rust different than as described here: https://github.com/rust-lang/rfcs/pull/208

“Currently, attributes and macros/syntax extensions are both conceptually macros: they are user-definable syntactic extensions that transform token trees to token trees.”

FWIW I definitely admit the point about Go compiler directives sort of cheating into this space a bit - I see them used responsibly for the most part but it’s a valid point. (Go’s struct tags OTOH, are an escape hatch I revile…).


> Is the situation for Rust different than as described here: https://github.com/rust-lang/rfcs/pull/208

In short: yes. The wording in that quote is imprecise: I suspect that by 'attributes', pcwalton was referring to user-definable attributes like #[serde(rename_all = "...")] and to custom derive macros like #[derive(Serializable)]. It is impossible to achieve the effects of the #[repr(C)] attribute using macros or token tree transformations.


If you're asking if macros and attributes are interchangeable terms, no they're not.


> very minimal/low-feature language, that’s fairly low level, even if that means somewhat more awkward or mistake-prone code

Do you think this is a good trade-off?

If you're using a tool every day or at least regularly, the one-time cost of mastering a slightly more complex tool is amortized over all uses of that tool.


You may be using the tool every day, but are you using this "disable field reordering" annotation every day? Also, after you used it, you may remember what "#[repr(C)]" does, but I bet most of the other developers working with the code in the future will have to look it up (unless you leave a comment). So the trade-off is not as cheap as you think...


I didn’t pass any judgement on whether it’s a good or bad tradeoff, just that it’s in-line with Go’s general approach to language design.


You could add something like that, but I suspect the new default behaviour would then break a number of programs (in particular things that use reflect and unsafe). There aren't many guarantees around this kind of usage but in practice the go devs are pretty reluctant to make changes that are known to break things without a very good reason, even in things where there's not a formal compatability promise.


The solution to A will break manual attempts to address B.


The solution to A being opt-out makes addressing B not an issue.


Yeah, for sure. I didn't mean to imply that it wraps up the whole argument, merely that it was the step in the original reasoning that the parent was missing.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: