php小编百草为您介绍Go语言中的强制接口规则,即只有方法上带有指针接收器的类型才能满足接口的要求。Go语言是一门静态类型的编程语言,它通过接口来实现多态性。在定义接口时,可以指定方法的接收器类型,可以是值类型或指针类型。但是,当我们使用强制接口规则时,只有方法上带有指针接收器的类型才能满足接口的要求,这是因为指针类型可以修改值的内容,而值类型不能。这个规则保证了接口的方法在操作值时不会引起不可预知的行为。通过了解这个规则,我们可以更好地理解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 } var m T = new(M) m.SetParams(req) return m.Run() } func main() { payload := []byte(`{"Name": "Mark"}`) bad, err := HandlerMethod[BadPing, PingParams, PingResponse](payload) if err != nil { log.Fatal(err) } fmt.Println(bad.Message) good, err := HandlerMethod[GoodPing, PingParams, PingResponse](payload) if err != nil { log.Fatal(err) } fmt.Println(good.Message) }
https://go.dev/play/p/eii8adkmdxe
你不能这么做。
当您在代码中执行以下操作时:
var m T = new(M)
即使t
的类型集仅包括*m
作为类型项,*m
的方法集也包括在m
上声明的方法。编译器无法检查该方法如何出现在 *m
的方法集中。
在 badping
上声明方法 setparam
时,您有责任确保该方法不会尝试徒劳地修改接收者。
以上是Go - 强制接口仅由方法上带有指针接收器的类型满足?的详细内容。更多信息请关注PHP中文网其他相关文章!