Confused about pointer and value parameter neoism - go

I am writing a web application in Go and use Neo4j database for storing data. As Neo4j api to Go, i choose neoism.
However, look at the following code snippet.
db, _ := neoism.Connect("http://localhost:7474/db/data")
// Create a node with a Cypher quer
// Issue a query
//
res1 := []struct {
A string `json:"n.email"`
}{}
cq1 := neoism.CypherQuery{
//Use backticks for long statements - Cypher is whitespace indifferent
Statement: `
MATCH (n:Account {email: {email}})
RETURN n.email
`,
Parameters: neoism.Props{"email": "hans#ueli.com"},
Result: &res1,
}
db.Cypher(&cq1)
fmt.Println(res1)
I query here data from node Account and got a result return, everything works fine here.
The second code almost the same, but I am creating here directly(variable res2) a pointer slice.
// Validate, if email already available in db
res2 := []*struct {
A string `json:"n.email"`
}{}
cq := &neoism.CypherQuery{
Statement: `
MATCH (n:Account {email: {email}})
RETURN n.email
`,
Parameters: neoism.Props{"email": "hans#ueli.com"},
Result: res2,
}
db.Cypher(cq)
fmt.Println(res2)
The difference between them are, I've got by the first sample a result but second not.
Result:
[{hans#ueli.com}]
[]
What do I wrong with pointer res2 here?

From the neoism documentation:
Result must be a pointer to a slice of structs - e.g. &[]someStruct{}
Nothing is said about slices of struct pointers, so I assume that your slice is empty because the function is not expecting pointers, so it couldn't put anything in the slice.
I encountered the same behavior when giving sqlx.Query the wrong type of slice. The lacks of error is quite frustrating the first times, but it quickly becomes a reflex.

Related

Go Scanner still returns <nil>

first of all: I am totally newbie in golang, so I may not understand well.
I am tasked to write a Go data extractor from one database using "gorp". The problem is with one table, that has custom field "TimeRange".
It is defined as:
type TimeRange struct {
From string
To string
}
Sadly when I try to fetch row I am getting scanner error, so I realised I need a custom scanner.
// Scan - Implement the database/sql scanner interface
func (tr *TimeRange) Scan(value interface{}) error {
tr.From = "mis"
tr.To = "lala"
fmt.Printf("%v\n", *tr)
return nil
}
So I expect to see fixed '{mis lala}' in returned string.
Why I am getting:
var q2 []models.Dashboard
result, err := dbmap.Select(&q2, "select * from dashboard where id=3")
fmt.Printf("q2=%v\n", q2)
prints:
p2=[{{<nil> Tomek b1f6f0ba-f618-00d6-6d24-8410a9219c95}}]
which is:
TimeRange, UserName and UUID
Might be important: using "gorp" for DB managment
the scan function would be called on passed value type to dbmap.Select() so in your case, you need to implement Dashboard as scanner.

function returning pointer to struct slice only returns 1

I have a function that basically looks like this:
func (db *datastoreDB) GetAllUsers(ctx context.Context) (*[]User, error) {
query := datastore.NewQuery("User")
var users []User
_, err := db.client.GetAll(ctx, query, &users)
return &users, nil
}
with the struct:
type User struct {
username string
password []byte
}
Now, if I try to call
users, err := models.DB.GetAllUsers(ctx)
log.Println(users)
then it will only print 1 user, even though there are many..
I tried to Print using users[0], users[1] but that returned errors, also tried with *users[1], &users[1], and for i, _ range users { log.Println(users[i]) }
Haven't quite been able to understand when/how to use * and & even though I read many online tutorials, so often just do trail and error.. I doubt there is anything wrong with my datastore GetAll function, so I assume I just fail to properly access/return the struct slice but feel like I tried everything..
Slices include pointers; in fact they are structs with a pointer to an array and some information as to where the slice begins and ends.
A slice is a descriptor of an array segment. It consists of a pointer to the array, the length of the segment, and its capacity (the maximum length of the segment)
Golang blog
The asterix before a type designates that type as a pointer (unless it already is a pointer, in that case it dereferences it). I think you probably meant to write []*User, which will expect a slice of pointers to Users. You can think of [] and User as distinct types.
To create a slice, the simplest way is probably with make();
You can try, instead of var users []User,
users := make([]*User, 0) // replace 0 with the amount of nil values in the slice you're looking to fill
Finally, you'll have to remove the & signs you place before users, as these pass the pointer to a value (but as I pointed out above, slices are already pointers)
To better understand pointers, Dave Cheney recently wrote a blog post titled Understand Go pointers in less than 800 words or your money back, you might find it useful.

How do you run a Cypher Query on a Neo4j Database in Go?

I've been working on this problem for a few hours, and I haven't had much luck with the community Golang drivers for Neo4j.
I've attempted to run "movies-go-cq" and "neoism" examples. The movies-go-cq example doesn't work for me, it crashes when localhost:8080 is loaded in the browser.
Cypher queries on my Neo4j database with neoism only return empty/blank data. However, when I run the same query in the Neo4j browser at localhost:7474, the expected data is returned.
Here is the Go code I am running with neoism:
package main
import (
"fmt"
"github.com/jmcvetta/neoism"
)
func main() {
// Reference: https://godoc.org/github.com/jmcvetta/neoism
// Connect to the Neo4j server
db, _ := neoism.Connect("http://localhost:7474/db/data")
// Issue a query
res1 := []struct {
A string `json:"path1"` // `json` tag matches column name in query
B string `json:"path2"`
}{}
cq1 := neoism.CypherQuery{
// Use backticks for long statements - Cypher is whitespace indifferent
Statement: `
MATCH path1 = shortestPath( (plant:Plant {Term: "Vaccinium corymbosum"})-[*..5]-(gene:Gene {Description: "adenylate cyclase activating polypeptide 1"}) )
MATCH path2 = shortestPath( (gene)-[*..5]-(disease:Medical_Heading {Term: "Alzheimer Disease"}) )
RETURN path1, path2
`,
Result: &res1,
}
db.Cypher(&cq1)
r := res1[0]
fmt.Println(r.A, r.B)
}
I am considering writing my own API wrapper in Go that uses Neo4j's HTTP RESTful API if I can't get existing Go drivers to work properly; I am new to Golang, and I would be thankful for any advice for debugging Go code or tips for working with Neo4j in Golang. Thank you for your time.
I know what you are facing right now. Some time before I was facing the same issue.
There are 2 possible cases are there:-
1) You should always declare struct variable Capital.
res1 := []struct {
CAPITAL_STR1 string `json:"path1"`
CAPITAL_STR2 string `json:"path2"`
}{}
which you are doing exactly right A and B.
2) You have to paste exact json type (There is mistake)
res1 := []struct {
CAPITAL_STR1 string `json:"path1.distance"`
CAPITAL_STR2 string `json:"path2.distance"`
}{}
For getting exact json format check output json response at your Neo4J in browser. It is available under section code.

Is it possible to dump golang db.Query() output to a string?

I have a small Heroku app in which i print out name and age from each rows after query execution.
I want to avoid looping rows.Next(),Scan().. and just want to show what database returned after query execution which may be some data or error.
Can we directly dump data to a string for printing?
rows, err := db.Query("SELECT name FROM users WHERE age = $1", age)
if err != nil {
log.Fatal(err)
}
for rows.Next() {
var name string
if err := rows.Scan(&name); err != nil {
log.Fatal(err)
}
fmt.Printf("%s is %d\n", name, age)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
Pretty much: No.
The Query method is going to return a pointer to a Rows struct:
func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
If you print that (fmt.Printf("%#v\n", rows)) you'll see something such as:
&sql.Rows{dc:(*sql.driverConn)(0xc8201225a0), releaseConn:(func(error)(0x4802c0), rowsi:(*pq.rows)(0xc820166700), closed:false, lastcols:[]driver.Value(nil), lasterr:error(nil), closeStmt:driver.Stmt(nil)}
...probably not what you want.
Those correspond to the Rows struct from the sql package (you'll notice the fields are not exported):
type Rows struct {
dc *driverConn // owned; must call releaseConn when closed to release
releaseConn func(error)
rowsi driver.Rows
closed bool
lastcols []driver.Value
lasterr error // non-nil only if closed is true
closeStmt driver.Stmt // if non-nil, statement to Close on close
}
You'll see []driver.Value (an interface from the driver package), that looks like where we can expect to find some useful, maybe even human readable data. But when directly printed it doesn't appear useful, it's even empty... So you have to somehow get at the underlying information. The sql package gives us the Next method to start with:
Next prepares the next result row for reading with the Scan method.
It returns true on success, or false if there is no next
result row or an error happened while preparing it. Err
should be consulted to distinguish between the two cases.
Every call to Scan, even the first one, must be preceded by a call to Next.
Next is going to make a []driver.Value the same size as the number of columns I have, which is accessible (within the sql package) through driver.Rows (the rowsi field) and populate it with values from the query.
After calling rows.Next() if you did the same fmt.Printf("%#v\n", rows) you should now see that []diver.Value is no longer empty but it's still not going to be anything that you can read, more likely something resembling:[]diver.Value{[]uint8{0x47, 0x65...
And since the field isn't exported you can't even try and convert it to something more meaningful. But the sql package gives us a means to do something with the data, which is Scan.
The Scan method is pretty concise, with lengthy comments that I won't paste here, but the really important bit is that it ranges over the columns in the current row you get from the Next method and calls convertAssign(dest[i], sv), which you can see here:
https://golang.org/src/database/sql/convert.go
It's pretty long but actually relatively simple, it essentially switches on the type of the source and destination and converts where it can, and copies from source to destination; the function comments tell us:
convertAssign copies to dest the value in src, converting it if possible. An error is returned if the copy would result in loss of information. dest should be a pointer type.
So now you have a method (Scan) which you can call directly and which hands you back converted values. Your code sample above is fine (except maybe the call to Fatal() on a Scan error).
It's important to realize that the sql package has to work with a specific driver, which is in turn implemented for specific database software, so there is quite some work going on behind the scenes.
I think your best bet if you want to hide/generalize the whole Query() ---> Next() ---> Scan() idiom is to drop it into another function which does it behind the scenes... write a package in which you abstract away that higher level implementation, as the sql package abstracts away some of the driver-specific details, the converting and copying, populating the Rows, etc.

Golang gorilla sessions preserving form data after redirect

From logic point of view I am trying to preserve partial form data between redirects for better user experience so user won't have to fill entire form again, just the part that was invalid.
From programing point of view I am trying to save request.PostForm data structure in gorilla session's flashes. The only thing I manage to retrieve after redirect is string representation of memory address like this [0xc2001c8b10].
Here is the part where I save flashes data after validation error (request.ParseForm() was executed before this):
session, _ := store.Get(request, "test")
session.AddFlash(err.Error(), "messages")
session.AddFlash(request.PostForm, "form_data")
session.Save(request, response)
http.Redirect(response, request, "/", http.StatusFound)
return
Also I tried registering structure with gob without effect:
func init() {
gob.Register(&url.Values{})
}
Form values are in lower case, eg. "first_name", "last_name" if that could have any influence on this behavior.
Please keep in mind that I successfully manage to retrieve "messages" after redirect, only problem I have is with structural data.
Am I doing something wrong or is there maybe another approach to fill partial forms after redirect that I am not aware of?
Your problem is that you're working with values of type interface{}, which is the generic type
and used when there can be more than one type. This is the case for gorilla's session.Flashes()
method as it can return arbitrary user data (whatever you put in).
You can reproduce what you're experiencing with this code (on play):
type MyData struct {
X int
}
// Simulate Flashes() from gorilla, which returns a slice of interface{} values.
func Flashes() []interface{} {
x := &MyData{2}
// Convert x to type interface{}
interfaceValue := interface{}(x)
// Put converted x into a slice of type []interface{}
return []interface{}{interfaceValue}
}
func main() {
// See that [0xSOMETHING] is printed
fmt.Println("Some data:", Flashes())
}
When running this program you will see output like this:
Some data: [0xc010000000]
This is the same you're experiencing. The reason for this is that fmt.Println does
not step through all levels of abstraction of pointers and interfaces and stops at
a certain level unless you tell it to print everything. So if you use
fmt.Printf("Some data: %#v\n", Flashes())
you will indeed see your data:
Some data: []interface {}{(*main.MyData)(0xc010000000)}
What you have to do to access the data is to match the resulted data for the type
you're expecting. You have to do a type assertion (example on play):
func main() {
value := Flashes()[0]
v, ok := value.(*MyData)
if ok {
fmt.Println("Some data:", v)
} else {
fmt.Println("Oh no, there's something else stored than expected")
}
}
In the example above the first flash returned by Flashes() is used and asserted to be
of type *MyData. If it is indeed this type, then it's value is printed to the console.
Otherwise an error message (albeit not a good one) is printed to the console.
After asserting a variable of being some type, the asserted value is of the asserted
type. That is the v in the example above is of type *MyType.

Resources