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.
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 have read some of the stack overflow question related to "why pointer and why not pointer", but I could not understand much.
So, I thought to understand and learn based on my situation on golang perspective.
I have 2 struct
type Discussion struct {
ID string `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Owner *User `json:"owner"`
}
type User struct {
ID string `json:"id"`
Name string `json:"name"`
}
In above Discussion struct you can see, I used *User for Owner field.
Considering situation, I do not have to change data for Owner after creating value for Discussion like below, should I use only User or it's better to use *User like below
func main() {
u := User {
ID: "2",
Name: "StackOverflow",
}
d := Discussion{
ID: "1",
Title: "This is my family",
Content: "I love my family",
Owner: &u,
}
}
or, Should I use like below -
type Discussion struct {
ID string `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Owner User `json:"owner"`
}
type User struct {
ID string `json:"id"`
Name string `json:"name"`
}
func main() {
u := User {
ID: "2",
Name: "StackOverflow",
}
d := Discussion{
ID: "1",
Title: "This is my family",
Content: "I love my family",
Owner: u,
}
}
I have following question based on above 2 situation
Performance - which one is better & why?
Garbage Collection - which one is better & why?
Any Memory effects?
Any other effects!
Which one should be used on above example and why?
Please put your answer only based on above example, which method would you have choosed above and why?
Thanks
Performance wise, it's better to use pointers as everything with golang is pass by value. So instead of golang having to look up the values of the User struct to then pass to the Discussion struct, it only passes the pointer to it. This also applies to how attaching methods to struct works. func (u *User)Example{} will execute faster as only the pointer has to be passed in. I think performance is negligible however
No Clue, I've only read one post about garbage collection issues by twitch and they said they where all resolved by golang 1.7. There are very few situations where you are worried about this.
If you don't use a pointer to User, updates to the User struct won't reflect inside of the Discussion struct. See this example here. Notice even though User's ID has been updated, it's not reflected in Discussion.
/shrug
I am a novice with regards to the swift 3 programming language though I am familiar basically with C++.
I am trying to learn to use dictionaries in Swift 3; which I believe are similar to hashes in C++. I have a dictionary with several key:value pairs in it.
I want to take a certain, single key (which I won't know in advance) and extract from that dictionary the corresponding value.
I know there will be a single key with that name, although the same value will be associated with keys of different names.
After extracting that value from the key:value pair of that dictionary then I want to store that single value in a variable as a string.
What type of code could do that?
I found some code that seems it might be helpful but I'm not sure and I'm not sure too how to use that code(how to write it actually) to make it perform as I wish.
extension Dictionary where Value: Equatable {
func someKeyFor(value: Value) -> Key? {
guard let index = indexOf({ $0.1 == value }) else {
return nil
}
return self[index].0
}
}
This is straight-forward dictionary access; no need to use extensions.
var myDictionary = [String:String]()
// At some point strings are put into the dictionary
// e.g. myDictionary["SomeKey"] = "SomeString"
// then you can say
if let someString = myDictionary[key] {
// You can now do something with someString
}
Keys and objects don't have to be strings, of course
I would suggest you read the Swift book from Apple in iBooks and try things out in in a Swift Playground in Xcode.
I am using PFQueryTableViewController to retrieve objects from Parse. This particular Parse class has three columns (group, category, client) which are pointers to other Parse classes. I want to use the includeKey option to bring in all object data for each of those pointer objects. However, when I run the code below, I do retrieve the basic data about each pointer column (like ObjectID), but none of the additional columns, like the "name" column of the Category class.
override func queryForTable() -> PFQuery {
let query:PFQuery = PFQuery(className:self.parseClassName!)
query.whereKey("client", equalTo: currentUser!)
query.whereKey("status", equalTo: "Open")
query.whereKey("expires", greaterThan: NSDate())
query.includeKey("group")
query.includeKey("category")
query.includeKey("client")
query.orderByAscending("expires")
if(objects?.count == 0)
{
query.cachePolicy = PFCachePolicy.CacheThenNetwork
}
return query
}
When my PFQueryTableViewController calls it's cellForRowAtIndexPath function, I have code to get the 'name' column of the category object brought in via includeKey
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
...
if let category = task["category"] as? PFObject {
cell?.categoryLabel.text = String(category["name"])
}
...
}
Running this retrieval of the category's 'name' value results in the following error and crash in Xcode:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Key "name" has no data. Call fetchIfNeeded before getting its value.'
This same error results when I attempt to access any additional columns of my pointer reference objects.
When I print(category) I appear to get a valid (but empty) object in my log, with no additional columns, like 'name':
<Category: 0x13c6ed870, objectId: mEpn6TH6Tc, localId: (null)> {
}
I have successfully tested calling the suggested fetch query to retrieve the missing pointer data for each pointer column, but (IMHO) the additional fetch defeats the purpose of the includeKey query option to limit API requests.
One thought I had was that a PFQuery may only allow one includeKey call. But, the research that I've done through both Parse's own iOS documentation and various developer posts do not indicate any limitation of max number of includeKeys a query can have.
Am I doing something unsupported by Parse or am I just syntactically not retrieving each pointers' object data the proper way?
I'm running the latest ParseUI as of this posting (1.1.6) and Parse (1.9.0) with Xcode 7.0.1
Thank you in advance for reading my post! I am only a couple months into learning iOS development, so this is both interesting and frustrating at the same time!
cell.category.text = object.objectForKey("category")!.objectForKey("name") as! String
also, use the other "version" of cellForRowAtIndexPath, the one for PFQueryTableViewControllers:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject!) -> PFTableViewCell? {
//4
let cell = tableView.dequeueReusableCellWithIdentifier("yourCellIdentifier", forIndexPath: indexPath) as! yourCell
return cell
}
this allows you to use the above syntax that I answered with.
linuxfood has created bindings for sqlite3, for which I am thankful. I'm just starting to learn Rust (0.8), and I'm trying to understand exactly what this bit of code is doing:
extern mod sqlite;
fn db() {
let database =
match sqlite::open("test.db") {
Ok(db) => db,
Err(e) => {
println(fmt!("Error opening test.db: %?", e));
return;
}
};
I do understand basically what it is doing. It is attempting to obtain a database connection and also testing for an error. I don't understand exactly how it is doing that.
In order to better understand it, I wanted to rewrite it without the match statement, but I don't have the knowledge to do that. Is that possible? Does sqlite::open() return two variables, or only one?
How can this example be written differently without the match statement? I'm not saying that is necessary or preferable, however it may help me to learn the language.
The outer statement is an assignment that assigns the value of the match expression to database. The match expression depends on the return value of sqlite::open, which probably is of type Result<T, E> (an enum with variants Ok(T) and Err(E)). In case it's Ok, the enum variant has a parameter which the match expression destructures into db and passes back this value (therefore it gets assigned to the variable database). In case it's Err, the enum variant has a parameter with an error object which is printed and the function returns.
Without using a match statement, this could be written like the following (just because you explicitly asked for not using match - most people will considered this bad coding style):
let res = sqlite::open("test.db");
if res.is_err() {
println!("Error opening test.db: {:?}", res.unwrap_err());
return;
}
let database = res.unwrap();
I'm just learning Rust myself, but this is another way of dealing with this.
if let Ok(database) = sqlite::open("test.db") {
// Handle success case
} else {
// Handle error case
}
See the documentation about if let.
This function open returns SqliteResult<Database>; given the definition pub type SqliteResult<T> = Result<T, ResultCode>, that is std::result::Result<Database, ResultCode>.
Result is an enum, and you fundamentally cannot access the variants of an enum without matching: that is, quite literally, the only way. Sure, you may have methods for it abstracting away the matching, but they are necessarily implemented with match.
You can see from the Result documentation that it does have convenience methods like is_err, which is approximately this (it's not precisely this but close enough):
fn is_err(&self) -> bool {
match *self {
Ok(_) => false,
Err(_) => true,
}
}
and unwrap (again only approximate):
fn unwrap(self) -> T {
match self {
Ok(t) => t,
Err(e) => fail!(),
}
}
As you see, these are implemented with matching. In this case of yours, using the matching is the best way to write this code.
sqlite::open() is returning an Enum. Enums are a little different in rust, each value of an enum can have fields attached to it.
See http://static.rust-lang.org/doc/0.8/tutorial.html#enums
So in this case the SqliteResult enum can either be Ok or Err if it is Ok then it has the reference to the db attached to it, if it is Err then it has the error details.
With a C# or Java background you could consider the SqliteResult as a base class that Ok and Err inherit from, each with their own relevant information. In this scenario the match clause is simply checking the type to see which subtype was returned. I wouldn't get too fixated on this parallel though it is a bad idea to try this hard to match concepts between languages.