func (n *node) GobDecode(buf []byte) error {
	r := bytes.NewBuffer(buf)
	decoder := gob.NewDecoder(r)
	if err := decoder.Decode(&n.nodes); err != nil {
		return err
	}
	if err := decoder.Decode(&n.keys); err != nil {
		return err
	}
	if err := decoder.Decode(&n.keysBytes); err != nil {
		return err
	}
	return decoder.Decode(&n.Node)
}
GobDecode decodes every member of node struct instance
package ctree
import (
	"bytes"
	"encoding/gob"
	"encoding/json"
	"fmt"
	log "github.com/sirupsen/logrus"
)
type ConfigTree struct {
	Debug bool
	root  *node
}
func New() *ConfigTree {
	return &ConfigTree{}
}
func (c *ConfigTree) log(s string) {
	if c.Debug {
		log.Print(s)
	}
}
func (c *ConfigTree) GobEncode() ([]byte, error) {
	w := new(bytes.Buffer)
	encoder := gob.NewEncoder(w)
	if c.root == nil {
		c.root = &node{}
	}
	if err := encoder.Encode(c.root); err != nil {
		return nil, err
	}
	return w.Bytes(), nil
}
func (c *ConfigTree) GobDecode(buf []byte) error {
	r := bytes.NewBuffer(buf)
	decoder := gob.NewDecoder(r)
	if err := decoder.Decode(&c.root); err != nil {
		return err
	}
	return nil
}
func (c *ConfigTree) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Root *node `json:"root"`
	}{
		Root: c.root,
	})
}
func (c *ConfigTree) Add(ns []string, inNode Node) {
	c.log(fmt.Sprintf("Adding %v at %s\n", inNode, ns))
	if len(ns) == 0 {
		c.log(fmt.Sprintln("ns is empty - returning with no change to tree"))
		return
	}
	f, remain := ns[0], ns[1:]
	c.log(fmt.Sprintf("first ns (%s) remain (%s)", f, remain))
	if c.root == nil {
		c.root = new(node)
		c.root.setKeys([]string{f})
		c.log(fmt.Sprintf("Root now = %v\n", c.root.keys))
		if len(remain) == 0 {
			c.log(fmt.Sprintf("adding node at root level\n"))
			c.root.Node = inNode
			return
		}
	} else {
		if f != c.root.keys[0] {
			panic("Can't add a new root namespace")
		}
	}
	c.root.add(remain, inNode)
}
type keyNode struct {
	Key []string
	Node
}
func (c *ConfigTree) GetAll() []keyNode {
	var ret []keyNode
	if c.root == nil {
		c.log(fmt.Sprintln("ctree: no root - returning nil"))
		return nil
	}
	return c.getAll(c.root, []string{}, &ret)
}
func (c *ConfigTree) getAll(node *node, key []string, res *[]keyNode) []keyNode {
	if len(node.keys) > 0 {
		if key != nil {
			key = append(key, node.keys[0])
		} else {
			key = []string{node.keys[0]}
		}
		if node.Node != nil {
			k := keyNode{
				Key:  key,
				Node: node.Node,
			}
			*res = append(*res, k)
		}
	}
	for _, child := range node.nodes {
		c.getAll(child, key, res)
	}
	return *res
}
func (c *ConfigTree) Get(ns []string) Node {
	c.log(fmt.Sprintf("Get on ns (%s)\n", ns))
	retNodes := new([]Node)
	if c.root == nil {
		c.log(fmt.Sprintln("ctree: no root - returning nil"))
		return nil
	}
	if len(c.root.keys) == 0 {
		return nil
	}
	rootKeyLength := len(c.root.keys)
	if len(ns) < rootKeyLength {
		c.log(fmt.Sprintln("ns less than root key length - returning nil"))
		return nil
	}
	match, remain := ns[:rootKeyLength], ns[rootKeyLength:]
	if bytes.Compare(nsToByteArray(match), c.root.keysBytes) != 0 {
		c.log(fmt.Sprintf("no match versus root key (match:'%s' != root:'%s')\n", string(nsToByteArray(match)), string(c.root.keysBytes)))
		return nil
	}
	c.log(fmt.Sprintf("Match root key (match:'%s' == root:'%s')\n", string(nsToByteArray(match)), string(c.root.keysBytes)))
	if c.root.Node != nil {
		c.log(fmt.Sprintf("adding root node (not nil) to nodes to merge (%v)\n", c.root.Node))
		*retNodes = append(*retNodes, c.root.Node)
	}
	c.log(fmt.Sprintf("children to get from (%d)\n", len(c.root.nodes)))
	for _, child := range c.root.nodes {
		childNodes := child.get(remain)
		*retNodes = append(*retNodes, *childNodes...)
	}
	if len(*retNodes) == 0 {
		return nil
	}
	c.log(fmt.Sprintf("nodes to merge count (%d)\n", len(*retNodes)))
	rn := (*retNodes)[0]
	for _, n := range (*retNodes)[1:] {
		rn = rn.Merge(n)
	}
	return rn
}
func (c *ConfigTree) Print() {
	c.root.print("")
}
type Node interface {
	Merge(Node) Node
}
type node struct {
	nodes     []*node
	keys      []string
	keysBytes []byte
	Node      Node
}
func (n *node) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Nodes     []*node  `json:"nodes"`
		Keys      []string `json:"keys"`
		KeysBytes []byte   `json:"keysbytes"`
		Node      Node     `json:"node"`
	}{
		Nodes:     n.nodes,
		Keys:      n.keys,
		KeysBytes: n.keysBytes,
		Node:      n.Node,
	})
}
func (n *node) GobEncode() ([]byte, error) {
	w := new(bytes.Buffer)
	encoder := gob.NewEncoder(w)
	if err := encoder.Encode(n.nodes); err != nil {
		return nil, err
	}
	if err := encoder.Encode(n.keys); err != nil {
		return nil, err
	}
	if err := encoder.Encode(n.keysBytes); err != nil {
		return nil, err
	}
	if err := encoder.Encode(&n.Node); err != nil {
		return nil, err
	}
	return w.Bytes(), nil
}