What version of Go are you using (go version)?
$ go version
go version go1.18beta1 darwin/amd64
Does this issue reproduce with the latest release?
na. This is only currently possible in 1.18beta1.
What operating system and processor architecture are you using (go env)?
go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/akutz/Library/Caches/go-build"
GOENV="/Users/akutz/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/akutz/Projects/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/akutz/Projects/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/Users/akutz/.go/active"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/akutz/.go/active/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.18beta1"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/akutz/Projects/controller-runtime/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/0c/ffr4wl4d37924s44ctztx_ym00bgms/T/go-build1780269713=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
Over the holidays I started digging into Golang generics, and after much consideration, I decided I wanted to create a constraint like so:
type Condition[T ~string, S ~string] interface {
~struct{
Type T
Status string
Severity S
LastTransitionTime int64
Reason string
Message string
}
}
It is my understanding the above constraint should be valid based upon the following example from the type parameter proposal (from the section Composite Types in Constraints):
// structField is a type constraint whose type set consists of some
// struct types that all have a field named x.
type structField interface {
struct { a int; x int } |
struct { b int; x float64 } |
struct { c int; x uint64 }
}
// This function is INVALID.
func IncrementX[T structField](p *T) {
v := p.x // INVALID: type of p.x is not the same for all types in set
v++
p.x = v
}
While the above example shows the function is INVALID, it also implies that such a constraint would be valid if not for the mixed-type of x. However, when I tried to use this in practice, I received the following error:
c.Type undefined (interface Condition has no method Type)
I was able to replicate this in the Go 1.18 playgound with the following example:
package main
import (
"fmt"
)
type Cat struct {
Name string
}
type Dog struct {
Name string
}
type Person struct {
Name string
}
type Named interface {
~struct{ Name string }
}
func SayName[T Named](t T) {
fmt.Println(t.Name)
}
func main() {
SayName(Person{Name: "Andrew"})
}
The above program produces the following error:
./prog.go:24:16: t.Name undefined (interface Named has no method Name)
Go build failed.
What did you expect to see?
I expected the program to build and print the line Andrew.
What did you see instead?
The aforementioned compile error:
./prog.go:24:16: t.Name undefined (interface Named has no method Name)
Go build failed.
It would be incredibly useful for this constraint to work as I understand it from the proposal. Perhaps:
- I misunderstood the proposal
- The proposal is not up-to-date with the implementation
- The implementation is incomplete in 1.18beta1
Regardless, the reason I would like this to work is as follows:
- Using the above example, imagine
C Condition[T, S]
- Now imagine a value of
c C
- If I want to set the
Type field on c, I can just do c.Type = ...
- But without the above constraint, I would have to change to something like the following:
type Condition[T ~string, S ~string] interface {
SetType(type3 T)
}
- The problem with the above is that if I have a struct that implements the interface
Condition[T, S], that means the struct must have a function like func (c *MyCondition) SetType(type3 MyConditionType).
- The receiver for the setter function is necessarily by address
- Which means it is not
MyCondition that satisfies the constraint Condition[T, S], but *MyCondition
- This greatly complicates things, and it would be much nicer to constrain based on the
~struct {...} and to use those fields directly
Thanks!
What version of Go are you using (
go version)?Does this issue reproduce with the latest release?
na. This is only currently possible in 1.18beta1.
What operating system and processor architecture are you using (
go env)?go envOutputWhat did you do?
Over the holidays I started digging into Golang generics, and after much consideration, I decided I wanted to create a constraint like so:
It is my understanding the above constraint should be valid based upon the following example from the type parameter proposal (from the section Composite Types in Constraints):
While the above example shows the function is
INVALID, it also implies that such a constraint would be valid if not for the mixed-type ofx. However, when I tried to use this in practice, I received the following error:I was able to replicate this in the Go 1.18 playgound with the following example:
The above program produces the following error:
What did you expect to see?
I expected the program to build and print the line
Andrew.What did you see instead?
The aforementioned compile error:
It would be incredibly useful for this constraint to work as I understand it from the proposal. Perhaps:
Regardless, the reason I would like this to work is as follows:
C Condition[T, S]c CTypefield onc, I can just doc.Type = ...Condition[T, S], that means the struct must have a function likefunc (c *MyCondition) SetType(type3 MyConditionType).MyConditionthat satisfies the constraintCondition[T, S], but*MyCondition~struct {...}and to use those fields directlyThanks!