Repository: go
Issue: proposal: spec: interface literals
Labels: LanguageChange,Proposal,LanguageChangeReview

Filing this for completeness sake, since it was mentioned in https://github.com/golang/go/issues/21670 that this proposal had been discussed privately prior to Go 1. Just like literals allow the construction of slice, struct, and map values, I propose "interface literals" which specifically construct values that satisfy an interface. The syntax would mirror that of struct literals, where field names would correspond to method names. The original idea is proposed by @Sajmani in https://github.com/golang/go/issues/21670#issuecomment-325739411.

Conceptually, this proposal would transform the following initializer
```Go
f := func(p int) { /* implementation */ }
x := interface{
	Name(p int)
}{f}

```
to the following type declaration and struct initializer
```Go
type _impl_Name_int struct {
	f func(p int)
}
func(v _impl_Name_int) Name(p int) { v.f(p) }
// … in some other scope
f := func(p int) { /* implementation */ }
var x interface{
	Name(p int)
} = _impl_Name_int{f}
```
As an extension to what’s mentioned in #21670, I propose that fields be addressable by both method names and field names, like in this example:
```Go
type ReadWriteSeekCloser interface {
	ReadWriteSeeker
	Closer
}

f := os.Open("file")
calls := 0
return ReadWriteSeekCloser{
	ReadWriteSeeker: f,
	Close: func() error {
		if calls < 1 {
			return f.Close()
		}
		return nil
	},
}
```
The default value for a method is `nil`. Calling a nil method will cause a panic. As a corollary, the interface can be made smaller to be any subset of the original declaration. The value can no longer be converted back to satisfy the original interface. See the following modified example (from @neild in https://github.com/golang/go/issues/21670#issuecomment-329251670):

```Go
type io interface {
  Read(p []byte) (n int, err error)
  ReadAt(p []byte, off int64) (n int, err error)
  WriteTo(w io.Writer) (n int64, err error)
}
// 3 method -> 2^3 = 8 subsets
func fn() io.Reader {
	return io{
		Read: strings.NewReader(“”),
	}
}
```
The nil values for `ReadAt` and `WriteTo` make it so the “downcasted” `io.Reader` can no longer be recast to an `io`. This provides a clean way to promote known methods, with the side effect that the struct transformation described above won't be a valid implementation of this proposal, since casting does not work this way when calling a nil function pointer through a struct.

Although this proposal brings parity between struct and interface initialization and provides easy promotion of known methods, I don’t think this feature would dramatically improve the way Go programs are written.

We may see more usage of closures like in this sorting example (now obviated because of sort.Slice):
```Go
arr := []int{1,2,3,4,5}
sort.Sort(sort.Interface{
	Len: func() int { return len(arr) },
	Swap: func(i, j int) {
		temp := arr[i]
		arr[i] = arr[j]
		arr[j] = temp
	},
	Less: func(i, j int) bool { return arr[i] < arr[j] },
})
```
Promotion of known methods also avoids a lot of boilerplate, although I’m not sure that it is a common enough use case to warrant a language feature.
For instance, if I wanted to wrap an `io.Reader`, but also let through implementations of `io.ReaderAt`, `io.WriterTo`, and `io.Seeker`, I would need seven different wrapper types, each of which embeds these types:
```Go
type wrapper1 struct {
	io.Reader
	io.ReaderAt
}
type wrapper2 struct {
	io.Reader
	io.WriterTo
}
type wrapper3 struct {
	io.Reader
	io.Seeker
}
type wrapper4 struct {
	io.Reader
	io.ReaderAt
	io.WriterTo
}
type wrapper5 struct {
	io.Reader
	io.ReaderAt
	io.Seeker
}
type wrapper6 struct {
	io.Reader
	io.WriterTo
	io.Seeker
}
type wrapper7 struct {
	io.Reader
	io.ReaderAt
	io.WriterTo
	io.Seeker
}
```
Here is the relevant change to the grammar (under the composite literal section of the spec):
```
LiteralType = StructType | InterfaceType | ArrayType | "[" "..." "]" ElementType | 
              SliceType | MapType | TypeName .
```