Условные / дополнительные поля в типе структуры - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть Node тип структуры, подобный этому:

package tree

// Enum for node category
type Level int32
const (
    Leaf Level = iota + 1
    Branch
    Root
)

type Node struct {
    Children []*Node
    Parent   *Node
    X        float32
    Y        float32
    Z        float32
    Dim      float32
    Category Level
    LeafPenetration float32 // Needed only if category is "Leaf"
    RootPadDim float32      // Needed only if category is "Root"
}

У меня есть два поля Node, которые являются необязательными и необходимы только в зависимости от поля category:

    leafPenetration float32 // Needed only if category is "Leaf"
    rootPadDim float32      // Needed only if category is "Root"

С текущей реализацией Node все в порядке? Какова наилучшая практика для таких дополнительных / условных полей внутри структурных типов?

Ответы [ 3 ]

3 голосов
/ 28 апреля 2020

По умолчанию поля инициализируются нулевым значением типа - в случае float32 это 0. Чтобы избежать этого, обычно используются указатели, для полей, которые являются необязательными, например:

type Node struct {
    Children []*Node
    Parent   *Node
    X        float32
    Y        float32
    Z        float32
    Dim      float32
    Category Level

    // Optional fields
    LeafPenetration *float32  // Needed only if category is "Leaf"
    RootPadDim      *float32  // Needed only if category is "Root"
}

По умолчанию для полей указателя будет nil.

0 голосов
/ 30 апреля 2020

Я использовал очень упрощенный подход:

package tree

// Enum for node category
type Level int32
const (
    Leaf Level = iota + 1
    Branch
    Root
)

type Node struct {
    Category Level
    Parent   *Node
    X        float32
    Y        float32
    Z        float32
    Dim      float32

    RootT  float32 // Root thickness
    RootD  float32 // Root diameter
    RootBR float32 // Root bezel ratio of top-bottom, i.e. top D is larger by this much
    LeafP  float32 // Leaf penetration
}

func NewNode(cat Level, parent *Node, x, y, z, dim float32) *Node {
    n := &Node{
        Category: cat,
        Parent:   parent,
        X:        x,
        Y:        y,
        Z:        z,
        Dim:      dim,
    }
    switch n.Category {
    case Leaf:
        n.LeafP = float32(0.3)
    case Root:
        n.RootT = float32(2)
        n.RootD = float32(30)
        n.RootBR = float32(1.08)
    }
    return n
}
0 голосов
/ 28 апреля 2020

Является ли хорошей идеей следовать этому руководству ?

Например, иметь такой тип Node:

package tree

// Enum for node category
type Level int32
const (
    Leaf Level = iota + 1
    Branch
    Root
)

type Node struct {
    Children []*Node
    Parent   *Node
    X        float32
    Y        float32
    Z        float32
    Dim      float32
    Category Level
    // https://github.com/uber-go/guide/blob/master/style.md#functional-options
    Opts []Option
}

Реализация таких опций:

type options struct {
    penetration float32 // Needed only if category is "Leaf"
    base        float32 // Needed only if category is "Root"
}

type Option interface {
    apply(*options)
}

// penetration option
type penetrationOption float32

func (p penetrationOption) apply(opts *options) {
    opts.penetration = float32(p)
}

func WithPenetrationOption(p float32) Option {
    return penetrationOption(p)
}

// base option
type baseOption float32

func (b baseOption) apply(opts *options) {
    opts.base = float32(b)
}

func WithBaseOption(b float32) Option {
    return baseOption(b)
}

При вышеуказанном подходе реализация становится слишком сложной. Однако это может быть расширено в будущем. Не уверен насчет его достоинства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...