2016-11-03 9 views
1

So weiß ich aus dem Lesen, dass Maps in Go absichtlich ungeordnet sind, aber sie bieten eine Menge Vorteile, die ich für dieses Problem, an dem ich arbeite, verwenden möchte. Meine Frage ist, wie könnte ich einen Karten-FIFO-Stil bestellen? Ist es überhaupt einen Versuch wert, dies zu erreichen? Genauer gesagt, ich versuche es so zu machen, dass ich in eine Reihe von Strukturen entmaren kann, die hoffentlich von einer Schnittstelle sind.Golang Wie man FIFO bestellt Eine Karte beim Unmarshalling

Zur Zeit habe ich:

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"` 
} 

Was ich möchte, ist zu tun, Arbeitsplätze haben Karte von String-Job enthalten und die Beseitigung des job Feldes, während Aufrechterhaltung der Ordnung, in der sie von der config in Verkehr gebracht wurden Datei. (Derzeit mit Viper). Alle Vorschläge, wie dies zu erreichen ist, sind willkommen.

+0

Verwandte/mögliche Duplikat [Warum kann nicht gehen Iterierte Karten in Auftrag?] (Http://stackoverflow.com/questions/28930416/why-cant-go-iterate-maps-in-insertion-order); und [Golang-Karte in der Reihenfolge der Bereichsschleife] (http://stackoverflow.com/questions/39450120/golang-map-in-order-range-loop). – icza

Antwort

4

Sie müssten die Tasten in einem separaten Slice halten und damit arbeiten.

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:] 
    } 
} 

Sowieso, wenn Sie viper verwenden können Sie so etwas wie die fifoJob struct oben definiert verwenden. Beachten Sie auch, dass ich hier einige Annahmen mache.

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 
    } 
} 

für

PS: Sie geben zu viele irrelevante Details in Ihrer Frage. Ich habe nach einem MCVE gefragt.

+0

Danke für die schnelle Antwort. Es scheint, dass meine Hoffnung, etwas für eine json-Liste, die iterables Mapping durch FIFO ermöglichen würde, leicht entzifferbar zu machen, nicht einfach wird und wahrscheinlich atm am besten ignoriert. Aber danke. Das hat sehr geholfen. –

+0

Es wäre möglich, wenn Sie die 'json.Unmarshaler'-Schnittstelle implementieren. Aber wie leicht es wäre, hängt von Ihrem genauen Problem ab. –

+2

Beachten Sie, dass bei einer großen Karte die Sortierung der Schlüssel verlangsamt wird. Ich habe dieses Problem mit einer Hashmap in der Größenordnung von 10 Millionen Einträgen gelöst und musste diesen Ansatz überdenken. Am Ende funktionierte eine kombinierte Hashmap- und Warteschlangen-Datenstruktur wie ein Zauber. – johnzachary

0

Karten sind von Natur aus ungeordnet, aber Sie können stattdessen eine Scheibe mit Ihren Schlüsseln füllen. Dann können Sie über Ihre Scheibe reichen und sie sortieren, wie Sie möchten. Sie können bestimmte Elemente in Ihrem Slice mit [i] herausziehen.

Check out Seiten 170, 203, oder 204 von einigen großen Beispiele:

Programming in Go