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
}
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’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
}
}
}
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.
with meteor's IronRouter, I'm trying to use the this.params object elsewhere, but confused as to what it is. It seems to be a zero length array, that is actually an object with named methods after the path components.
# coffee
#route 'magnets',
path: '/magnets/lesson/:lessonCname'
data: ->
if #ready()
debugger;
console.log("route.params", #params)
with this code, in the debug console I will get:
this.params
[]
this.params.lessonCname
"despite-magnets-01"
typeof(this.params)
"object"
this.params.length
0
this.ready()
but in passing the params object to a server method, the methods (ie "lessonCname") disappear.
If my understanding is correct, then the near-term question is what is the best way to retrieve/convert these methods to {property:value} so they can be serialized and passed to server calls?
There are two easy ways of solving your problem, you can either set a global variable from within the data scope (but this is considered bad practice, at least IMO) or you can use the "data" function, which returns the data context for the current template:
data: ->
window._globalscopedata = #params.whatever #setting global variable
return someCollection.findOne #returns data context
_id: #params.whatever
when proccessing this route I will have the whatever param available in _globalscoredata and my document available in the template context.
Take a look at the source code for retrieving the parameters from a path. params is an array, but may have named properties. To iterate over everything, you can use the for in loop:
for(var x in myArray){
// Do something.
}
In this way, you can copy over everything to a new object (there may be a simpler way to create a copy).
The params property attached to a RouteController is an object with the following properties :
hash : the value of the URL hash.
query : an object consisting of key/value pairs representing the query string.
a list of URL fragments with their name and actual value.
Let's take an example, for this route definition :
// using iron:router#1.0.0-pre2 new route definition
Router.route("/posts/:slug");
And this URL typed in the browser address bar : /posts/first-post#comments?lang=en
We can use the console to find out precisely what params will actually contain :
> Router.current().params
Which will display this result :
Object {
hash: "comments",
slug: "first-post",
query: {
lang: "en"
}
}
Here slug is already a property of the params object whose value is "first-post", this is not a method.
If you want to extract from params these URL fragments as an object of key/value pairs, you can use underscore omit :
// getting rid of the hash and the query string
var parameters=_.omit(this.params,["hash","query"]);
I have two entities. One is "Students" while another is "Subjects".
The details of the two entities is something like:
students { id, name}
subjects { studentID, subjectName, passed}
where "passed" is of boolean type.
Now I want to query the student name and count of subject that he can pass with follows:
var result = from s in db.students
select new {s.name, s.subjects.Count(i => i.passed.Equals(true)};
But i get error msg:Invalid anonymous type member declarator. Anonymous type members must be declared with a member assignment, simple name or member access.
I dun know how to solve it. Would anyone help me please?
thanks
This means that you need to name your anonymous type's properties that cannot be inferred
select new
{
s.name,
Count=s.subjects.Count(i => i.passed.Equals(true))
};
Usually, the property name is good enough, however you are using the Count method, so that property has no inherent name
You have to add anonymous type properties names:
var result = from s in db.students
select new {
s.name,
count = s.subjects.Count(i => i.passed.Equals(true)
};
You can skip them only when using member assignment. Compiler will take the name from that member. That's why s.name can be applied without specifying property name. Count() is an expression, so you have to specify how the property should be named.
Source: Anonymous Types (C# Programming Guide)
If you do not specify member names in the anonymous type, the compiler
gives the anonymous type members the same name as the property being
used to initialize them. You must provide a name for a property that
is being initialized with an expression (...)