繁体   English   中英

结构类型中的条件/可选字段

[英]Conditional/optional fields in struct type

我有一个这样的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实现是否正常? 结构类型中此类可选/条件字段的最佳实践是什么?

默认情况下,字段初始化为类型的零值——在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

我最终使用了一种非常简化的方法:

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
}

遵循这个指南是个好主意吗?

例如具有此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)
}

使用上述方法,实现变得过于复杂。 但是,它可以在未来进一步扩展。 虽然不确定它的价值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM