Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Go - Paksa antara muka untuk berpuas hati hanya dengan jenis dengan penerima penunjuk pada kaedah?

Go - Paksa antara muka untuk berpuas hati hanya dengan jenis dengan penerima penunjuk pada kaedah?

PHPz
PHPzke hadapan
2024-02-10 09:27:201194semak imbas

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

editor php Baicao memperkenalkan kepada anda peraturan antara muka wajib dalam bahasa Go, iaitu, hanya jenis dengan penerima penunjuk pada kaedah boleh memenuhi keperluan antara muka. Bahasa Go ialah bahasa pengaturcaraan bertaip statik yang melaksanakan polimorfisme melalui antara muka. Apabila mentakrifkan antara muka, anda boleh menentukan jenis penerima kaedah, yang boleh menjadi jenis nilai atau jenis penunjuk. Walau bagaimanapun, apabila kami menggunakan peraturan antara muka wajib, hanya jenis dengan penerima penunjuk pada kaedah boleh memenuhi keperluan antara muka Ini kerana jenis penunjuk boleh mengubah suai kandungan nilai, tetapi jenis nilai tidak boleh. Peraturan ini memastikan kaedah antara muka tidak menyebabkan tingkah laku yang tidak dapat diramalkan apabila memanipulasi nilai. Dengan memahami peraturan ini, kami boleh lebih memahami penggunaan dan reka bentuk antara muka dalam bahasa Go.

Kandungan soalan

Saya sedang melakukan beberapa eksperimen dengan parameter jenis untuk menghasilkan cara umum menggabungkan struktur untuk menjana respons kepada permintaan http json.

Kaedah yang method 接口有一个 setparams struktur mesti laksanakan. Selagi pelaksanaan menggunakan penerima penunjuk, ini akan berfungsi seperti yang diharapkan.

Soalan saya: Jika setparams mempunyai penerima nilai, adakah ada cara untuk menjadikannya ralat masa kompilasi?

Contoh berikut menunjukkan masalah setparams dengan penerima nilai:

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

Penyelesaian

Anda tidak boleh melakukan ini.

Apabila anda melakukan perkara berikut dalam kod anda:

var m T = new(M)

Malaht的类型集仅包括*m作为类型项,*m的方法集也包括在m上声明的方法。编译器无法检查该方法如何出现在 *m kaedahnya fokus.

Pada badping 上声明方法 setparam adalah menjadi tanggungjawab anda untuk memastikan kaedah tersebut tidak sia-sia untuk mengubah suai penerima.

Atas ialah kandungan terperinci Go - Paksa antara muka untuk berpuas hati hanya dengan jenis dengan penerima penunjuk pada kaedah?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam