Golang如何在Unmarshalling期间FIFO排序地图

时间:2016-11-03 23:31:24

标签: go mapping fifo

所以我从阅读中了解到,地图在Go中是故意无序的,但是它们提供了很多好处,我想用这个问题来解决这个问题。我的问题是我如何订购地图FIFO样式?是否值得尝试实现这一目标?具体来说,我希望这样做,以便我可以解组成一组希望脱离接口的结构。

目前我有:

type Package struct {
    Account   string
    Jobs      []*Jobs
    Libraries map[string]string
}

type Jobs struct {
// Name of the job
     JobName string `mapstructure:"name" json:"name" yaml:"name" toml:"name"`
// Type of the job. should be one of the strings outlined in the job struct (below)
     Job *Job `mapstructure:"job" json:"job" yaml:"job" toml:"job"`
// Not marshalled
     JobResult string
// For multiple values
     JobVars []*Variable
}

type Job struct {
// Sets/Resets the primary account to use
    Account *Account `mapstructure:"account" json:"account" yaml:"account" toml:"account"`
// Set an arbitrary value
    Set *Set `mapstructure:"set" json:"set" yaml:"set" toml:"set"`
// Contract compile and send to the chain functions
    Deploy *Deploy `mapstructure:"deploy" json:"deploy" yaml:"deploy" toml:"deploy"`
// Send tokens from one account to another
    Send *Send `mapstructure:"send" json:"send" yaml:"send" toml:"send"`
// Utilize eris:db's native name registry to register a name
    RegisterName *RegisterName `mapstructure:"register" json:"register" yaml:"register" toml:"register"`
// Sends a transaction which will update the permissions of an account. Must be sent from an account which
// has root permissions on the blockchain (as set by either the genesis.json or in a subsequence transaction)
    Permission *Permission `mapstructure:"permission" json:"permission" yaml:"permission" toml:"permission"`
// Sends a bond transaction
    Bond *Bond `mapstructure:"bond" json:"bond" yaml:"bond" toml:"bond"`
// Sends an unbond transaction
    Unbond *Unbond `mapstructure:"unbond" json:"unbond" yaml:"unbond" toml:"unbond"`
// Sends a rebond transaction
    Rebond *Rebond `mapstructure:"rebond" json:"rebond" yaml:"rebond" toml:"rebond"`
// Sends a transaction to a contract. Will utilize eris-abi under the hood to perform all of the heavy lifting
    Call *Call `mapstructure:"call" json:"call" yaml:"call" toml:"call"`
// Wrapper for mintdump dump. WIP
    DumpState *DumpState `mapstructure:"dump-state" json:"dump-state" yaml:"dump-state" toml:"dump-state"`
// Wrapper for mintdum restore. WIP
    RestoreState *RestoreState `mapstructure:"restore-state" json:"restore-state" yaml:"restore-state" toml:"restore-state"`
// Sends a "simulated call" to a contract. Predominantly used for accessor functions ("Getters" within contracts)
    QueryContract *QueryContract `mapstructure:"query-contract" json:"query-contract" yaml:"query-contract" toml:"query-contract"`
// Queries information from an account.
    QueryAccount *QueryAccount `mapstructure:"query-account" json:"query-account" yaml:"query-account" toml:"query-account"`
// Queries information about a name registered with eris:db's native name registry
    QueryName *QueryName `mapstructure:"query-name" json:"query-name" yaml:"query-name" toml:"query-name"`
// Queries information about the validator set
    QueryVals *QueryVals `mapstructure:"query-vals" json:"query-vals" yaml:"query-vals" toml:"query-vals"`
// Makes and assertion (useful for testing purposes)
    Assert *Assert `mapstructure:"assert" json:"assert" yaml:"assert" toml:"assert"`
}

我想要做的是让作业包含一个字符串到Job的映射并消除job字段,同时保持它们从配置文件中放入的顺序。 (目前正在使用毒蛇)。任何和所有关于如何实现这一点的建议都是受欢迎的。

2 个答案:

答案 0 :(得分:4)

您需要将密钥保存在单独的切片中并使用它。

type fifoJob struct {
    m map[string]*Job
    order []string
    result []string
    // Not sure where JobVars will go. 
}

func (str *fifoJob) Enqueue(key string, val *Job) {
    str.m[key] = val
    str.order = append(str.order, key)
}

func (str *fifoJob) Dequeue() {
    if len(str.order) > 0 {
        delete(str.m, str.order[0])
        str.order = str.order[1:]
    }
}

无论如何,如果您使用viper,您可以使用类似上面定义的fifoJob结构的内容。另请注意,我在这里做了一些假设。

type Package struct {
    Account   string
    Jobs      *fifoJob
    Libraries map[string]string
}

var config Package
config.Jobs = fifoJob{}
config.Jobs.m = map[string]*Job{}

// Your config file would need to store the order in an array.
// Would've been easy if viper had a getSlice method returning []interface{}
config.Jobs.order = viper.GetStringSlice("package.jobs.order") 

for k,v := range viper.GetStringMap("package.jobs.jobmap") {

    if job, ok := v.(Job); ok {
        config.Jobs.m[k] = &job
    }
}

代表

PS:你在问题中提供了太多不相关的细节。我要的是MCVE

答案 1 :(得分:0)

地图本质上是无序的,但您可以用钥匙填充切片。然后,您可以对切片进行测距并根据需要对其进行排序。您可以使用[i]。

提取切片中的特定元素

查看第170,203或204页的一些很好的例子:

Programming in Go