dsvd407787736
2018-02-07 08:36
浏览 104
已采纳

动态类型的结构

I am learning Go at the moment and I write a small project with some probes which report to a internal Log. I have a basic probe and I want create new probes extending the basic probe.

I want save the objects in an array/slice LoadedProbes.

type LoadableProbe struct {
    Name   string
    Probe  Probe
    Active bool
}

var LoadableProbes []LoadableProbe

The basic probe struct is:

type ProbeModule struct {
    version   VersionStruct
    name      string
    author    string
    log       []internals.ProbeLog
    lastcall  time.Time
    active    bool
}

func (m *ProbeModule) New(name string, jconf JsonConfig) {
    // read jsonConfig 
}
func (m *ProbeModule) Exec() bool {
    // do some stuff
    return true
}

func (m *ProbeModule) String() string {
    return m.name + " from " + m.author
}

func (m *ProbeModule) GetLogCount() int {
    return len(m.log)
}
[...]

I am using this basic struct for other probes, for example:

type ShellProbe struct {
    ProbeModule
}

func (s *ShellProbe) New(name string, jconf JsonConfig) {
    s.ProbeModule.New(name, jconf)
    fmt.Println("Hello from the shell")
}

func (s *ShellProbe) Exec() bool {
    // do other stuff
    return true
}

during Init() I call the following code:

func init() {
    RegisterProbe("ShellProbe", ShellProbe{}, true)
}

func RegisterProbe(name string, probe Probe, state bool) {
    LoadableProbes = append(LoadableProbes, LoadableProbe{name, probe, state})
}

The Problem is now that I can't add the type Shellprobe the the LoadableProbe struct, which expects a Probe struct.

My idea was to use interface{} instead the Probe struct in the Loadable Probe struct. But when I call the New() method of the Probe object:

for _, p := range probes.LoadableProbes {
    probe.Probe.New(probe.Name, jconf)
}

But I got the error: p.Probe.New undefined (type interface {} is interface with no methods)

how can I solve this problem?

图片转代码服务由CSDN问答提供 功能建议

此刻我正在学习Go,我编写了一个包含一些探针的小项目,这些探针向内部Log报告。 我有一个基础探针,我想创建扩展基础探针的新探针。

我想将对象保存在数组/切片LoadedProbes中。

   type LoadableProbe struct {
名称字符串
探针探针
活动布尔
} 
 
var LoadableProbes [] LoadableProbe 
   
 
 

基本探针 结构是:

 类型ProbeModule结构{
版本VersionStruct 
名称字符串
作者字符串
日志[] internals.ProbeLog 
上次调用时间。时间
有效 bool 
} 
 
func(m * ProbeModule)New(名称字符串,jconf JsonConfig){
 //读取jsonConfig 
} 
func(m * ProbeModule)Exec()bool {
 //做一些事情 
返回true 
} 
 
func(m * ProbeModule)String()字符串{
返回m.name +“ from” + m.author 
} 
 
func(m * ProbeModule)GetLogCount()  int {
 return len(m.log)
} 
 [...] 
   
 
 

例如,我正在将此基本结构用于其他探针 :

 类型ShellProbe struct {
概率 eModule 
} 
 
func(s * ShellProbe)新建(名称字符串,jconf JsonConfig){
 s.ProbeModule.New(name,jconf)
 fmt.Println(“来自外壳的Hello”)
}  
 
func(s * ShellProbe)Exec()bool {
 //做其他事情
返回true 
} 
   
 
 

调用以下代码:

  func init(){
 RegisterProbe(“ ShellProbe”,ShellProbe {},true)
} 
 
func RegisterProbe(名称字符串,  probe探针,状态布尔){
 LoadableProbes = append(LoadableProbes,LoadableProbe {名称,探针,状态})
} 
   
 
 

现在的问题是我 无法将类型Shellprobe添加到LoadableProbe结构中,该结构需要一个Probe结构。

我的想法是使用Interface {}代替Loadable Probe结构中的Probe结构。 但是当我调用Probe对象的New()方法时:

  for _,p:=范围probes.LoadableProbes {
 probe.Probe.New(probe.Name  ,jconf)
} 
   
 
 

但是我得到了错误:p.Probe.New未定义(类型interface {}是没有方法的接口)

如何解决此问题?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • duanlu9970 2018-02-07 09:14
    已采纳

    If you will have common data fields in each probe type, you might consider using Probe as a concrete base type defining your base data fields and base methods, and using a new ProbeInterface interface as an abstract base type defining common expected method signatures to allow you to pass around / collect / manage different specialized probe types.

    You would embed Probe into each specialized probe type, and methods and fields would be promoted according to rules of embedding. It looks like you're familiar with embedding in general, but the details are worth reviewing in the "Embedding" section of Effective Go if you haven't looked at it recently.

    You could override Probe methods in specialized probe types to execute type-specific code.

    It might look something like this:

    type ProbeInterface interface {
         New()
         Exec() bool
         // whatever other methods are common to all probes
    }
    
    type Probe struct {
        // whatever's in a probe
    }
    
    func (p *Probe) New() {
        // init stuff
    }
    
    func (p *Probe) Exec() bool {
        // exec stuff
        return true
    }
    
    // Probe's methods and fields are promoted to ShellProbe according to the rules of embedding
    type ShellProbe struct {
        Probe
        // any specialized ShellProbe fields
    }
    
    // override Probe's Exec() method to have it do something ShellProbe specific.
    func (sp *ShellProbe) Exec() bool {
        // do something ShellProbe-ish
        return true
    }
    
    type LoadableProbe struct {
        Name        string
        P           ProbeInterface
        Active      bool
    }
    
    func RegisterProbe(name string, probe ProbeInterface, state bool) {
        LoadableProbes = append(LoadableProbes, LoadableProbe{name, probe, state})
    }
    
    点赞 打赏 评论
  • duanmu0834 2018-02-07 08:46

    There are different approaches to your question.

    The most direct answer would be: You need to convert your interface{} to a concrete type before calling any methods on it. Example:

    probe.Probe.(ShellProbe).New(...)
    

    But this is a really confusing API to use.

    A better approach is probably to re-think your entire API. It's hard to do this level of design thinking with the limited information you've provided.

    I don't know whether this will work for you, but a common pattern is to define an interface:

    type Probe interface {
        New(string, JsonConfig)
        Exec() bool
        // ... etc
    }
    

    Then make all of your probe types implement the interface. Then use that interface instead of interface{}, as you initially did:

    type LoadableProbe struct {
        Name   string
        Probe  Probe
        Active bool
    }
    

    Then your syntax should work again, because the Probe interface includes a New method.

    probe.Probe.New(...)
    
    点赞 打赏 评论

相关推荐 更多相似问题