Printing value of sql.NullString in Go template - sql

I have fetched details from database where couple of column were of sql.NullString and sql.NullInt64 column.
Now, while I print them, after checking if it is Valid, it prints data in {3 true} format. I only want to print value 3 from it.
How can I achieve this?
Currently this is what, I am printing:
{{ range $value := .CatMenu }}
... // Other data
{{ $value.ParentID }} // This is sql.NullInt64 type
{{ end }}

sql.NullInt64 is a struct:
type NullInt64 struct {
Int64 int64
Valid bool // Valid is true if Int64 is not NULL
}
When printing struct values, the default formatting is what you currently see.
If you check if it is valid and non-nil prior, you can simply print the NullInt64.Int64 field only which holds the numerical value.
This is how you can do it:
{{ range $value := .CatMenu }}
... // Other data
{{ $value.ParentID.Int64 }} // This is sql.NullInt64 type
{{ end }}
See this simple example to test it:
vs := []*sql.NullInt64{
{3, true},
{2, true},
}
t := template.Must(template.New("").Parse(
"{{range .}}{{.Int64}}\n{{end}}",
))
if err := t.Execute(os.Stdout, vs); err != nil {
panic(err)
}
Output (try it on the Go Playground):
3
2

Related

Get pointers to all fields of a struct dynamically using reflection

I'm trying to build a simple orm layer for golang.
Which would take a struct and generate the cols [] which can then be passed to sql function
rows.Scan(cols...) which takes pointers of fields in the struct corresponding to each of the columns it has found in the result set
Here is my example struct
type ExampleStruct struct {
ID int64 `sql:"id"`
aID string `sql:"a_id"`
UserID int64 `sql:"user_id"`
And this is my generic ORM function
func GetSqlColumnToFieldMap(model *ExampleStruct) map[string]interface{} {
typeOfModel := reflect.TypeOf(*model)
ValueOfModel := reflect.ValueOf(*model)
columnToDataPointerMap := make(map[string]interface{})
for i := 0; i < ValueOfModel.NumField(); i++ {
sql_column := typeOfModel.Field(i).Tag.Get("sql")
structValue := ValueOfModel.Field(i)
columnToDataPointerMap[sql_column] = structValue.Addr()
}
return columnToDataPointerMap
}
Once this method works fine i can use the map it generates to create an ordered list of sql pointers according to the column_names i get in rows() object
However i get below error on the .Addr() method call
panic: reflect.Value.Addr of unaddressable value [recovered]
panic: reflect.Value.Addr of unaddressable value
Is it not possible to do this ?
Also in an ideal scenario i would want the method to take an interface instead of *ExampleStruct so that it can be reused across different db models.
The error says the value whose address you want to get is unaddressable. This is because even though you pass a pointer to GetSqlColumnToFieldMap(), you immediately dereference it and work with a non-pointer value later on.
This value is wrapped in an interface{} when passed to reflect.ValueOf(), and values wrappped in interfaces are not addressable.
You must not dereference the pointer, but instead use Type.Elem() and Value.Elem() to get the element type and pointed value.
Something like this:
func GetSqlColumnToFieldMap(model *ExampleStruct) map[string]interface{} {
t := reflect.TypeOf(model).Elem()
v := reflect.ValueOf(model).Elem()
columnToDataPointerMap := make(map[string]interface{})
for i := 0; i < v.NumField(); i++ {
sql_column := t.Field(i).Tag.Get("sql")
structValue := v.Field(i)
columnToDataPointerMap[sql_column] = structValue.Addr()
}
return columnToDataPointerMap
}
With this simple change it works! And it doesn't depend on the parameter type, you may change it to interface{} and pass any struct pointers.
func GetSqlColumnToFieldMap(model interface{}) map[string]interface{} {
// ...
}
Testing it:
type ExampleStruct struct {
ID int64 `sql:"id"`
AID string `sql:"a_id"`
UserID int64 `sql:"user_id"`
}
type Point struct {
X int `sql:"x"`
Y int `sql:"y"`
}
func main() {
fmt.Println(GetSqlColumnToFieldMap(&ExampleStruct{}))
fmt.Println(GetSqlColumnToFieldMap(&Point{}))
}
Output (try it on the Go Playground):
map[a_id:<*string Value> id:<*int64 Value> user_id:<*int64 Value>]
map[x:<*int Value> y:<*int Value>]
Note that Value.Addr() returns the address wrapped in a reflect.Value. To "unwrap" the pointer, use Value.Interface():
func GetSqlColumnToFieldMap(model interface{}) map[string]interface{} {
t := reflect.TypeOf(model).Elem()
v := reflect.ValueOf(model).Elem()
m := make(map[string]interface{})
for i := 0; i < v.NumField(); i++ {
colName := t.Field(i).Tag.Get("sql")
field := v.Field(i)
m[colName] = field.Addr().Interface()
}
return m
}
This will output (try it on the Go Playground):
map[a_id:0xc00007e008 id:0xc00007e000 user_id:0xc00007e018]
map[x:0xc000018060 y:0xc000018068]
For an in-depth introduction to reflection, please read blog post: The Laws of Reflection

What does Dafny know about loops with a break?

I am used to loops
while Grd
invariant Inv
{ ..}
assert Inv && !Grd;
with out any break Dafny knows that Inv && ! Grd is true but:
Dafny does not check the loop invariant after a break; command. Hence
method tester(s:seq<int>) returns (r:int)
ensures r <= 0
{ var i:nat := |s|;
r := 0;
while (i > 0)
decreases i
invariant r == 0;
{ i := i -1;
if s[i]< 0 { r:= s[i]; break;}
}
// assert r == 0; // invariant dose not hold
}
method Main() {
var x:int := tester([1,-9,0]);
print x,"\n";
}
Clearly Dafny understands that the invariant no longer holds. Could anyone tell me what dafny actually knows.
If there are break statements, the condition after the loop is
the disjunction of Inv && !Grd and the conditions that hold at
the respective break statements.
Here's a more formal answer:
In the absence of any abrupt exits (like break) from a loop, the familiar
way to prove the Hoare triple
{{ P }}
while Grd
invariant Inv
{
Body
}
{{ Q }}
is to prove the following three conditions (I'm ignore termination):
Check that the loop invariant holds on entry to the loop:
P ==> Inv
Check that the loop invariant is maintained by the loop body:
{{ Inv && Grd }}
Body
{{ Inv }}
Check that the invariant and negated guard prove Q:
Inv && !Grd ==> Q
Let me rephrase conditions 1 and 2. To do that, I will start by
rewriting the while loop into a repeat-forever loop with breaks:
loop
invariant Inv
{
if !Grd {
break;
}
Body
}
(In other words, I'm using loop as while true.) Proof obligation 1 above
can now be rephrased as proving
{{ Inv }}
if !Grd {
break;
}
Body
{{ Inv }}
where you don't have to prove anything further along any path that reaches
a break.
Proof obligation 2 can be rephrased in a sort of dual way:
{{ Inv }}
if !Grd {
break;
}
Body
{{ break: Q }}
by which I mean you don't have to prove anything if you reach the end of ...Body,
but you do have to prove Q at any break.
What I just said also applies when Body contains other break statements. That's how Dafny treats loops (that is, condition 0 plus the rephrased conditions 1 and 2, plus termination checking).

How can I discover if a []byte is an array or a single object

I'm creating an API that will receive an object in a specific route. In this route I can receive a single object or a bulk of it.
Example:
[{"foo":"bar"}]
{"foo":"bar"}
How can I know if the body request is a slice or a single object before de json.Unmarshal. Moreover, if this is not possible, what is the best way to accept this two types of body requests and convert them to a list of objects?
I expect something like this:
type Foo struct {
Foo string `json:"foo"`
}
func Bla() []Foo {
fakeBody := []byte(`[{"foo":"bar"}]`)
fakeBody2 := []byte(`{"foo":"bar"}`)
var foo []Foo
// If fakeBody contains a array of objects
// then parse it to the foo slice variable normally
// So, if the fakeBody2 is a single object then
// parse this single object to the foo slice that will contain only
// one element.
return foo
}
This is what I would consider doing in this situation, in this order:
You can read the body, and check the first non-space character to see if it is '[' or '{', and unmarshal based on that.
You can first unmarshal as an array, then if that fails, as a single object.
You can unmarshal to an interface{}, do a type assertion, and parse the contents yourself.
Check the first non-whitespace byte to determine if the JSON document is an array or object. Decode accordingly.
func decode(body []byte) ([]Foo, error) {
b = bytes.TrimLeft(body, " \t\n\r")
if len(b) > 0 && b[0] == '[' {
var v []Foo
err := json.Unmarshal(body, &v)
return v, err
}
var v [1]Foo
err := json.Unmarshal(body, &v[0])
return v[:], err
}
Why not just add the [ the and ] if it's not their, and then always treat it as an array?
body := []byte(`{"foo":"bar"}`)
body = bytes.TrimSpace(body)
if len(body) > 0 && body[0] != '[' {
tmp := make([]byte, len(body)+2, len(body)+2)
tmp[0] = '['
tmp[len(tmp)-1] = ']'
copy(tmp[1:len(tmp)-1], body)
body = tmp
}
https://play.golang.org/p/YfnLgN9q64F
Or, create the array first, and then based on the first character either marshal into the array or the first item:
f := make([]Foo, 1)
body := []byte(`{"foo":"bar"}`)
if len(body) > 0 && body[0] != '[' {
json.Unmarshal(body, &f[0])
} else {
json.Unmarshal(body, &f)
}
fmt.Println(f)
https://play.golang.org/p/1fxBKH3ZJyH

Go validator with sql null types?

I am having problems getting the golang validator to work with SQL null types. Here's an example of what I tried:
package main
import (
"database/sql"
"database/sql/driver"
"log"
"gopkg.in/go-playground/validator.v9"
)
// NullInt64
type NullInt64 struct {
sql.NullInt64
Set bool
}
func MakeNullInt64(valid bool, val int64) NullInt64 {
n := NullInt64{}
n.Set = true
n.Valid = valid
if valid {
n.Int64 = val
}
return n
}
func (n *NullInt64) Value() (driver.Value, error) {
if !n.NullInt64.Valid {
return nil, nil
}
return n.NullInt64.Int64, nil
}
type Thing struct {
N2 NullInt64 `validate:"min=10"`
N3 int64 `validate:"min=10"`
N4 *int64 `validate:"min=10"`
}
func main() {
validate := validator.New()
n := int64(6)
number := MakeNullInt64(true, n)
thing := Thing{number, n, &n}
e := validate.Struct(thing)
log.Println(e)
}
When I run this code, I only get this output:
Key: 'Thing.N3' Error:Field validation for 'N3' failed on the 'min'
tag
Key: 'Thing.N4' Error:Field validation for 'N4' failed on the
'min' tag
The problem is that I want it to also show that Thing.N2 failed for the same reasons as Thing.N3 and Thing.N4.
I tried introducing the func (n *NullInt64) Value() method because it was mentioned in the documentation. But I think I misunderstood something. Can anyone tell me what I did wrong?
UPDATE
There is an Example specifically for that. You may check it out. My other proposed solution should still work though.
Since the value you are trying to validate is Int64 inside sql.NullInt64, the easiest way would be to remove the validate tag and just register a Struct Level validation using:
validate.RegisterStructValidation(NullInt64StructLevelValidation, NullInt64{})
while NullInt64StructLevelValidation is a StructLevelFunc that looks like this:
func NullInt64StructLevelValidation(sl validator.StructLevel) {
ni := sl.Current().Interface().(NullInt64)
if ni.NullInt64.Int64 < 10 {
sl.ReportError(ni.NullInt64.Int64, "Int64", "", "min", "")
}
}
Note #1: this line thing := Thing{number,&number,n,&n} has one argument too many. I assume you meant thing := Thing{number, n, &n}
Note #2: Go tooling including gofmt is considered to be one of the most powerful features of the language. Please consider using it/them.
EDIT #1:
I don't think implementing Valuer interface is of any value in this context.

Implement a for loop inside a Go template

I am working in Go, and right now I need to print at least 20 options inside a select, so I need to use some kind of loop that goes from 0 to 20 (to get an index).
How can I use a for loop inside a Go template?
I need to generate the sequence of numbers inside the template. I don't have any array to iterate.
EDIT:
I need to get something like this:
<select>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
So, I need to do in the code something like:
<select>
{{for i := 1; i < 5; i++}}
<option value="{{i}}">{{i}}</option>
{{end}}
</select>
But, this doesn't work.
You can use range in templates as well. See https://golang.org/pkg/text/template/#hdr-Variables
Easiest option might be to just use a slice containing your options:
func main() {
const tmpl = `
<select>
{{range $val := .}}
<option value="{{$val}}">{{$val}}</option>
{{end}}
</select>
`
t := template.Must(template.New("tmpl").Parse(tmpl))
t.Execute(os.Stdout, []int{1, 2, 3})
}
Your best bet is to add an "Iterate" function to your func_map.
template.FuncMap{
"Iterate": func(count *uint) []uint {
var i uint
var Items []uint
for i = 0; i < (*count); i++ {
Items = append(Items, i)
}
return Items
},
}
Once you register your function map with text/template, you can iterate like this:
{{- range $val := Iterate 5 }}
{{ $val }}
{{- end }}
I don't know why this useful function isn't part of the default set of functions text/template provides. Maybe they'll add something similar in the future.
You can also use a channel to avoid building a slice:
funcMap := template.FuncMap{
"loop": func(from, to int) <-chan int {
ch := make(chan int)
go func() {
for i := from; i <= to; i++ {
ch <- i
}
close(ch)
}()
return ch
},
}
then:
{{range $x := loop 3 9 }}
Hey {{$x}}!
{{- end}}
See the full working example: https://go.dev/play/p/DP2WuROnCC9