l'éditeur php Baicao vous présente les règles d'interface obligatoires en langage Go, c'est-à-dire que seuls les types avec des récepteurs de pointeurs sur les méthodes peuvent répondre aux exigences de l'interface. Le langage Go est un langage de programmation typé statiquement qui implémente le polymorphisme via des interfaces. Lors de la définition d'une interface, vous pouvez spécifier le type de récepteur d'une méthode, qui peut être un type valeur ou un type pointeur. Cependant, lorsque nous utilisons des règles d'interface obligatoires, seuls les types avec des récepteurs de pointeurs sur les méthodes peuvent répondre aux exigences de l'interface. En effet, les types pointeurs peuvent modifier le contenu de la valeur, mais pas les types valeur. Cette règle garantit que les méthodes d'interface ne provoquent pas de comportement imprévisible lors de la manipulation des valeurs. En comprenant cette règle, nous pouvons mieux comprendre l’utilisation et la conception des interfaces dans le langage Go.
Je fais quelques expériences avec les paramètres de type pour trouver une manière générale de concaténer des structures pour générer des réponses aux requêtes http json.
Méthodes que la method
接口有一个 setparams
structure doit mettre en œuvre. Tant que l'implémentation utilise des récepteurs de pointeurs, cela fonctionnera comme prévu.
Ma question : si setparams
a un récepteur de valeur, existe-t-il un moyen d'en faire une erreur de compilation ?
L'exemple suivant illustre le problème de setparams
avec un récepteur de valeur :
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
Vous ne pouvez pas faire ça.
Lorsque vous effectuez ce qui suit dans votre code :
var m T = new(M)
Mêmet
的类型集仅包括*m
作为类型项,*m
的方法集也包括在m
上声明的方法。编译器无法检查该方法如何出现在 *m
la méthode est ciblée.
Chez badping
上声明方法 setparam
il est de votre responsabilité de vous assurer que la méthode ne tente pas en vain de modifier le récepteur.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!