How to sort slices in GAE Go - google-app-engine

I am trying to sort slices. How to this in gae using go?
I have struct
type courseData struct {
Key *datastore.Key
FormKey *datastore.Key
Selected bool
User string
Name string
Description string
Date time.Time
}
I would like to sort slice of this entity kind in the Name field.
q := datastore.NewQuery("Course")
var courses []*courseData
if keys, err := q.GetAll(c, &courses); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} else {
for i := range courses {
courses[i].Key = keys[i]
}
}
I tried the
Sort(data Interface)
but not sure how to use it.
Please help. Thanks!

For example,
package main
import (
"fmt"
"sort"
"time"
)
type Course struct {
Key string // *datastore.Key
FormKey string // *datastore.Key
Selected bool
User string
Name string
Description string
Date time.Time
}
type Courses []*Course
func (s Courses) Len() int { return len(s) }
func (s Courses) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
type ByName struct{ Courses }
func (s ByName) Less(i, j int) bool { return s.Courses[i].Name < s.Courses[j].Name }
func main() {
var courses = Courses{
&Course{Name: "John"},
&Course{Name: "Peter"},
&Course{Name: "Jane"},
}
sort.Sort(ByName{courses})
for _, course := range courses {
fmt.Println(course.Name)
}
Output:
Jane
John
Peter
Course and Courses need to be exported for use by the sort package.
To avoid making the example dependent on GAE, type *datastore.Key was changed to string.

Why not just ask for the entities in the correct order from the datastore?
q := datastore.NewQuery("Course").Order("Name")

Related

missing destination name field_name in struct model

I am using sqlx with mssql driver in golang
here is my struct model :
type Employee struct {
ID string `json:"id,omitempty" validate:"required"`
EmployeeNo int `json:"employeeno,omitempty" validate:"required"`
FullName string `json:"fullname,omitempty" validate:"required"`
}
and here is the rest of the code :
type EmployeeRepo interface {
GetEmployees() (*[]db_models.Employee, error)
}
type employeeRepo struct {
logger *zap.SugaredLogger
db db.DBFactory
}
var _ EmployeeRepo = (*employeeRepo)(nil)
func EmployeeRepoProvider(db db.DBFactory, logger *zap.SugaredLogger) EmployeeRepo {
return &employeeRepo{db: db, logger: logger}
}
func (e *employeeRepo) GetEmployees() (*[]db_models.Employee, error) {
fmt.Println("======= Getting Employees REPOO=======")
employees := &[]db_models.Employee{}
var err error
err = e.db.AuthDB.Select(employees, `SELECT * FROM testEmployees`)
if err != nil {
fmt.Println("err getting emp : ", err)
return nil, err
} else {
return employees, nil
}
}
whenever I try to get data from db I get this :
*missing destination name EmployeeNo in []db_models.Employee
already check issues 234 and 322 and did not work with me

How to insert an array in Postgresql with data from REST echo

I receive data into my echo rest api by post method. I have two arrays. I import pq library.
My structure is
type Lien struct {
LinkID int `json: "linkID"`
Linklabel string `json: "label"`
Linkaddress string `json: "address"`
Langs []string `json: "langs"`
Cats []int `json: "cats"`
}
My post function is
func createLink(c echo.Context) error {
l := new(Lien)
if err := c.Bind(l); err != nil {
return err
}
sqlStatement := "INSERT INTO link_test (label, address,langs, cats)VALUES ($1, $2, $3, $4)"
res, err := db.Query(sqlStatement, l.Linklabel, l.Linkaddress, pq.Array(l.Langs), pq.Array(l.Cats))
if err != nil {
fmt.Println(err)
} else {
fmt.Println(res)
return c.JSON(http.StatusCreated, l)
}
return c.String(http.StatusOK, "ok")
}
It works for the first two fields but not for the arrays, I always get a null value.

Unmarshaling array of objects in Go

in GO, I've tried to produce the following json :
[["my",257.14,257.24],["txt", 121.11, 65.555]]
from a struct that's undergo unmarshaling - and i'm failing to do so.
Here is what I tried:
x := []MyStruct{{Zero: map[int]string{0: "str"}, One: map[int]float32{1: 5.6}, Two: map[int]float32{1: 5.88}}}
where MyStruct is :
type Timestamp struct {
Zero map[int]string `json:"0"`
One map[int]float32 `json:"1"`
Two map[int]float32 `json:"2"`
}
this produces the wrong json structure:
"myStruct":[{"0":{"0":"has"},"1":{"1":5.6},"2":{"1":5.88}}]
tried this as well
any clue in the right direction will be highly appreciated.
Maybe this is your expected. It's possible to implement custom MarshalJSON/UnmarshalJSON.
package main
import (
"encoding/json"
"errors"
"fmt"
"log"
)
type Timestamp struct {
Zero []string
One []float32
Two []float32
}
func (t *Timestamp) UnmarshalJSON(b []byte) error {
var arr [][3]interface{}
err := json.Unmarshal(b, &arr)
if err != nil {
return nil
}
t.Zero = nil
t.One = nil
t.Two = nil
for _, v := range arr {
if len(v) != 3 {
return errors.New("invalid json")
}
if s, ok := v[0].(string); ok {
t.Zero = append(t.Zero, s)
}
if f, ok := v[1].(float64); ok {
t.One = append(t.One, float32(f))
}
if f, ok := v[2].(float64); ok {
t.Two = append(t.Two, float32(f))
}
}
return nil
}
func (t *Timestamp) MarshalJSON() ([]byte, error) {
var arr [][3]interface{}
var max int
if max < len(t.Zero) {
max = len(t.Zero)
}
if max < len(t.One) {
max = len(t.One)
}
if max < len(t.Two) {
max = len(t.Two)
}
for i := 0; i < max; i++ {
var v [3]interface{}
if i < len(t.Zero) {
v[0] = t.Zero[i]
}
if i < len(t.One) {
v[1] = t.One[i]
}
if i < len(t.Two) {
v[2] = t.Two[i]
}
arr = append(arr, v)
}
return json.Marshal(arr)
}
const j = `[["my",257.14,257.24],["txt", 121.11, 65.555]]`
func main() {
var ts Timestamp
err := json.Unmarshal([]byte(j), &ts)
if err != nil {
log.Fatal(err)
}
b, err := json.Marshal(&ts)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
}
https://play.golang.org/p/WtVEja1JDY
The problem you are having is you're trying to unmarshal a map, and a map will correlate to a JSON object. Your desired output is a list, so you need to unmarshal an array or a slice to get a list as your values.
Try making an adapter.
Small example:
type Object struct {
Base float32
Radius float32
Height float32
X float32
Y float32
}
func (obj *Object) ToCircle() *Circle {
return &Circle{
Radius: obj.Radius,
X: obj.X,
Y: obj.Y,
}
}
func (obj *Object) ToRectangle() *Rectangle {
return &Rectangle{
Base: obj.Base,
Height: obj.Height,
X: obj.X,
Y: obj.Y,
}
}
In the example above, Object is converted to a Rectangle or a Circle using the ToRectangle() and ToCircle() adapters, respectively. In your case, you need to convert Timestamp to a []interface{}. Then you can unmarshal and you'll just get a list of whatever values are in that slice, which is your desired output in this case.
For intsance, the signature if your adapter could look like this:
func (t *Timestamp) ToFoo() []interface{} {
var ret []interface{}
// Do some stuff to take values of 't' and append to 'ret'
return ret
}
func main() {
var result []interface{}
json.Unmarshal(t.ToFoo(), &result)
// ...
}
I'll leave the implementation details for you.

Improving performance of searching slice of structs for value

How can I optimize the code below for searching an array of maps for a specific key-value (and then return the other key-values)?
type userMap struct {
JiraUsername string
CHProjectID int
CHID string
}
func main() {
var userMaps []userMap
userMaps = append(userMaps, userMap{
JiraUsername: "ted",
CHProjectID: 81,
CHID: "23jk3f32jl3323",
})
fmt.Println(GetUserInfo(userMaps, "ted"))
}
func GetUserInfo(userMaps []userMap, jiraUsername string) (CHProjectID int, CHID string) {
for _, u := range userMaps {
if u.JiraUsername == jiraUsername {
return u.CHProjectID, u.CHID
}
}
return 0, ""
}
Your code is reasonable, but it's not array of map, it's slice of struct. The efficient way would be
type userMap struct {
JiraUsername string
CHProjectID int
CHID string
}
type UsersMap map[string]userMap
func main() {
userMaps := make(UsersMap)
userMaps["ted"] = userMap{
JiraUsername: "ted",
CHProjectID: 81,
CHID: "23jk3f32jl3323",
}
fmt.Println(GetUserInfo(userMaps, "ted"))
}
func GetUserInfo(userMaps UsersMap, jiraUsername string) (CHProjectID int, CHID string) {
if u, ok := userMaps[jiraUsername]; ok {
return u.CHProjectID, u.CHID
}
return 0, ""
}
This doesn't require loop and has O(1) complexity.

Assigning return values of a function to elements in Struct array in Golang

I want the Struct array to have return values of the Function I defined later in the code.
In here I defined a struct "array" and info is the array of all those values in the struct, I want every element in the info array to have the respective values I mentioned, info.pos should have the value of the string I'm passing through the function PossibleMoves(), info.bitrep should have the return value from the function converttobit(), info.numrep should have the return value of toNumber(), and v1-v8 should have the values of the moves[] array, (v1=moves[0]).
My code is definitely clumsy can someone help?
package main
import ("bufio"
"fmt"
"os"
"strings")
type array struct{
pos string
bitrep int64
numrep,v1,v2,v3,v4,v5,v6,v7,v8 int8
}
func main() {
file, err := os.Open("chessin.txt")
if err != nil {
fmt.Println(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
valid := []bool{}
for scanner.Scan() {
b := strings.Split(scanner.Text(), ",")
valid = append(valid, isvalid(b))
}
fmt.Println(valid)
info :=[64][11]array {
info.pos = Possiblemoves(pos)
info.bitrep=coverttobit(num)
info.numrep=toNumber(string)
info.v0=moves[0]
info.v1=moves[1]
info.v2=moves[2]
info.v3=moves[3]
info.v4=moves[4]
info.v5=moves[5]
info.v6=moves[6]
info.v7=moves[7]
}
}
func convertingtobit( num int){
n := int64(num)
bit:=strconv.FormatInt(n, 2)
}
func isvalid(b string) bool {
if b[0]<='H' && b[0]>='A' && b[1]<='8' && b[1]>='0' {
return true
}
return false
}
func toNumber(s string) int {
if len(s) != 2 {
fmt.Println("Invalid Input",s,".")
}
num=int(s[0]-'A')*8 + int(s[1]-'0')
return num
}
func PossibleMoves(a string) {
isvalid := isvalid(a)
if isvalid == true {
var moves [8]string
moves[0]=string(a[0]+1)+string(a[1]+2)
moves[1]=string(a[0]+1)+string(a[1]-2)
moves[2]=string(a[0]-1)+string(a[1]+2)
moves[3]=string(a[0]-1)+string(a[1]-2)
moves[4]=string(a[0]+2)+string(a[1]+1)
moves[5]=string(a[0]+2)+string(a[1]-1)
moves[6]=string(a[0]-2)+string(a[1]+1)
moves[7]=string(a[0]-2)+string(a[1]-1)
fmt.Println("Possible moves are : ",moves)
var PosMoves [8] int
for i:=0;i<8;i++ {
if isvalid == true {
PosMoves[i]=toNumber(moves[i])
}
}
fmt.Println("After converting : ",PosMoves)
} else {
fmt.Println("Invalid Input")
}
}
Short Answer ( Compile: Success) :
package main
import "fmt"
type array struct {
pos string
bitrep int64
numrep, v1, v2, v3, v4, v5, v6, v7, v8 int8
}
func toNumber(s string) int8 {
if len(s) != 2 {
fmt.Println("Invalid Input", s, ".")
}
num := int8(s[0]-'A')*8 + int8(s[1]-'0')
return num
}
func PossibleMoves(out *array, a string) {
out.v1 = toNumber(string(a[0]+1) + string(a[1]+2))
}
func main() {
info := &array{
pos: "A1",
bitrep: 1,
}
PossibleMoves(info, "")
}
There are some problems:
1- in your code use := instead of = for new vars:
func toNumber(s string) int {
if len(s) != 2 {
fmt.Println("Invalid Input",s,".")
}
num=int(s[0]-'A')*8 + int(s[1]-'0')
return num
}
Like this:
func toNumber(s string) int {
if !isvalid(s) {
panic("Invalid Input" + s + ".")
}
num := int(s[0]-'A')*8 + int(s[1]-'0')
return num
}
2- your code:
func isvalid(b string) bool {
if b[0]<='H' && b[0]>='A' && b[1]<='8' && b[1]>='0' {
return true
}
return false
}
check for len(b) == 2 like this:
func isvalid(b string) bool {
if len(b) == 2 && b[0] <= 'H' && b[0] >= 'A' && b[1] <= '8' && b[1] >= '1' {
return true
}
return false
}
3- try not to copy paste:
moves[0]=string(a[0]+1)+string(a[1]+2)
moves[1]=string(a[0]+1)+string(a[1]-2)
moves[2]=string(a[0]-1)+string(a[1]+2)
moves[3]=string(a[0]-1)+string(a[1]-2)
moves[4]=string(a[0]+2)+string(a[1]+1)
moves[5]=string(a[0]+2)+string(a[1]-1)
moves[6]=string(a[0]-2)+string(a[1]+1)
moves[7]=string(a[0]-2)+string(a[1]-1)
Answering exact question:
type array struct{
pos string
bitrep int64
numrep,v1,v2,v3,v4,v5,v6,v7,v8 int8
}
func PossibleMoves(out *array, a string) {
out.v1 = tonumber(string(a[0]+1) + string(a[1]+2))
// ...
}
func main() {
// ...
info := &array{
pos: "...",
bitrep: 1234,
}
PossibleMoves(info, line)
}
But instead of this small detail, concentrate on answer by #Amd.

Resources