Access to the map with a tuple key on partial key - go

I have a map with tuple key {int, string}:
NWKey struct {
deviceId int64
interfaceType string
}
m = make(map[NWKey]int, 0)
I need to get map's elements for partial key, something like this {int, *}, where * means this part of key isn't matter. Is it possible in goland to do it& If yes please explain how to do it.

It is not possible with just a direct lookup. One problem is that there could exist multiple keys with the same deviceId.
Instead what you would need to do is to iterate over your map and find the with the correct id. For example:
wantedId := 532
for key, value := range m {
if key.deviceId == wantedId {
// Do what you want to do here
}
}
However, this does partly remove the use case for maps. You could reconsider refactoring your struct to only have the deviceId as key (map[int64]int), but this might not work for you.

Related

Go Struct data identifier/authenticity

How to make a struct with fields and values unique for the data it holds?, The order of fields doesn't matter, what matter is the values of struct's fields must be exactly the same in order to be authenticated/identified.
Currently I used SHA256 hashing method. I hash the struct with the said data. For the next incoming data with same struct, I hash again to verify against previously hashed data to check if it was existed before.
So, let's say:
type F struct {
A string
B string
C interface{}
}
The value of C can be arbitrary, can be simple types(string, int,etc), map, or struct(e.g. nested json). How to make every data passed to F struct made unique. Have I already doing right using SHA256 on the struct?, I'm worry about the C value might affect the value of hash.

Getting error while access the struct type of array element as undefined (type []ParentIDInfo has no field or method PCOrderID)

I am new to golang and I have one issue which I think community can help me to solve it.
I have one data structure like below
type ParentIDInfo struct {
PCOrderID string `json:"PCorderId",omitempty"`
TableVarieties TableVarietyDC `json:"tableVariety",omitempty"`
ProduceID string `json:"PRID",omitempty"`
}
type PCDCOrderAsset struct {
PcID string `json:"PCID",omitempty"`
DcID string `json:"DCID",omitempty"`
RequiredDate string `json:"requiredDate",omitempty"`
Qty uint64 `json:"QTY",omitempty"`
OrderID string `json:"ORDERID",omitempty"`
Status string `json:"STATUS",omitempty"`
Produce string `json:"Produce",omitempty"`
Variety string `json:"VARIETY",omitempty"`
Transports []TransportaionPCDC `json:"Transportaion",omitempty"`
ParentInfo []ParentIDInfo `json:"ParentInfo",omitempty"`
So I have issue to access the PCOrderID which inside the []ParentIDInfo . I have tried below however I getting error as "pcdcorder.ParentInfo.PCOrderID undefined (type []ParentIDInfo has no field or method PCOrderID)"
keyfarmercas = append(keyfarmercas, pcdcorder.ParentInfo.PCOrderID)
Any help will be very good
Thanks in advance
PCDCOrderAsset.ParentInfo is not a struct, it does not have a PCOrderID field. It's a slice (of element type ParentIDInfo), so its elements do, e.g. pcdcorder.ParentInfo[0].PCOrderID.
Whether this is what you want we can't tell. pcdcorder.ParentInfo[0].PCOrderID gives you the PCOrderID field of the first element of the slice. Based on your question this may or may not be what you want. You may want to append all IDs (one from each element). Also note that if the slice is empty (its length is 0), then pcdcorder.ParentInfo[0] would result in a runtime panic. You could avoid that by first checking its length and only index it if its not empty.
In case you'd want to add ids of all elements, you could use a for loop to do that, e.g.:
for i := range pcdorder.ParentInfo {
keyfarmercas = append(keyfarmercas, pcdcorder.ParentInfo[i].PCOrderID)
}

Go equivalent of Python's Dictionary

I am looking for a way to store multiple values for each key (just like we can in python using dictionary) using Go.
Is there a way this can be achieved in Go?
Based on your response in comments I would suggest something like the following using a struct (though if you are only interested in a single value like name for each item in your slice then you could just use a map[int][]string{}
type Thing struct {
name string
age int
}
myMap := map[int][]Thing{}
If you want to add things then you just do...
myMap[100] = append(myMap[100], Thing{"sberry": 37})
Or if you want to create it in place:
myMap := map[int][]Thing{
100: []Thing{Thing{"sberry", 37}},
2: []Thing{Thing{"johndoe", 22}},
}
EDIT: Adding a "nameIn" function based on comments as demo:
func nameIn(things []Thing, name string) bool {
for _, thing := range things {
if thing.name == name {
return true
}
}
return false
}
if nameIn(myMap[100], "John") {
...
If the slices are really big and speed is concern then you could keep a reverse lookup map like map[string]int where an entry would be John: 100, but you will need to most likely use some user defined functions to do your map modifications so it can change the reverse lookup as well. This also limits you by requiring unique names.
Most likely the nameIn would work just fine.
In go, the key/value collection is called a map. You create it with myMap := map[keyType]valType{}
Usually something like mapA := map[string]int{}. If you want to store multiple values per key, perhaps something like:
mapB := map[string][]string{} where each element is itself a slice of strings. You can then add members with something like:
mapB["foo"] = append(mapB["foo"], "fizzbuzz")
For a great read see Go maps in action

Why do I get a "cannot assign" error when setting value to a struct as a value in a map? [duplicate]

This question already has answers here:
Accessing struct fields inside a map value (without copying)
(2 answers)
Closed 7 years ago.
New to Go. Encountered this error and have had no luck finding the cause or the rationale for it:
If I create a struct, I can obviously assign and re-assign the values no problem:
type Person struct {
name string
age int
}
func main() {
x := Person{"Andy Capp", 98}
x.age = 99
fmt.Printf("age: %d\n", x.age)
}
but if the struct is one value in a map:
type Person struct {
name string
age int
}
type People map[string]Person
func main() {
p := make(People)
p["HM"] = Person{"Hank McNamara", 39}
p["HM"].age = p["HM"].age + 1
fmt.Printf("age: %d\n", p["HM"].age)
}
I get cannot assign to p["HM"].age. That's it, no other info. http://play.golang.org/p/VRlSItd4eP
I found a way around this - creating an incrementAge func on Person, which can be called and the result assigned to the map key, eg p["HM"] = p["HM"].incrementAge().
But, my question is, what is the reason for this "cannot assign" error, and why shouldn't I be allowed to assign the struct value directly?
p["HM"] isn't quite a regular addressable value: hashmaps can grow at runtime, and then their values get moved around in memory, and the old locations become outdated. If values in maps were treated as regular addressable values, those internals of the map implementation would get exposed.
So, instead, p["HM"] is a slightly different thing called a "map index expression" in the spec; if you search the spec for the phrase "index expression" you'll see you can do certain things with them, like read them, assign to them, and use them in increment/decrement expressions (for numeric types). But you can't do everything. They could have chosen to implement more special cases than they did, but I'm guessing they didn't just to keep things simple.
Your approach seems good here--you change it to a regular assignment, one of the specifically-allowed operations. Another approach (maybe good for larger structs you want to avoid copying around?) is to make the map value a regular old pointer that you can modify the underlying object through:
package main
import "fmt"
type Person struct {
name string
age int
}
type People map[string]*Person
func main() {
p := make(People)
p["HM"] = &Person{"Hank McNamara", 39}
p["HM"].age += 1
fmt.Printf("age: %d\n", p["HM"].age)
}
The left side of the assignment must b "addressable".
https://golang.org/ref/spec#Assignments
Each left-hand side operand must be addressable, a map index expression, or (for = assignments only) the blank identifier.
and https://golang.org/ref/spec#Address_operators
The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array.
as #twotwotwo's comment, p["HM"] is not addressable.
but, there is no such definition show what is "addressable struct operand" in the spec. I think they should add some description for it.

Check if value exists in enum

I have created a strict like the following in my app:
type Datatype int8
const (
user Datatype = iota
address
test
)
var datatypes = [...]string{"User", "Address", "Test"}
func (datatype Datatype) String() string {
return datatypes[datatype]
}
I would like to be able to validate a value passed via a command-line flag against this enum.
I thought I had seen something like dtype == Datatype being used, but I am apparently sorely mistaken.
If this is not possible I can go the route of putting these values in an array. However, I feel the enum approach is more elegant.
From your code sample it looks like you are trying to see if a map (rather than a struct) contains a particular key.
If so, the answer is here
A two-value assignment tests for the existence of a key:
i, ok := m["route"]
In this statement, the first value (i) is assigned
the value stored under the key "route". If that key doesn't exist, i
is the value type's zero value (0). The second value (ok) is a bool
that is true if the key exists in the map, and false if not.
To test for a key without retrieving the value, use an underscore in
place of the first value:
_, ok := m["route"]

Resources