Beego raw sql - Type conversion issue - sqlite

Here is the code used inside the Beego MVC architecture.
var maps []orm.Params
//Pallets Completed already.
o.Raw("Select SUM(Things) as AllTheThings FROM SomeTable").Values(&maps)
numThings := strconv.Atoi(maps[0]["AllTheThings"].(string))
c.Data["Stuff"] = maps[0]["AllTheThings"]
Error:
multiple-value strconv.Atoi() in single-value context
Trying to figure out how I can get data out with our ORM and type cast it so arithmetic can be done on it.
Any more details please let me know.

strconv.Atoi has a signature of:
func Atoi(s string) (int, error)
you should check the error before using the result, like so:
var maps []orm.Params
//Pallets Completed already.
o.Raw("Select SUM(Things) as AllTheThings FROM SomeTable").Values(&maps)
numThings, err := strconv.Atoi(maps[0]["AllTheThings"].(string))
if err != nil {
// couldn't convert
}
c.Data["Stuff"] = maps[0]["AllTheThings"]

Related

Why do I not get an error when running this, but I do get an error when running this `a,b := 2`?

I am very new to Go and a beginner to programming. I cam across this:
res, err := http.Get("URL_HERE")
if err != nil {
log.Fatal(err)
}
Can anyone please help me understand this? Does http.Get return two values? Is err a pointer?
Yes, http.Get returns two values. The documentation of http.Get is here, and this is its signature:
func Get(url string) (resp *Response, err error)
err is a value of the error type, which is an interface so it could be nil. From its documentation:
The error built-in interface type is the conventional interface for
representing an error condition, with the nil value representing no
error.
I strongly suggest you start learning Go by completing the online tour, and then check out additional learning resources at https://learn.go.dev/

Golang: How to append pointer to slice to slice?

I'm a Golang newbie but I thought I had got the essentials of pointers and references straight, but apparently not:
I have a method that must return a []github.Repository, which is a type from the Github client in go.
The API call returns the results paginated so I must cycle until there's no more results, and add the result of each call to the allRepos variable, and return that. Here's what I have so far:
func (s *inmemService) GetWatchedRepos(ctx context.Context, username string) ([]github.Repository, error) {
s.mtx.RLock()
defer s.mtx.RUnlock()
opt := &github.ListOptions{PerPage: 20}
var allRepos []github.Repository
for {
// repos is of type *[]github.Repository
repos, resp, err := s.ghClient.Activity.ListWatched(ctx, "", opt)
if err != nil {
return []github.Repository{}, err
}
// ERROR: Cannot use repos (type []*github.Repository) as type github.Repository
// but dereferencing it doesn't work, either
allRepos = append(allRepos, repos...)
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return allRepos, nil
}
My question: how can I append the results of each call and return a result of type []github.Repository?
Also, why doesn't dereferencing work here? I've tried replacing allRepos = append(allRepos, repos...) with allRepos = append(allRepos, *(repos)...) but I get this error message:
Invalid indirect of (repos) (type []*github.Repository)
Well, something is not okay here:
You say in the comment that "repos is of type *[]github.Repository" but the compiler's error message indicates that repos is of type []*Repository". The compiler is never (except when buggy) wrong.
Note that *[]github.Repository and []*Repository are completely different types, especially the second is not a slice of Repositories and you cannot (really, there is no way) dereference these pointers during append(): You have to write a loop and dereference each slice item and append one by one.
What is strange too: github.Repository and Repository seem to be two different types one from package github, the other from the current package. Again, you'll have to get that straight too.
Note that there are no references in Go. Stop thinking about these immediately: This is a concept from other languages which is not helpful (as inexistent) in Go.
In your example the dereferencing is not correct. You should make it like this:
allRepos = append(allRepos, *repos...)
Here a simple example with dereferencing a pointer to a slice of string. https://play.golang.org/p/UDzaG5z8Pf

Reflect on Time type in go

I am trying to write a csv parser using the example provided here. It works great for all native types but I am having trouble with any structs that contain a timestamp of type time.Time. It exits with an error of "cannot convert this type".
This is the code.
//For each field in a given struct...
//Get a field
val := sv.Field(i)
// this is necessary because Kind can't tell
// distinguish between a primitive type
// and a type derived from it. We're looking
// for a Value interface defined on
// the pointer to this value
_, ok := val.Addr().Interface().(Value)
if ok {
val = val.Addr()
kind = value_k
} else {
switch Kind {
case reflect.Int, reflect.Int16, reflect.Int8,
reflect.Int32, reflect.Int64:
kind = int_k
case reflect.Uint, reflect.Uint16, reflect.Uint8,
reflect.Uint32, reflect.Uint64:
kind = uint_k
case reflect.Float32, reflect.Float64:
kind = float_k
case reflect.String:
kind = string_k
default:
// Kind is Struct here
kind = value_k
_, ok := val.Interface().(Value)
if !ok {
err = os.NewError("cannot convert this type ")
this = nil
return
}
}
}
What this code does is take an interface and a reader. It attempts to match the field headers in the reader (csv file) with field names in the interface. It also reflects on the interface (struct) and collects positional a type information for later setting the fields in the iterator. It is this step that is failing for non-native types.
I've tried a few methods to work around this but the only thing that seems to work is changing the timestamp to a string. I am undoubtedly missing something and would greatly appreciate some guidance.

How to force passing parameter as a pointer in Go?

I am implementing an application layer network protocol which uses JSON in Go.
func ReadMessage(conn net.Conn, returnMessage interface{}) bool {
messageBytes := // read from conn
error := json.Unmarshal(messageBytes, &returnMessage)
if error != nil {
return false
}
return true
}
The function takes a struct as its second parameter where the message is unmarshalled. The function can be called like this:
msg := MessageType1{}
ok := ReadMessage(conn, &msg)
Or without the ampersand (&)
msg := MessageType1{}
ok := ReadMessage(conn, msg)
which will compile, but not do what is should as the struct is passed as a copy, not as a reference and the original msg will remain empty. So I'd like to force passing the struct by reference and catch this error at compile time.
Changing the parameter type to *interface{} will not compile:
cannot use &msg (type *MessageType1) as type *interface {} in function argument:
*interface {} is pointer to interface, not interface
Is there some Go style way of doing this correctly?
There is not a way to do this in the function declaration.
You can use reflection though and panic at runtime when the argument is not a pointer.
However maybe you should consider changing the design of your code. The concrete type of the argument should not matter. It either implements the interface you need or not.
Demo: http://play.golang.org/p/7Dw0EkFzbx
Since Go 1.18 you can do this using generics:
func test[T any](dst *T) {
//Do something with dst
}
You can't enforce this as *T always has the method set of T. Thus both implement the interface.
From the spec:
The method set of any other type T consists of all methods with receiver type T. The method set of the corresponding pointer type *T is the set of all methods with receiver *T or T (that is, it also contains the method set of T).
What you can do instead is to use the language's ability to return multiple values in your function, as Volker already stated:
func ReadMessage(conn net.Conn) (interface{}, bool) {
var returnMessage interface{}
messageBytes := // read from conn
error := json.Unmarshal(messageBytes, &returnMessage)
if error != nil {
return nil, false
}
return returnMessage, true
}
You should also consider not returning type interface{} but some meaningful type.

Replace wrapping struct with a type declaration in Go

I want to extend the regexp from the Go standard library to be able to define my own methods. I use the following struct:
type RichRegexp struct {
*regexp.Regexp
}
As you can see, this struct contains nothing but the wrapped regexp.Regexp. So I wonder whether I could replace this with a simple type declaration like this:
type RichRegexp regexp.Regexp
But how should I write the following func then?
func Compile(expression string) (*RichRegexp, error) {
regex, err := regexp.Compile(expression)
if err != nil {
return nil, err
}
return &RichRegexp{regex}, nil // How to do this?
}
I tried to convert regexp.Regexp to my RichRegexp but it didn't compile. What is the general pattern to return a custom type which wraps a underlying type?
You can use a conversion, but in this case it is necessary, that your type definition is not a pointer:
type MyRegexp *regexp.Regexp // Doesn't work
This is backed by the spec:
The receiver type must be of the form T or *T where T is a type name.
The type denoted by T is called the receiver base type; it must not be
a pointer or interface type and it must be declared in the same
package as the method. The method is said to be bound to the base type
and the method name is visible only within selectors for that type.
However, you can do this:
type MyRegexp regexp.Regexp
As you're handling values now, you can do the following:
x := regexp.MustCompile(".*")
y := MyRegexp(*x)
And you have your own regexp type.
Full code at play: http://play.golang.org/p/OWNdA2FinN
As a general pattern, I would would say:
If it's unlikely to change and you don't need to store arbitrary values, use
a type conversion.
If you need to store values along with your embedded type, use a struct.
If your code is likely to change and needs to support large varieties of things,
define an interface and don't use embedding / type conversion.
package main
import (
"regexp"
)
type RichRegexp regexp.Regexp
func Compile(expression string) (*RichRegexp, error) {
regex, err := regexp.Compile(expression)
if err != nil {
return nil, err
}
return (*RichRegexp)(regex), nil
}
func main() {
Compile("foo")
}
Also here: http://play.golang.org/p/cgpi8z2CfF

Resources