web-dev-qa-db-ja.com

複数のパラメーターと戻り値の型のためのGolangインターフェース設計

一般的な質問

両方をサポートできるインターフェイスを設計するにはどうすればよいですか

// v1beta1.Deployment
type Deployment struct {
    metav1.TypeMeta
    metav1.ObjectMeta
    Spec v1beta1.DeploymentSpec
    Status v1beta1.DeploymentStat
}
type DeploymentInterface interface {
    Create(*v1beta1.Deployment) (*v1beta1.Deployment, error)
    Update(*v1beta1.Deployment) (*v1beta1.Deployment, error)
    UpdateStatus(*v1beta1.Deployment) (*v1beta1.Deployment, error)
}
// v1.Deployment
type Deployment struct {
    metav1.TypeMeta
    metav1.ObjectMeta
    Spec v1.DeploymentSpec
    Status v1.DeploymentStat
}
type DeploymentInterface interface {
    Create(*v1.Deployment) (*v1.Deployment, error)
    Update(*v1.Deployment) (*v1.Deployment, error)
    UpdateStatus(*v1.Deployment) (*v1.Deployment, error)
}

異なるパラメーターと戻り値の型はどれですか?


詳細

上記の2つのインターフェースはkubernetes go-clientからのもので、異なるバージョンのAPIを定義しています。実行しているクラスターの異なるバージョンで両方をサポートする必要があり、すべてのバージョンのアプリケーションコードをコピーしたくないので、Deploymentの異なるバージョンをサポートできるインターフェイスを設計したいと思います。

アプリケーションの現在のコードには、例として、特定のタイプに依存する多くのヘルパー関数があります。

func (s *KubeControllerService) deploymentCustomImage(deployment *v1beta1.Deployment, appGitBuildConfig *models.AppGitBuildConfig) *v1beta1.Deployment {
}

そして私たちは何百ものそれらを持っています。各関数をコピーして新しいバージョンをサポートすることは非常に難しく、そのようなコードを維持することは不可能です。

私が知っていることとして、goにはジェネリックがないため、2つの異なるタイプをサポートするには、インターフェースを使用するしかありません。しかし、さまざまなタイプのパラメーターと戻り値を持つメソッドに直面しているので、このシナリオ用に設計する方法がわかりません。

3
dotslashlu

1つの方法は、次のように示すことができます。ここで私は自分のタイプを知っているので、reflectパッケージを使用して値を取得し、面積を計算します。 playground で実行できます。チェックアウト reflect パッケージはこちら


import (
    "fmt"
    "reflect"
)

type shape interface {
    area(interface{}, interface{}) interface{}
}

type rect struct{}
type tri struct{}

func (r rect)area(a,b interface{}) interface{} {
    fmt.Println(reflect.ValueOf(r).Type(), reflect.ValueOf(b).Kind())

    lenf := reflect.ValueOf(a).Float()
    widthf := reflect.ValueOf(b).Float()

    return lenf * widthf
}

func (t tri)area(a,b interface{}) interface{} {
    l := reflect.ValueOf(a).Int()
    h := reflect.ValueOf(b).Int()

    return h * l
}

func main() {
    r := rect{}
    t := tri{}
    fmt.Println("Area of rectangle:", r.area(4.5, 4.0))
    fmt.Println("Area of triangle:", t.area(4, 4))
}

したがって、あなたの場合、DeploymentInterfaceインターフェースは次のようになります。

type DeploymentInterface interface {
    Create(interface{}) (interface{}, error)
    Update(interface{}) (interface{}, error)
    UpdateStatus(interface{}) (interface{}, error)
}
3
asr9