I get the compile error shown below saying that the ErrFieldMismatch type is missing an Error() method, but as shown in the last code chunk, it is not.
Any idea to why I cannot perform the type comparison for this?
Error
impossible type switch case: err (type error) cannot have dynamic type "google.golang.org/appengine/datastore".ErrFieldMismatch (missing Error method)
my code
type Program struct {
aemodel.Base
Name string `json:"name" required:"true"`
Public bool `json:"isPublic"`
Description string `json:"description" required:"true"`
Default bool `json:"isDefault"`
Tags []string `json:"tags"`
// Level int
}
// Load - PropertyLoadSaver interface
func (p *Program) Load(ps []datastore.Property) error {
if err := datastore.LoadStruct(p, ps); err != nil {
switch err.(type) {
case datastore.ErrFieldMismatch: // <-- Failure point
return nil
default:
return err
}
}
return nil
}
appengine code
type ErrFieldMismatch struct {
StructType reflect.Type
FieldName string
Reason string
}
func (e *ErrFieldMismatch) Error() string {
return fmt.Sprintf("datastore: cannot load field %q into a %q: %s",
e.FieldName, e.StructType, e.Reason)
}
Error method is defined on the type that is a pointer to datastore.ErrFieldMismatch, i.e., Error is defined on *datastore.ErrFieldMismatch, hence it's only *datastore.ErrFieldMismatch that implements the Error interface.
Try changing your case expression:
func (p *Program) Load(ps []datastore.Property) error {
if err := datastore.LoadStruct(p, ps); err != nil {
switch err.(type) {
case *datastore.ErrFieldMismatch: // use pointer type here
return nil
default:
return err
}
}
return nil
}
Related
I am new to go, I am trying to get 3 functions to return them as follows
function 1 - To return memory usage of the system
function 2 - To return disk usage of the system
function 3 - To return CPU usage of the system
So far I am able to do this much only (PS: trying not to use any libs)
func getCPUTrack() (idle, total uint64) {
contents, err := ioutil.ReadFile("/proc/stat")
if err != nil {
return
}
lines := strings.Split(string(contents), "\n")
for _, line := range lines {
fields := strings.Fields(line)
if fields[0] == "cpu" {
numFields := len(fields)
for i := 1; i < numFields; i++ {
val, err := strconv.ParseUint(fields[i], 10, 64)
if err != nil {
fmt.Println("Error: ", i, fields[i], err)
}
total += val // tally up all the numbers to get total ticks
if i == 4 { // idle is the 5th field in the cpu line
idle = val
}
}
return
}
}
return
}
idle0, total0 := getCPUTrack()
time.Sleep(3 * time.Second)
idle1, total1 := getCPUTrack()
idleTicks := float64(idle1 - idle0)
totalTicks := float64(total1 - total0)
cpuUsage := 100 * (totalTicks - idleTicks) / totalTicks
fmt.Printf("CPU usage is %f%% [busy: %f, total: %f]\n", cpuUsage, totalTicks-idleTicks, totalTicks)
Can anyone help me with this?
Thanks
There is a pretty cool library you can use Go-osstat, or see in detail how it is implemented so you can build your own.
I've developed a client that uses this library and runs in the background sending Memory and CPU usage metrics
package main
import (
"fmt"
"os"
"time"
"github.com/mackerelio/go-osstat/cpu"
"github.com/mackerelio/go-osstat/memory"
)
const (
memoryMetric = "memory"
cpuMetric = "cpu"
retries = 10
)
type client struct {
packageName string
memoryIteration int
cpuIteration int
OSClient OSClient
}
type Client interface {
EmitMetrics()
}
type osClient struct{}
type OSClient interface {
GetMemory() (*memory.Stats, error)
GetCPU() (*cpu.Stats, error)
}
func (osc osClient) GetMemory() (*memory.Stats, error) { return memory.Get() }
func (osc osClient) GetCPU() (*cpu.Stats, error) { return cpu.Get() }
func NewClient(packageName string, memoryIteration, cpuIteration int) Client {
return newClient(packageName, memoryIteration, cpuIteration, osClient{})
}
func newClient(packageName string, memoryIteration, cpuIteration int, osclient OSClient) Client {
return &client{
packageName: packageName,
memoryIteration: memoryIteration,
cpuIteration: cpuIteration,
OSClient: osclient,
}
}
func (c *client) EmitMetrics() {
protectFromPanic := func(metric string) {
if r := recover(); r != nil {
fmt.Printf(fmt.Sprintf("Recover from fail sending %s metrics for %s", metric, c.packageName), zap.Any("recover", r))
}
}
c.sendMemoryMetrics(protectFromPanic)
c.sendCPUMetrics(protectFromPanic)
}
func (c *client) sendMemoryMetrics(f func(string)) {
count := 0
go func() {
defer func() {
f(memoryMetric)
}()
for {
memory, err := c.OSClient.GetMemory()
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
count++
if count == retries {
return
}
} else {
count = 0
EmitMemoryMetrics(c.packageName, memory.Total, memory.Used, memory.Cached, memory.Free)
time.Sleep(time.Duration(c.memoryIteration) * time.Millisecond)
}
}
}()
}
func (c *client) sendCPUMetrics(f func(string)) {
go func() {
defer func() {
f(cpuMetric)
}()
for {
before, err := c.OSClient.GetCPU()
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
return
}
time.Sleep(time.Duration(c.cpuIteration) * time.Millisecond)
after, err := c.OSClient.GetCPU()
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
return
}
total := float64(after.Total - before.Total)
EmitCPUMetrics(c.packageName,
total,
float64(after.User-before.User)/total*100,
float64(after.System-before.System)/total*100,
float64(after.Idle-before.Idle)/total*100)
}
}()
}
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
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.
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.
I am trying to write a go function that will read in lines in a text file, sort them (alphabetize), and overwrite them back to the file. Right now, I am able to essentially emulate cat, but I can't seem to be able to manipulate the contents of the elements in read_line.
func sort() {
ff, _ := os.OpenFile(file, os.O_RDWR, 0666)
f := bufio.NewReader(ff)
for {
read_line, _ := f.ReadString('\n')
fmt.Print(read_line)
if read_line == "" {
break
}
}
ff.Close()
}
when i use ReadString, how can i store each line into a slice (or is there a better way to store them so i can manipulate them)? Then I would use the sort package in a manner similar to this:
sorted := sort.Strings(lines)
then, to write to the file, i am using something similar to the following, although i have not included it because i have not yet gotten "sort" to work:
io.WriteString(ff, (lines + "\n"))
Thank you in advance for any suggestions!
For example,
package main
import (
"bufio"
"fmt"
"os"
"sort"
)
func readLines(file string) (lines []string, err os.Error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
r := bufio.NewReader(f)
for {
const delim = '\n'
line, err := r.ReadString(delim)
if err == nil || len(line) > 0 {
if err != nil {
line += string(delim)
}
lines = append(lines, line)
}
if err != nil {
if err == os.EOF {
break
}
return nil, err
}
}
return lines, nil
}
func writeLines(file string, lines []string) (err os.Error) {
f, err := os.Create(file)
if err != nil {
return err
}
defer f.Close()
w := bufio.NewWriter(f)
defer w.Flush()
for _, line := range lines {
_, err := w.WriteString(line)
if err != nil {
return err
}
}
return nil
}
func main() {
file := `lines.txt`
lines, err := readLines(file)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
sort.Strings(lines)
err = writeLines(file, lines)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
This is a pretty simple way of doing it.
import (
"bytes"
"io/ioutil"
"sort"
)
// allow [][]byte to implement the sort.Interface interface
type lexicographically [][]byte
// bytes.Compare compares the byte slices lexicographically (alphabetically)
func (l lexicographically) Less(i, j int) bool { return bytes.Compare(l[i], l[j]) < 0 }
func (l lexicographically) Len() int { return len(l) }
func (l lexicographically) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func SortFile(name string) error {
content, err := ioutil.ReadFile(name)
if err != nil {
return err
}
lines := bytes.Split(content, []byte{'\n'})
sort.Sort(lexicographically(lines))
content = bytes.Join(lines, []byte{'\n'})
return ioutil.WriteFile(name, content, 0644)
}
since you are about to sort the lines, you pretty much need to read the entire file. you can either slurp the file with io/ioutil.ReadAll or you can just write a small slurp function. once you have the lines of the file, sorting them can be done with a call to sort.Strings. i'll add a perhaps overly verbose version which hopefully illustrates how it can be done. i also recomment reading this excellent explanation on how go's sort package works: Go's sort package
package main
import (
"os"
"bufio"
"fmt"
"sort"
)
// slurp file into slice of lines/strings
func slurp(f string) (lines []string, e os.Error) {
var fd *os.File
var line string
var bufRd *bufio.Reader
var keepReading bool = true
fd, e = os.Open(f)
if e != nil {
return nil, e
}
defer fd.Close()
bufRd = bufio.NewReader(fd)
for keepReading {
line, e = bufRd.ReadString('\n')
switch e {
case nil:
lines = append(lines, line)
case os.EOF:
lines = append(lines, line)
keepReading = false
default:
return lines, e
}
}
return lines, nil
}
// test stuff out..
func main() {
if len(os.Args) > 1 {
lines, e := slurp(os.Args[1])
if e != nil {
fmt.Fprintf(os.Stderr,"%s\n", e)
os.Exit(1)
}
fmt.Println("\n----- unsorted -----\n")
for _, line := range lines {
fmt.Printf("%s", line)
}
fmt.Println("\n----- sorted -----\n")
sort.Strings(lines)
for _, line := range lines {
fmt.Printf("%s", line)
}
}
}
note that the sort is in-place, so it does not return anything
Just wondering how convenient is using Unix's sort for this purpose. I know it's not possible to have this code working in many deployment scenarios, but I see it worth it to mention as an option:
package main
import (
"os"
"os/exec"
)
func main() {
file := "file.txt"
command := []string{"sort", file, "-o", file}
cmd := exec.Command(command[0], command[1:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
panic(err)
}
}
Thoughts?