// isValidNumber reports whether s is a valid JSON number literal. // // isValidNumber should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/bytedance/sonic
Hyrum’s Law in Golang
101–110 of 190 posts
Re: Hyrum’s Law in Golang
#102Earlier quoted context omitted.
> You will be forced to lug this broken behavior with you forever Yep, welcome to my life.
Wouldn't a nil ECDSA key be a security risk?
I don't see how this can be a security risk, but allowing a public key that has a curve but a nil value is definitely a messy API.
Re: Hyrum’s Law in Golang
#103Hyrum's Law is one of those observations that's certainly useful, but be careful not to fixate on it and draw the wrong conclusions. Consider that even the total runtime of a function is an observable property, which means that optimizing a function to make it faster is a breaking change (what if suddenly one of your queues clears too fast and triggers a deadlock??), despite the fact that 99.99999999% of your users w…
I think everything you said is totally correct for open source library owners. But let me offer a different perspective: Hyrum’s law is neither a technical contract nor a social contract. It’s an emergent technical property in a sufficiently used system. How you respond to that emergent property depends on the social context. If you are a FOSS maintainer, and an optimization speeds up 99.99% of users and requires 0.0…
This is also a sufficient description of "social contract" for this context.
Re: Hyrum’s Law in Golang
#104That being said, you can take proactive steps to defeat this. For example, the default Hash for strings in .NET is randomly seeded each time a process starts[1] in order to strongly dissuade folks from taking an implicit dependency on the underlying algorithm which is not guaranteed to be stable
[0] : https://en.wikipedia.org/wiki/Protocol_ossification
[1] : https://andrewlock.net/why-is-string-gethashcode-different-e...
Re: Hyrum’s Law in Golang
#105Earlier quoted context omitted.
Semantic versioning does nothing to help here. If you don't realize that people are depending on such a behavior, you won't increment the major version number.
And if you realize it (as in this case) you probably don't want to increase the major version number either, but leave it as-is (unless you follow the CADT model of maintainership).
A bit trickier in this case no doubt; and trade offs. Ive not minded the React updates over the years, but busting out the Go code I wrote many years ago and having it still run flawlessly is amazing too.
Re: Hyrum’s Law in Golang
#106Earlier quoted context omitted.
Go has typed errors, it just didn't use it in this case.
In principle. In practice, most Go code, and even significant parts of the Go standard library, return arbitrary error strings. And error returning functions never return anything more specific than `error` (you could count the exceptions in the top 20 Go codebases on your fingers, most likely). Returning non-specific exceptions is virtually encouraged by the standard library (if you return an error struct, you run i…
package example
var ErrValue = errors.New("stringly")
type ErrType struct {
Code int
Message string
}
func (e ErrType) Error() string {
return fmt.Sprintf("%s (%d)", e.Message, e.Code)
}
You can now use errors.Is with a target of ErrValue and errors.As with a target of *ErrType. No extra methods are needed.However, you can't compare ErrValue to another errors.New("stringly") by design (under the hood, errors.New returns a pointer, and errors.Is uses simple equality). If you want pure value semantics, use your own type instead.
There are Is and As interfaces that you can implement, but you rarely need to implement them. You can use the type system (subtyping, value vs. pointer method receivers) to control comparability in most cases instead. The only time to break out custom implementations of Is or As is when you want semantic equality to differ from ==, such as making two ErrType values match if just their Code fields match.
The one special case that the average developer should be aware of is unwrapping the cause of custom errors. If you do your own error wrapping (which is itself rarely necessary, thanks to the %w specifier on fmt.Errorf), then you need to provide an Unwrap method (returning either an error or a slice of errors).
Re: Hyrum’s Law in Golang
#107Earlier quoted context omitted.
The map iteration order change helps to avoid breaking changes in future, by preventing reliance on any specific ordering, but when the change was made it was breaking for anything that was relying on the previous ordering behaviour. IMO this is a worthwhile tradeoff. I use Go a lot and love the strong backwards compatibility, but I would happily accept a (slightly) higher rate of breaking changes if it meant greater…
Data point of one, but I've been using Go since 2012 and would drop it instantly if any of the backwards compatibility guarantees were relaxed. Having bugs imposed on you from outside your project is a waste of time to deal with and there are dozens of other languages you can pick from if you enjoy that time sink. Most of them give you greater capabilities as the balance. Go's stability is a core feature and compensa…
I’d call your bluff.
Re: Hyrum’s Law in Golang
#108Sure... but this is why we have sem versioning and release notes. It's always nice to try and support all users but sometimes you just need to ship breaking changes...
Re: Hyrum’s Law in Golang
#109This is a good example of "stringly typed" software. Golang designers did not want exceptions (still have them with panic/recover), but untyped errors are evil. On the other hand, how would one process typed errors without pattern matching? Because "catch" in most languages is a [rudimentary] pattern matching. https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
Go has typed errors, it just didn't use it in this case.
In this case the Error has an easy-to-check public type (*MaxBytesError) and the documentation clearly indicates that. But that has not always been the case. The original sin is that the API returned a generic error and the only way to test that error was to use a string comparison.
This is an important context to have when you need to make balanced decisions about Hyrum's law. As some commentators already mentioned, you should be wary of taking the extreme version of the law, which suggest that every single observable behavior of the API becomes part of the API itself and needs to be preserved. If you follow this extreme version, every error or exception message in every language must be left be left unchanged forever. But most client code doesn't just go around happily comparing exception messages to strings if there is another method to detect the exception.