来自我的包外部的结构的多态性
Polymorphism with struct from outside my package
我正在尝试构建一种方法,使用 Kubernetes client-go 库,获取并 returns 给定 *metav1.OwnerReference
的实际资源。我有这个:
func fetchResource(ref *metav1.OwnerReference, options *RequestOptions) (*metav1.ObjectMeta, error) {
switch ref.Kind {
case "ReplicaSet":
return options.Clientset.AppsV1().ReplicaSets(options.Namespace).Get(options.Context, ref.Name, metav1.GetOptions{})
case "Deployment":
return options.Clientset.AppsV1().Deployments(options.Namespace).Get(options.Context, ref.Name, metav1.GetOptions{})
case "Job":
fallthrough
// more stuff...
default:
return nil, nil
}
}
此代码无法编译,因为:
cannot use options.Clientset.AppsV1().ReplicaSets(options.Namespace).Get(options.Context, ref.Name, (metav1.GetOptions literal)) (value of type *"k8s.io/api/apps/v1".ReplicaSet) as *"k8s.io/apimachinery/pkg/apis/meta/v1".ObjectMeta value in return statement
我的猜测是,由于 documentation 表示基本上所有资源都嵌入了 metav1.ObjectMeta
,我可以将其用作 return 类型。
我尝试创建并 returning 一个 interface
,但意识到我无法为包外的类型实现它:
type K8sResource interface {
Name() string
Kind() string
OwnerReferences() []metav1.OwnerReference
}
func (pod *corev1.Pod) Name() string {
return pod.Name
}
func (pod *corev1.Pod) Kind() string {
return pod.Kind
}
func (pod *corev1.Pod) OwnerReferences() []metav1.OwnerReference {
return pod.OwnerReferences
}
此代码无法编译,因为:
invalid receiver *"k8s.io/api/core/v1".Pod (type not defined in this package)
这里惯用的正确解决方案是什么?
如果您想 return 导入的类型作为它们尚未实现的接口,您可以将它们包装在实现它的类型中。
例如:
type K8sResource interface {
Name() string
Kind() string
OwnerReferences() []metav1.OwnerReference
}
type replicaSet struct{ *v1.ReplicaSet }
func (s replicaSet) Name() string {
return s.ReplicaSet.Name
}
func (s replicaSet) Kind() string {
return s.ReplicaSet.Kind
}
func (s replicaSet) OwnerReferences() []metav1.OwnerReference {
return s.ReplicaSet.OwnerReferences
}
func fetchResource(ref *metav1.OwnerReference, options *RequestOptions) (K8sResource, error) {
switch ref.Kind {
case "ReplicaSet":
res, err := options.Clientset.AppsV1().ReplicaSets(options.Namespace).Get(options.Context, ref.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
return replicaSet{res}, nil // wrap it up
case "Pod":
res, err := options.Clientset.AppsV1().Pods(options.Namespace).Get(options.Context, ref.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
return pod{res}, nil // wrap it up
case "Job":
fallthrough
// more stuff...
default:
return nil, nil
}
}
我正在尝试构建一种方法,使用 Kubernetes client-go 库,获取并 returns 给定 *metav1.OwnerReference
的实际资源。我有这个:
func fetchResource(ref *metav1.OwnerReference, options *RequestOptions) (*metav1.ObjectMeta, error) {
switch ref.Kind {
case "ReplicaSet":
return options.Clientset.AppsV1().ReplicaSets(options.Namespace).Get(options.Context, ref.Name, metav1.GetOptions{})
case "Deployment":
return options.Clientset.AppsV1().Deployments(options.Namespace).Get(options.Context, ref.Name, metav1.GetOptions{})
case "Job":
fallthrough
// more stuff...
default:
return nil, nil
}
}
此代码无法编译,因为:
cannot use options.Clientset.AppsV1().ReplicaSets(options.Namespace).Get(options.Context, ref.Name, (metav1.GetOptions literal)) (value of type *"k8s.io/api/apps/v1".ReplicaSet) as *"k8s.io/apimachinery/pkg/apis/meta/v1".ObjectMeta value in return statement
我的猜测是,由于 documentation 表示基本上所有资源都嵌入了 metav1.ObjectMeta
,我可以将其用作 return 类型。
我尝试创建并 returning 一个 interface
,但意识到我无法为包外的类型实现它:
type K8sResource interface {
Name() string
Kind() string
OwnerReferences() []metav1.OwnerReference
}
func (pod *corev1.Pod) Name() string {
return pod.Name
}
func (pod *corev1.Pod) Kind() string {
return pod.Kind
}
func (pod *corev1.Pod) OwnerReferences() []metav1.OwnerReference {
return pod.OwnerReferences
}
此代码无法编译,因为:
invalid receiver *"k8s.io/api/core/v1".Pod (type not defined in this package)
这里惯用的正确解决方案是什么?
如果您想 return 导入的类型作为它们尚未实现的接口,您可以将它们包装在实现它的类型中。
例如:
type K8sResource interface {
Name() string
Kind() string
OwnerReferences() []metav1.OwnerReference
}
type replicaSet struct{ *v1.ReplicaSet }
func (s replicaSet) Name() string {
return s.ReplicaSet.Name
}
func (s replicaSet) Kind() string {
return s.ReplicaSet.Kind
}
func (s replicaSet) OwnerReferences() []metav1.OwnerReference {
return s.ReplicaSet.OwnerReferences
}
func fetchResource(ref *metav1.OwnerReference, options *RequestOptions) (K8sResource, error) {
switch ref.Kind {
case "ReplicaSet":
res, err := options.Clientset.AppsV1().ReplicaSets(options.Namespace).Get(options.Context, ref.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
return replicaSet{res}, nil // wrap it up
case "Pod":
res, err := options.Clientset.AppsV1().Pods(options.Namespace).Get(options.Context, ref.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
return pod{res}, nil // wrap it up
case "Job":
fallthrough
// more stuff...
default:
return nil, nil
}
}