用作接口的复合文字的地址

The address of a composite literal is evaluated as the literal itself when used as an interface. Can somebody please point to the part of the ref spec which deals with this ?

package main
import "fmt"

type ntfc interface {
    rx() int
}

type cncrt struct {
    x int
}

func (c cncrt) rx() int{
    return c.x
}

func rtrnsNtfca() ntfc {
    return &cncrt{3}
}

func rtrnsNtfc() ntfc {
    return cncrt{3}
}

func rtrnsCncrt() *cncrt {
    return &cncrt{3}
}

func main() {
    fmt.Println(rtrnsNtfca().rx())
    fmt.Println(rtrnsNtfc().rx())
    fmt.Println(rtrnsCncrt().rx())
}

Also here. For future ref., is it acceptable to just link to the playground without including the code here?

Spec: Method sets:

A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).

So the method set of *cncrt includes the methods set of cncrt. Since rx() is an element of cncrt's method set, it will also be in *cncrt's method set. Which means both cncrt and *cncrt types implement the ntfc interface.

If you have a pointer value (*cncrt) and you call rx() on it, the pointer will automatically be dereferenced which will be the receiver of the rx() method.

In your rtnsNtfca() and rtnsNtfc() functions an interface value of ntfc will automatically be created and returned. Interface values in Go are represented as (type;value) pairs (for more details: The Laws of Reflection #The representation of an interface). So both rtnsNtfca() and rtnsNtfc() return an interface value, but the first one holds a dynamic value of type *cncrt and the latter one holds a dynamic value of type cncrt.

And your 3rd method rtrnsCncrt() returns a concrete type (*cncrt), there is no interface wrapping involved there.

Note: "The other way around"

Spec: Calls:

If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().

This means if you would have declared rx() to have a pointer receiver, and you have a variable of type cncrt (note: not pointer), you could still call the rx() method on it if it is addressable, and the address would be taken automatically and used as the receiver.