php editor Baicao introduces to you an important feature in Go language version 1.20 - strict comparability at compile time. In Go language version 1.20, new compiler flags are introduced to ensure that the binary files generated during compilation are comparable under different compilation environments. This means that binaries generated under different compilation environments will have the same behavior and results, reducing potential problems caused by different compilation environments. The introduction of this feature will further improve the reliability and stability of the Go language and provide developers with a better development experience.
In Go 1.18 and Go 1.19, I can ensure at compile time that the type is strictly comparable , i.e. it supports ==
and !=
operators, and ensure that these operators do not panic when they run.
This is useful, for example, to avoid inadvertently adding fields to a structure, causing unnecessary panic.
I just tried to instantiate it with comparable
:
// supports == and != but comparison could panic at run time type Foo struct { SomeField any } func ensureComparable[T comparable]() { // no-op } var _ = ensureComparable[Foo] // doesn't compile because Foo comparison may panic
This is possible in Go 1.18 and 1.19 due to the definition of comparable
constraints:
The predeclared interface type comparable denotes the set of all non-interface types that are comparable
Although the Go 1.18 and 1.19 specifications do not mention types that are not interfaces but cannot be strictly compared, such as [2]fmt.Stringer
or struct { foo any }
, gc compile The compiler does reject these as arguments to comparable
.
A playground with several examples: https://go.dev/play/p/_Ggfdnn6OzZ
In Go 1.20, instantiation of comparable
will be consistent with the broader concept of comparability. This makes ensureComparable[Foo]
compile even though I don't want it .
Is there a way to statically ensure strict comparability with Go 1.20?
To test whether Foo
is strictly comparable in Go 1.20, use a type parameter## constrained by
Foo #instantiationensureComparable.
// unchanged type Foo struct { SomeField any } // unchanged func ensureComparable[T comparable]() {} // T constrained by Foo, instantiate ensureComparable with T func ensureStrictlyComparable[T Foo]() { _ = ensureComparable[T] // <---- doesn't compile }
This solution was originally suggested by Robert Griesemer here . a>
So how does it work?Go 1.20 introduced
implementing the interface and satisfying constraints:
The second point is to allow interfaces and types with interfaces to instantiatecomparable exceptions.
Foo itself can be instantiated
comparable due to satisfiability exceptions. But the type parameter
T is not
Foo. Compatibility definitions for type parameters
are different :
The type set of
T contains a type
Foo that is not strictly comparable (because it has an interface field), so
T is not
comparable . Even
Foo itself.
Foo's operators
== and
!= are likely to panic at runtime.
The above is the detailed content of Ensuring strict comparability at compile time in Go 1.20?. For more information, please follow other related articles on the PHP Chinese website!