I've come across a scenario where
func main (c *gin.Context){
if err := g.Bind(&data); err != nil {
log.Fatalln(err)
helper.TraceLog(err)
helper.Fail(c, helper.INPUT_PARAMS_ERROR, "", err)
return
}
}
func Fail(c *gin.Context, errorCode string, result string, message interface{}) {
response := Response{}
response.Code = errorCode
response.Result = message
response.Message = result
json.Marshal(response)
c.JSON(http.StatusBadRequest, response)
}
Is it possible that I do not have to pass gin to Fail func? I've tried every solution I can think of and nothing works.
The reason I'm doing this is to make the code looks more simple and clean.
What I'm looking for is something like this:
func main (c *gin.Context){
if err := g.Bind(&data); err != nil {
log.Fatalln(err)
helper.TraceLog(err)
helper.Fail(helper.INPUT_PARAMS_ERROR, "", err)
return
}
}
func Fail(errorCode string, result string, message interface{}) {
var c *gin.Context
response := Response{}
response.Code = errorCode
response.Result = message
response.Message = result
json.Marshal(response)
c.JSON(http.StatusBadRequest, response)
}
Related
How I can assign result from rendering template to send this value as json, for ajax call
my example:
func Load(c echo.Context) error {
params := map[string]any{
"btn_style": "btn-light btn-sm",
}
if err := c.Render(http.StatusOK, "test.tmpl", params); err != nil {
return err
}
payload := []byte(fmt.Sprintf(`{"payload":"%s"}`, c.Get("tmpl").(string)))
fmt.Println(string(payload))
return c.JSONBlob(http.StatusOK, (payload))
}
Render function
func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
var buf bytes.Buffer
err := t.templates.ExecuteTemplate(&buf, name, data)
if err != nil {
return err
}
c.Set("tmpl", buf.String())
return t.templates.ExecuteTemplate(w, name, data)
}
I'm currently trying to figure out the Ethereum code and have learned how to send transactions to the blockchain using the client module.Here is an example of a contract call function:
func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
var hex hexutil.Bytes
err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), toBlockNumArg(blockNumber))
if err != nil {
return nil, err
}
return hex, nil
}
, where CallContext defined as:`
func (c *Client) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
if result != nil && reflect.TypeOf(result).Kind() != reflect.Ptr {
return fmt.Errorf("call result parameter must be pointer or nil interface: %v", result)
}
msg, err := c.newMessage(method, args...)
if err != nil {
return err
}
op := &requestOp{ids: []json.RawMessage{msg.ID}, resp: make(chan *jsonrpcMessage, 1)}
if c.isHTTP {
err = c.sendHTTP(ctx, op, msg)
} else {
err = c.send(ctx, op, msg)
}
if err != nil {
return err
}
// dispatch has accepted the request and will close the channel when it quits.
switch resp, err := op.wait(ctx, c); {
case err != nil:
return err
case resp.Error != nil:
return resp.Error
case len(resp.Result) == 0:
return ErrNoResult
default:
return json.Unmarshal(resp.Result, &result)
}`
And my question is: Where is the handler for these messages implemented in go - ethereum?
For example:
switch msg.name:
case "eth_call": ...
case "eth_sendTx": ...
...
I'm trying to send a JSON inside the body of the message using AMQP and receive it. The message sends without any error, however I can't unmarshall it on the other side. I get a unexpected end of JSON input error.
JSON:
var jsonStr = []byte(`
{
"name": "Test",
"phone_number": "12345"
}`)
err = files.SendMessageToCore(jsonStr, "event.saveorder")
if err != nil {
logr.Error("Error sending a message to rabbitmq:", fmt.Sprintf("%v", err))
}
SendMessageToCore function:
func SendMessageToCore(body []byte, routingKey string) error {
pb, err := GetRabbitPublisher()
if err != nil {
return err
}
var message amqp.Message
message.Exchange = "example"
message.RoutingKey = routingKey
message.Body = body
messageByte, err := json.Marshal(message)
if err != nil {
return err
}
err = (*pb).Publish(amqp.Message{Exchange: message.Exchange, RoutingKey: message.RoutingKey, Body: messageByte})
if err != nil {
return err
}
fmt.Println("Message was successfully sent")
return nil
}
Unmarshalling part:
func SaveOrderEventHandler(mes amqp.Message) *amqp.Message {
var incomingMessage amqp.Message
if err := json.Unmarshal(mes.Body, &incomingMessage); err != nil {
fmt.Println(err)
return nil
}
var user foodDomain.User
if err := json.Unmarshal(incomingMessage.Body, &user); err != nil {
fmt.Println("Error unmarshalling incomingMessage body: ", err) //Error appears here
return nil
}
fmt.Println(user.PhoneNumber)
return nil
}
User struct:
type User struct {
Name string `json:"name"`
PhoneNumber string `json:"phone_number"`
}
In your SendMessageToCore you already initialized amqb.Message. No need to re-initialize in the Publish func, just pass your initialized message. Also, your json string body is already in jsonByte, so no need to marshal it once more.
For instance -
func SendMessageToCore(body []byte, routingKey string) error {
pb, err := GetRabbitPublisher()
if err != nil {
return err
}
var message amqp.Message
message.Exchange = "example"
message.RoutingKey = routingKey
message.Body = body
err = (*pb).Publish(message)
if err != nil {
return err
}
fmt.Println("Message was successfully sent")
return nil
}
And your mes already in amqp.Message type, so no need to unmarshal mes.Body into amqp.Message type variable.
Just directly unmarshal your mes.Body into user.
func SaveOrderEventHandler(mes amqp.Message) *amqp.Message {
var user foodDomain.User
if err := json.Unmarshal(mes.Body, &user); err != nil {
fmt.Println(err)
return nil
}
fmt.Println(user.PhoneNumber)
return nil
}
I'm implementing a Go wrapper for a REST API. It basically parses JSON and should return the appropriate struct type. I find myself doing a lot of this:
// GetBlueprintDetails returns details about a blueprint
func (c *Client) GetBlueprintDetails(projectID string, blueprintID string) (*BlueprintDetails, *APIError) {
path := fmt.Sprintf("projects/%s/blueprints/%s", projectID, blueprintID)
res, err := c.Request("GET", path, nil, nil)
if err != nil {
return nil, err
}
var ret BlueprintDetails
e := json.Unmarshal(res.Body, &ret)
if e != nil {
return nil, &APIError{Error: &e}
}
return &ret, nil
}
// GetProjects returns a list of projects for the user
func (c *Client) GetProjects() (*[]Project, *APIError) {
res, err := c.Request("GET", "projects", nil, nil)
if err != nil {
return nil, err
}
var ret []Project
e := json.Unmarshal(res.Body, &ret)
if e != nil {
return nil, &APIError{Error: &e}
}
return &ret, nil
}
The only difference between the two functions is the type of the unmarshaled struct basically. I know there are no generic in Go, but there has to be a pattern to make this more DRY.
Any ideas?
You may create a MakeRequest function that does the http request part and unmarshal the json to struct
Here is how you may do it, have a look at the MakeRequest function
// GetBlueprintDetails returns details about a blueprint
func (c *Client) GetBlueprintDetails(projectID string, blueprintID string) (*BlueprintDetails, *APIError) {
path := fmt.Sprintf("projects/%s/blueprints/%s", projectID, blueprintID)
bluePrintDetails = new(BlueprintDetails)
err := c.MakeRequest("GET", path, bluePrintDetails)
return bluePrintDetails, err
}
// GetProjects returns a list of projects for the user
func (c *Client) GetProjects() (*[]Project, *APIError) {
projects = make([]Project, 0)
err := c.MakeRequest("GET", "project", &projects)
return &projects, err
}
func (c *Client) MakeRequest(method string, path string, response interface{}) *APIError {
res, err := c.Request(method, path, nil, nil)
if err != nil {
return nil, err
}
e := json.Unmarshal(res.Body, response)
if e != nil {
return &APIError{Error: &e}
}
return nil
}
I stumbled accross something that threw me for a loop in golang recently.
package main
import (
"net/http"
"bytes"
"fmt"
"io/ioutil"
)
func createRequest(method, uri string, data *bytes.Buffer) string {
req, err := http.NewRequest(method, uri, data)
if err != nil {
return ""
}
req.Close = true
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return ""
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return ""
}
return string(respBody)
}
func createRequestNoBody(method, uri string) string {
req, err := http.NewRequest(method, uri, nil)
if err != nil {
return ""
}
req.Close = true
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return ""
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return ""
}
return string(respBody)
}
func main() {
data := createRequestNoBody("GET", "http://google.com")
if len(data) != 0 {
fmt.Println("First Request Ok")
}
data = createRequest("GET", "https://google.com", nil)
if len(data) != 0 {
fmt.Println("Second Request OK")
}
}
This code works in the createRequestNoBody function when nil is passed directly to http.NewRequest but it produces a panic when calling createRequest with the *bytes.Buffer set to nil in the calling function.
The NewRequest function in the http library has the following prototype:
func NewRequest(method, urlStr string, body io.Reader) (*Request, error)
Where io.Reader is an interface.
I'm not sure why the nil being passed through a variable would cause body in NewRequest to become non nil.
Can anyone explain why createRequest method results in a panic? How is the nil parameter at data = createRequest("GET", "https://google.com", nil) becoming non nil inside of the NewRequest method?
#JimB was correct in his comment. This snippet of code below shows that the type of the object is indeed (*bytes.Buffer, nil)
package main
import (
"bytes"
"fmt"
"reflect"
"errors"
"io"
)
func NewRequest(method, urlStr string, body io.Reader) (error) {
if body == nil {
fmt.Println("Body Is Nil")
return nil
}
fmt.Println(reflect.TypeOf(body).Elem())
return errors.New("NOT NIL")
}
func createRequest(method, uri string, data *bytes.Buffer) string {
fmt.Println("Type Of data is ", reflect.TypeOf(data).Elem())
if data == nil {
fmt.Println("data is nil")
}
err := NewRequest(method, uri, data)
if err != nil {
return err.Error()
}
return "OK"
}
func createRequestNoBody(method, uri string) string {
err := NewRequest(method, uri, nil)
if err != nil {
return err.Error()
}
return "OK"
}
func main() {
data := createRequestNoBody("GET", "http://google.com")
if len(data) != 0 {
fmt.Println("First Request Ok")
}
data = createRequest("GET", "https://google.com", nil)
if len(data) != 0 {
fmt.Println("Second Request Not OK")
}
}
The output of the run looks like:
Body Is Nil
First Request Ok
Type Of data is bytes.Buffer
data is nil
bytes.Buffer
Second Request Not OK
Since body io.Reader is an interface and not a pointer to a particular type when you pass in a nil pointer of type bytes.Buffer it will be a non nil interface.