dongxing4805 2017-12-29 20:42
浏览 74
已采纳

GoLang WebServer在Json Response上发送对param结构的描述

So here is the deal : I have been working on a huge system (PHP) for a couple years, and now, I decided to give up part of heavy jobs for golang scripts.

So far, I replicated a few php scripts to a go version. Then, I am able to benchmark which option is better ( ok, I know go is faster, but I need curl or sockets to comunication, so, I have to check if it is still worth ) .

One of the scripts just generate a random code, check if this new code is already in use ( on mysql db ), if not, record the new code and return it, if is already in use, just recursive call the function again until find an exclusive code. pretty simple one.

I already had this code generator in php, so, wrote new one in go to be called as http/post with json params. Using linux terminal, I call it as

curl -H [headers] -d [jsondata] [host]

and I get back a pretty simple json

{"locator" : "XXXXXX"}

After, I wrote a simple php script to call the scripts and check how long each took to complete, something like :

<?php
public function indexAction()
    {
    $phpTime = $endPHP = $startPHP =
    $goTime = $endGO = $startGO = 0;

// my standard function already in use


    ob_start();

    $startPHP = microtime(true);
    $MyCodeLocator =  $this->container->get('MyCodeLocator')->Generate(22, 5);
    $endPHP = microtime(true);

    ob_end_clean();


    sleep(1);
    // Lets call using curl
    $data = array("comon" => "22", "lenght" => "5");
    $data_string = json_encode($data);

    ob_start();
    $startGO = microtime(true);



    $ch = curl_init('http://localhost:8888/dev/fibootkt/MyCodeGenerator');
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Content-Length: ' . strlen($data_string))
    );

    $result = curl_exec($ch);
    curl_close($ch);
    $endGO = microtime(true);
    ob_end_clean();

    $result_rr = json_decode($result);

    // tst just echo the variable in a nice way, second parameter means no kill execution
    tst($result, 1); // HERE IS MY PROBLEM, please read below
    tst($result_rr, 1); // IT SHOW NULL

    sleep(1);

// just to have params for comparision, always try by shell script
    ob_start();
    $startShell = microtime(true);;

    $exec =  "curl -H \"Content-Type: application/json\" -d '{\"comon\":\"22\"}' http://localhost:8888/dev/fibootkt/MyCodeGenerator";
    $output = shell_exec($exec);
    $endShell  = microtime(true);
    ob_end_clean();

    tst(json_decode($output),1); // here show a stdclass with correct value
    tst($output,1); // here shows a json typed string ready to be converted

    // and here it is just for show the execution time ...
    $phpTime = $endPHP - $startPHP;
    $goTime = $endGO - $startGO ;
    $shellTime = $endShell - $startShell;

    tst("php " . $phpTime, 1);
    tst("curl ". $goTime, 1);
    tst("shell " . $shellTime, 1);

And I get the results from GO : By Shell Script :

{"locator" : "DPEWX22"} 

So, this one is pretty and easy decode to a stdobj.

But, using curl, the operation is faster ! So, I want to use it. But, the curl request responds something like :

{"Value":"string","Type":{},"Offset":26,"Struct":"CodeLocatorParams","Field":"lenght"}
{"locator":"DPEWX22"}

And when I try to decode it, I get a null as result !!!

CodeLocatorParams the struct type I use in go to get the post params, as show below

so, here is my question : Why GO is returning this ? how to avoid it.

I have another similar go script which take no params and responds a similar json ( but in this case, a qrcode image path ) and it works fine !

My go function:

type CodeLocatorParams struct {
    Comon string `json:"comon"`
    Lenght int  `json:"lenght"`
}

func Generate(w http.ResponseWriter, r *http.Request) {


    data, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
    if err != nil {
        fmt.Println(err)
        panic(err)

    }
    if err := r.Body.Close(); err != nil {
        panic(err)
    }

// retrieve post data  and set it to params which is CodeLocatorParams type
    var params CodeLocatorParams
    if err := json.Unmarshal(data, &params ); err != nil {
        w.Header().Set("Content-Type", "application/json; charset=UTF-8")
        w.WriteHeader(422) // unprocessable entity
        if err := json.NewEncoder(w).Encode(err); err != nil {
            fmt.Println(err)
            panic(err)
        }
    }





    var result struct{
        Locator string `json:"locator"`
    }
// here actually comes the func that generates random code and return it as string, but for now, just set it static
    result.Locator = "DPEWX22"

    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    json.NewEncoder(w).Encode(result)


}
  • 写回答

1条回答 默认 最新

  • douhong1703 2017-12-29 21:19
    关注

    There is an error parsing the incoming JSON. This error is written to the response as {"Value":"string","Type":{},"Offset":26,"Struct":"CodeLocatorParams","Field":"lenght"}. The handler continues to execute and writes the normal response {"locator":"DPEWX22"}.

    Here's how what to fix:

    • After writing error response, return from the handler.
    • The input JSON has lenght as a string value. Either change the struct field from int to string or modify the input to pass an integer.
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 win10权限管理,限制普通用户使用删除功能
  • ¥15 minnio内存占用过大,内存没被回收(Windows环境)
  • ¥65 抖音咸鱼付款链接转码支付宝
  • ¥15 ubuntu22.04上安装ursim-3.15.8.106339遇到的问题
  • ¥15 blast算法(相关搜索:数据库)
  • ¥15 请问有人会紧聚焦相关的matlab知识嘛?
  • ¥15 网络通信安全解决方案
  • ¥50 yalmip+Gurobi
  • ¥20 win10修改放大文本以及缩放与布局后蓝屏无法正常进入桌面
  • ¥15 itunes恢复数据最后一步发生错误