将方法添加到嵌套的导出结构中

时间:2018-11-02 14:59:22

标签: go

我想在导出结构中使用的嵌套导出结构中添加一个方法。

我有一个ldap.Search().Entries返回的[]*ldap.Entry类型

ldap.Entry类型由Attributes []*EntryAttribute组成。我的目标是在ldap.EntryAttribute中添加一个额外的方法,例如MarshalJSON

我可以直接在ldap包中添加一个额外的代码,它将按预期工作。但这是一种肮脏的方式:

// EntryAttribute holds a single attribute
type newEntryAttribute struct {
        // Name is the name of the attribute
        Name string
        // Values contain the string values of the attribute
        Values []string
        // ByteValues contain the raw values of the attribute
        ByteValues [][]byte
}

// Print outputs a human-readable description
func (e EntryAttribute) MarshalJSON() ([]byte, error) {
        b := newEntryAttribute(e)
        b.ByteValues = nil
        return json.Marshal(b)
}

我该如何以更优雅的方式做到这一点?

2 个答案:

答案 0 :(得分:1)

最接近的方法是根据您自己的类型创建方法,该方法将嵌入EntryAttribute类型。像这样:

package mine

import "github.com/go-ldap/ldap""

type EntryAttribute {
    ldap.EntryAttribute
}

func (e EntryAttribute) MarshalJSON() ([]byte, error) {
    // ...
}

但是,在程序中的任何地方,您必须使用您的类型,而不是原始类型。

答案 1 :(得分:-1)

到目前为止,我已经找到以下解决方案。它不优雅,但不需要修改程序包。

type myEntry struct {
        *ldap.Entry
        Attributes []*myEntryAttribute
}

type myEntryAttribute struct {
        *ldap.EntryAttribute
}

func (a *myEntryAttribute) MarshalJSON() ([]byte, error) {
        return json.Marshal(struct {
                Name   string
                Values []string 
        }{Name: a.Name, Values: a.Values})
}

func ldapEntry2myEntry(t interface{}) interface{} {
        switch e := t.(type) {
        case []*ldap.Entry:
                var res []interface{}
                for _, v := range e {
                        res = append(res, ldapEntry2myEntry(v))
                }
                return res
        case *ldap.Entry:
                var att []*myEntryAttribute
                for _, a := range e.Attributes {
                        att = append(att, &myEntryAttribute{a})
                }
                return &myEntry{e, att}
        }
        return nil
}

... ... ...

data, err := json.Marshal(ldapEntry2myEntry(sr.Entries))
if err != nil {
        log.Fatal("error")
}
fmt.Printf("%s\n", data)

// or only one element

data, err := json.Marshal(ldapEntry2myEntry(sr.Entries[0]))
if err != nil {
        log.Fatal("error")
}
fmt.Printf("%s\n", data)