Home  >  Article  >  Backend Development  >  Ensuring strict comparability at compile time in Go 1.20?

Ensuring strict comparability at compile time in Go 1.20?

王林
王林forward
2024-02-11 23:20:081042browse

确保 Go 1.20 中编译时的严格可比性?

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.

Question content

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?

Workaround

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 instantiate

comparable exceptions.

Now in Go 1.20, type

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.

This trick effectively makes the program fail to compile if

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!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete