Go - 强制接口仅由方法上具有指针接收器的类型满足?

我正在对类型参数进行一些实验,以提出一种通用的方法来连接生成对 JSON HTTP 请求的响应的结构。


Method结构必须实现的接口有一个方法SetParams。只要实现使用指针接收器,这就会按预期工作。


SetParams我的问题:如果有值接收者,有什么方法可以使它成为编译时错误?


SetParams下面是一个示例,它演示了具有值接收者的问题:


package main


import (

    "encoding/json"

    "fmt"

    "log"

)


type PingParams struct {

    Name string

}


type PingResponse struct {

    Message string

}


func (p PingParams) Greeting() string {

    if p.Name != "" {

        return fmt.Sprintf("Hello, %s", p.Name)

    }


    return fmt.Sprintf("Hello, nobody!")

}


type GoodPing struct {

    Params PingParams

}


// SetParams has a pointer receiver.

func (m *GoodPing) SetParams(p PingParams) {

    fmt.Printf("assign %v with pointer receiver, Good!\n", p)

    m.Params = p

}

func (m GoodPing) Run() (*PingResponse, error) {

    return &PingResponse{Message: fmt.Sprintf("%T %s", m, m.Params.Greeting())}, nil

}


type BadPing struct {

    Params PingParams

}


// SetParams has a value receiver.

func (m BadPing) SetParams(p PingParams) {

    fmt.Printf("assign %v with value receiver, Bad!\n", p)

    m.Params = p

}

func (m BadPing) Run() (*PingResponse, error) {

    return &PingResponse{Message: fmt.Sprintf("%T %s", m, m.Params.Greeting())}, nil

}


type Method[M, RQ, RS any] interface {

    // Run builds the RPC result.

    Run() (*RS, error)

    // SetParams is intended to set the request parameters in the struct implementing the RPC method.

    // This then allows the request parameters to be easily available to all methods of the Method struct.

    // The method MUST have a pointer receiver. This is NOT enforced at compile time.

    SetParams(p RQ)

    // The following line requires the implementing type is a pointer to M.

    *M

    // https://stackoverflow.com/a/72090807

}


func HandlerMethod[M, RQ, RS any, T Method[M, RQ, RS]](in json.RawMessage) (*RS, error) {

    // A real implementation of this would return a func for wiring into a request router


    var req RQ


    err := json.Unmarshal(in, &req)


    if err != nil {

        return nil, err

    }


}



https://go.dev/play/p/Eii8ADkmDxE


临摹微笑
浏览 172回答 1
1回答

心有法竹

你不能那样做。在您的代码中执行此操作时:var m T = new(M)即使T的类型集仅*M作为类型术语包含,*M的方法集也包含声明在 上的方法M。编译器无法为您检查该方法如何*M在 的方法集中结束。SetParam在声明该方法时,您有责任BadPing确保该方法不会尝试无效地修改接收器。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go