-1
votes

Retour type polymorphe avec membre de données

J'essaie d'écrire une fonction gettargetserver () pour renvoyer un type polymorphique qui a à la fois un élément de données URL et une méthode fermeture () < / code>. Ce serait une généralisation de * serveur retourné de httpest.newserver () Mais je veux alternativement être capable de retourner un type personnalisé pour lequel ferme () est un nop. xxx

ceci fonctionne comme un charme sauf que ferme () est toujours un nop. Lorsque je découvre l'erreur indiquée ### ERROR ### LIGNE afin de renvoyer un serveur Clostable , je reçois le message d'erreur suivant:

Impossible d'utiliser testServer (type * httpest.server) comme type * externestestServer dans l'argument de retour

Je comprends l'erreur, mais je n'ai pas découvert une solution qui me permet de retourner un type polymorphe qui généralise * serveur


note: " Une visite de Go "définit un type d'interface comme suit:

Un type d'interface est défini comme un ensemble de signatures de méthodes.

Par conséquent, le retour d'une interface simple ne permettra pas aux membres de données directement accessibles.


3 commentaires

La seule forme de polymorphisme dans Go est des interfaces et des interfaces décrivent uniquement le comportement; ils ne peuvent pas avoir de champs.


Reddit: Interface vs struct avec les pointeurs de fonction


-2: À ce rythme, je ne deviendrai jamais "curieux" :(


3 Réponses :


2
votes

http.server est une structure, vous ne pouvez donc pas renvoyer un objet polymorphe qui généraliste cela. Vous pouvez faire quelque chose d'autre cependant: xxx

Vous pouvez ensuite retourner le serveur de votre fonction.


1 commentaires

Bonne réponse. Cela ressemble à l'approche que j'ai initialement pensé que je devrais prendre. C'est un peu volumineux (créant des emballages supplémentaires pour les choses), donc pas ma préférence.



2
votes

Vous pouvez créer une struct qui a un champ qui est une chaîne url code> et un champ qui correspond à un fermeture code> func code>. Le Fermer code> FUNC code> peut être implémenté par ExternatestSserver code> ou HTTPTEST.SERVER CODE>:

    if urlbase, ok := optionals["urlbase"].(string); ok {
        extServer := &externalTestServer{URL: urlbase}
        return &server{
            URL:   urlbase,
            Close: extServer.Close,
        }
    }
    testServer := httptest.NewServer(newMyServerHandler())
    return &server{
        URL:   testServer.URL,
        Close: testServer.Close,
    }


2 commentaires

Cela semble se comporter exactement comme je l'avais espéré - et très simple à construire.


N'ayez même pas besoin externestestSserver - peut simplement utiliser Fermer: FUNC () {} pour créer le NOP.



0
votes

L'approche de Chris Drew est idéale pour ce cas particulier, car elle nécessite une surcharge de code minimale. Mettez un autre moyen, c'est la chose la plus simple qui résoudra le problème d'aujourd'hui. La solution utilise la magie d'une fermeture implicite (pour le récepteur em>) pour référencer la mise en oeuvre de fermer () code> polymorphiquement.

ma version légèrement simplifiée de celle-ci est ici. .. p> xxx pré>


par l'intégration em> un type d'interface em> dans la structure de retour, ce concept peut être de manière transparente étendu à de mieux supporter des interfaces polymorphes non triviales. Dans ce cas, le polymorphisme est explicite sur la base de l'utilisation interne d'un type d'interface. Néanmoins, le type retourné est une enveloppe comprenant une copie des données de membre (constante), de sorte que l'utilisation est identique - généralisant efficacement celui de * SERVER CODE> pour ce cas d'utilisation. P>

type Server interface {
    Close()
}

type nopServer struct {
}

func (nopServer) Close() {}

type genericServer struct {
    URL string // snapshot of specific data
    Server // embedded interface type for explicit polymorphism
}

func getTargetServer() genericServer {
    if urlbase, ok := optionals["urlbase"].(string); ok {
        return genericServer{URL: urlbase, Server: nopServer{}}
    }
    testServer := httptest.NewServer(newMyServerHandler())
    return genericServer{URL: testServer.URL, Server: testServer}
}


0 commentaires