i’ve struct which responsible to parse data from yaml file
While this struct is working sometimes I got some newly fields which I need to parse
This is working
- name: test1
type: type
path: path
This is not
- name: test1
type: type
path: path
build-parameters:
maven-opts:
defines:
skipTests: true
This is the struct
type Modules struct {
Name string
Type string
Path string
Parameters Parameters `yaml:"build-parameters,omitempty"`
}
And the parameters is type of:
type Parameters map[string]string
How I should construct my struct to accept this build-parameters entries also?
This is the library I use
https://github.com/go-yaml/yaml
Your struct does not match the data structure. If Parameters is a map[string]string, it accepts key-value pairs where the key and value are both string. In your data, build-parameters contains an object, which contains an object, which contains a key-value pair.
You could either redefine Parameters to be map[string]interface{} and use type assertions, or you can define the entire structure, e.g.:
type Parameters struct {
MavenOpts struct {
Defines map[string]string
} `yaml:"maven-opts"`
}
If you use the empty interface, you'll have to use type assertions, which can get pretty cumbersome. For example:
if opts, ok := module.Parameters["maven-opts"].(map[string]interface{}); ok {
if defines,ok := opts["defines"].(map[string]interface{}); ok {
if skipTests,ok := defines["skipTests"].(bool); ok {
// skipTests is the bool value from the yaml
}
}
}
Related
I have the following struct that contains channels and a map for storage of data. I want to be able to pass that struct into functions in order to make use of those channels so that once they are triggered/have incoming messages, to use them in order to update the map that is associated with it.
I understand that maps by default are passed by reference when sent to various functions. Would this be the same case even when they are contained within a custom struct? How do i make sure that my entire struct is passed around to functions by reference in order to update Storage and also make use of its channels?
type CustomStrct struct {
Storage map[string]string
RetrieveChannel chan string
InsertChannel chan string
}
This is a constructor I have created for initialising a new instance of the struct:
func InitializeNewStore() CustomStrct {
newCustomStruct := CustomStrct {
Storage: make(map[string]string),
RetrieveChannel: make(chan Request),
InsertChannel: make(chan Request),
}
return newCustomStruct
}
Slices, maps and channels are pointer-like values in Go: copying a struct containing a channel copies a reference to the channel, not the channel itself:
a := CustomStrct{
RetrieveChannel: make(chan Request),
}
b := a
log.Println(a.RetrieveChannel == b.RetrieveChannel) // logs true
So it's quite fine to pass your struct either by value or by reference.
If you need to ensure that go vet will flag attempts to pass your struct by value, the simplest solution is to embed a sync.Mutex inside the struct:
type CustomStrct struct {
mu sync.Mutex
...
}
You don't need to actually use the mutex: just having it embedded in the struct will cause go vet to complain whenever you attempt to pass it by value.
I need to create a string to string map with flatbuffers in Rust similar to:
pub struct HashMapIndex {
keyword_by_filter: HashMap<String, String> // filter text -> keyword
}
I've found some key flatbuffers attribute that can be put on array item, but it seems to be neither documented nor shown in samples:
Can be used for in-place binary search
table KeywordToFilters {
filter_text: string (key);
keyword: string;
}
table Index {
map: [KeywordToFilters];
}
How can i use it (get value by key)? The problem is that no map-like methods are generated - it's just a vector:
pub map: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a , flatbuffers::ForwardsUOffset<KeywordToFilters<'a >>>>>,
Is there more efficient way to have a map with flatbuffers in Rust?
PS. flatbuffers crate version is 0.8.3
The problem can be demo'd here
I want to define a function that can take an array of mixed types:
function foo(x: Array<mixed>): string {
// ... do something
}
Then I try to call it with an array off some custom object type:
type Thing = {
id: string
}
let array : Array<Thing> = [{id: 'hello'}];
foo(array);
... and I get the following error
Cannot call `foo` with `array` bound to `x` because `Thing` [1] is incompatible with mixed [2] in array element.`
Is there something that I'm not understanding about the mixed type. Why can't a use an array of objects as an argument?
It has to do with a mutability of the array argument. You can use $ReadOnlyArray to satisfy the requirement.
function foo(x: $ReadOnlyArray<mixed>): string {
// ... do something
return "hello";
}
type Thing = {
id: string
}
let array : Array<Thing> = [{id: 'hello'}];
foo(array);
Array's are passed by reference, not by value, so the value contained in the variable array can be modified within foo. e.g.
x.push(1)
array would no longer be an array of Thing only. So using $ReadOnlyArray means that x is immutable and therefore array is safe.
Background:
I am trying to cache some struct information for efficiency but am having trouble differentiating between struct with the same name, within the same package.
Example Code:
func Struct(s interface{}){
val := reflect.ValueOf(s)
typ := val.Type()
// cache in map, but with what key?
typ.Name() // not good enough
typ.PkgPath + typ.Name() // not good enough
}
func Caller1() {
type Test struct {
Name string
}
t:= Test{
Name:"Test Name",
}
Struct(t)
}
func Caller2() {
type Test struct {
Address string
Other string
}
t:= Test{
Address:"Test Address",
Other:"OTHER",
}
Struct(t)
}
Problem
Can't find a proper unique key as:
Name is the same "Test"
PkgPath with be identical as both functions are in same package
Pointers etc is out because need a consistent key otherwise caching would be pointless
Can anyone help in finding a way to uniquely identify these structs?
P.S. I do realize that changing of the struct name would solve the issue, but need to handle this scenario as I have a generic library that others will be calling and may have the structs defined like the above example.
To uniquely identify types in a map, use reflect.Type as the map key:
var cache map[reflect.Type]cachedType
This is recommended by the reflect documentation:
To test for [type] equality, compare the Types directly.
I thought I'd be able to make an ordered map type by using anonymous fields:
type customMap struct{
map[string]string
ordered []string
}
where I could reference the map with customMapInstance["key"] and iterate over ordered. Alas, it appears arrays and maps are not valid anonymous fields. I suspect there's a good reason...
From the spec:
An embedded type must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type.
You see that it mentions a "type name".
Named types are specified by a (possibly qualified) type name; unnamed types are specified using a type literal, which composes a new type from existing types.
In other words, a map or slice may not be anonymous unless they are defined as a named type. For example:
type MyMap map[string]string
type customMap struct{
MyMap
ordered []string
}
However, even if you embed MyMap or a slice type, you would still not be able to index customMap. Only fields and methods may be "promoted" when you embed. For everything else they act as just another field. In the above example, MyMap doesn't have any fields or methods and therefore is equivalent to:
type customMap struct{
MyMap MyMap
ordered []string
}