2016-11-03 99 views
1

因此,我从阅读中了解到,Google地图在Go中是故意无序的,但它们提供了很多好处,我希望用于解决我正在处理的这个问题。我的问题是如何订购地图FIFO风格?试图做到这一点甚至值得吗?具体而言,我希望能够使它能够解组为一组希望脱离接口的结构。Golang如何先进先出在解组过程中订购地图

目前我有:

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领域,同时保持它们被从配置顺序放置文件。 (目前使用毒蛇)。任何和所有关于如何实现这一点的建议都值得欢迎。

+0

相关/可能重复(HTTP:/ /stackoverflow.com/questions/28930416/why-cant-go-iterate-maps-in-insertion-order);和[Golang映射顺序循环](http://stackoverflow.com/questions/39450120/golang-map-in-order-range-loop)。 – icza

回答

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

+0

感谢您的快速响应。看起来,我希望能够轻松地制作一个能够通过FIFO实现迭代映射的json列表,这不是一件容易的事情,而且可能最好忽略atm。但是,谢谢。这帮了很多。 –

+0

如果你实现'json.Unmarshaler'接口,那将是可能的。但是,这将是多么容易,取决于你确切的问题。 –

+2

请注意,如果您的地图很大,那么维护一个排序的按键列表会减慢速度。我用一个10M条目的散列图来解决这个问题,并且不得不重新考虑这种方法。最后,一个组合的散列表和队列数据结构就像一个魅力。 – johnzachary

0

地图本质上是无序的,但你可以用你的密钥来填充一个片。然后你可以在你的切片上排序并按照你喜欢的方式排序。你可以用[i]拉出切片中的特定元素。

退房页170,203,或者这样的一些很好的例子204:

Programming in Go

的[为什么不能进去插入顺序迭代地图?]