How can I return user.Class.Name string in reflectCallArgs. Is it impossible?
type User struct {
Class struct {
Name string
}
}
var user = &User{}
reflectCallArgs := func(src interface{}) string {
//how to get this string?
return "user.Class.Name"
}
reflectCallArgs(user.Class.Name)
The nearest thing you can get is the filename and line number where the function is being called, by querying runtime.Caller. https://golang.org/pkg/runtime/#Caller
func Caller(skip int) (pc uintptr, file string, line int, ok bool)
Caller reports file and line number information about function invocations on the calling goroutine's stack. The argument skip is the number of stack frames to ascend, with 0 identifying the caller of Caller. (For historical reasons the meaning of skip differs between Caller and Callers.) The return values report the program counter, file name, and line number within the file of the corresponding call. The boolean ok is false if it was not possible to recover the information.
However, you need to have access to that file and be able to parse the file (or that single line) to get "caller arguments string".
Related
I am using https://github.com/labstack/echo in one of the projects. I am using c.QueryParam to parse the query parameter and its values. One of the values contains a + symbol in it and it converts them to a space character (which is correct). However, I would like to retain the + character in the value.
Ex: http://localhost:8080?param=test+test
fmt.Println(c.QueryParam("param"))
Right now it outputs test test. However, I am expecting the output as test+test. Is it possible to achieve it using c.QueryParam?
You can get the raw query and then parse the parameter and it's value
func hello(c echo.Context) error {
//to get the raw query
fmt.Println(c.Request().URL.RawQuery)
return c.String(http.StatusOK, "Hello, World!")
}
Then you can use strings.split(rawQuery,"=") to get the parameter and it's value.
You can write a custom helper function like below -
func CustomQueryParam(c echo.Context, name string) string {
qParams := make(map[string]string)
for _, singleQueryParamStr := range strings.Split(c.QueryString(), "&") {
val := strings.Split(singleQueryParamStr, "=")
qParams[val[0]] = val[1]
}
return qParams[name]
}
func TestGet(c echo.Context) error {
param := CustomQueryParam(c, "param")
fmt.Println(param)
return c.JSON(http.StatusOK, map[string]interface{}{
"message": "request is successful",
})
}
Now, the output is as your expection. It prints test+test. But what actually CustomQueryParam do?
Okay, let's explore the insight. Suppose, the api call is -
http://localhost:8080?param=test1+test2¶m2=test3
The CustomQueryParam function will take an echo.Context instance and the query param name as function parameters.
Then, inside for loop the whole query string i.e. in our case which is param=test1+test2¶m2=test3 is split by & and stored into string slice made by each query param string ([]string{"param=test1+test2", "param2=test3"}).
After that, we iterate over each query param string and again split into a string slice of two values having first value as param name and second value as param value. For example, for first query param string, the resultant output is like below -
"param=test1+test2" => []string{"param", "test1+test2"}
Then, the first value (param name) is assigned as map key and second value (param value) as map value.
After finishing above process for every query string, the map value by query param name (which is the parameter of this function) is returned.
One of the interesting fact about this custom function is that it returns empty string if query param is not found.
This program does not compile. It shows that the Env method is not available on the struct sample on method call. I can access the Env variable directly in the main program, but I'm curious to know why this is not compiling.
package main
//Sample is a struct
type Sample struct {
Env string
}
func main() {
pa := &Sample{Env: "acd"}
pa.call()
}
func (p *Sample) call() *Sample.Env {
return &p.Env
}
Function types are defined by the keyword func, followed by an optional receiver, followed by the function name, the parameter list between parentheses (which may be empty), and the result list (which may be empty), and then the function body.
The result list (zero or more types) is the contract for what the function will return. It can be a list of types or a list of named parameters including their types.
In your function definition for call():
func (p *Sample) call() *Sample.Env {
Your result list does not meet this expectation. *Sample.Env is a pointer to the Env property of type Sample, but not a type itself.
Your function returns value &p.Env. If you modify your function signature so that the result list is simply the type of &p.Env, then your program will run. p.Env is a string, therefore &p.Env is a pointer to a string. *string is the type "pointer to a string." Therefore if you change your function signature to this your code will work:
func (p *Sample) call() *string {
See:
Function Types
Types
Post script
The return type of call() is *string -- that is, a pointer to a string. So to print it you simply dereference it to a string with the asterisk:
env := pa.call()
fmt.Printf("Env is %s\n", *env)
I have an issue with my function. I'm getting a
final function parameter must have type
For this method
func (s *BallotaApi) PostUser(c endpoints.Context,userReq Users) (userRes Users, error) {
c.Debugf("in the PostUser method")
user := userManger.login(userReq)//return a Users Type
return user, nil
I read those threads but I can't figure out where I'm wrong. It looks like I declared everything.
can-you-declare-multiple-variables-at-once-in-go
go-function-declaration-syntax
If you are naming your return parameters, you must name all of them
(userRes Users, err error)
That way, return statements can apply.
As mentioned in Function type:
Within a list of parameters or results, the names (IdentifierList) must either all be present or all be absent.
If you try to name one and not the other, as in this example, you will get:
func a() (b int, error) {
return 0, nil
}
# command-line-arguments
/tmp/sandbox170113103/main.go:9: final function parameter must have type
Dave C reminds us that:
Named returns should normally be limited to helping make better/clearer godoc documentation or when you need to change return values in a deferred closure.
Other than that they should be avoided.
Somehow my error validations are duplicated when I use valid global variable like below
var (
valid validation.Validation
)
func validationInit() validation.Validation {
valid := validation.Validation{}
return valid
}
But when I move valid := validation.Validation{} to my model function it works fine without any duplicates like below:
func AddClub(name string) (id int64, error []*validation.ValidationError) {
club := Club{Name: name}
valid := validation.Validation{}
How am I able to not duplicate this valid across each function but reuse variable without results being incremented and duplicated?
Since your validationInit() func returns a validation.Validation value and not a pointer to it, you cannot return the same global variable from multiple functions or from multiple invocations of the same function.
If you really want this, you have to return a pointer to the global variable, else a copy of the value of the global variable will be returned.
Example:
var valid validation.Validation
func someFunc() *valid.Validation {
// You can access the global variable valid here, you can also modify it
return &valid
}
But this is most likely not what you want. This would not allow you to have 2 different validation.Validation values exist at the same time returned by your functions.
I suggest you to leave out the global variable, and just create a new validation.Validation value each time it is needed and return that new value (either by value or a pointer to it).
I have a Go function that has interface{} as a parameter. When I call the function with string, it will cast one alloc/ns. Why?
func foo(...interface{}) error {
....
}
func use() {
var str = "use it"
e := foo(str)
_ = e
}
Internally, an interface variable is a two word structure. The first word is a pointer to the information about the dynamic type of the variable. The second word will either (a) contain the variable's dynamic value if it will fit in a word, or (b) contain a pointer to memory holding the dynamic value if it is larger.
A string variable is larger than a word, since it holds both it's length and a pointer to the underlying character data. So storing a string in a an interface variable involves allocating some memory to hold that value.