变量一开始是空的,但后来有了一个值。

huangapple go评论95阅读模式
英文:

variable is empty but later has a value

问题

我正在尝试开发一个Terraform提供程序,但是我在第一个请求体的问题上遇到了问题。以下是代码:

type Body struct {
    id string
}

func resourceServerCreate(d *schema.ResourceData, m interface{}) error {
    key := d.Get("key").(string)
    token := d.Get("token").(string)
    workspace_name := d.Get("workspace_name").(string)
    board_name := d.Get("board_name").(string)

    resp, err := http.Post("https://api.trello.com/1/organizations?key="+key+"&token="+token+"&displayName="+workspace_name,"application/json",nil)

    if err != nil {
        log.Fatalln(err)
    }

    defer resp.Body.Close()

    //读取body
    body := new(Body)
    json.NewDecoder(resp.Body).Decode(body)

    log.Println("[ORCA MADONNA] il log funzia "+body.id)
    d.Set("board_id",body.id)

    resp1, err1 := http.Post("https://api.trello.com/1/boards?key="+key+"&token="+token+"&idOrganization="+body.id+"&=&name="+board_name,"application/json",nil)
    
    if err1 != nil {
        log.Fatalln(resp1)
    }

    defer resp1.Body.Close()
    
    d.SetId(board_name)

    return resourceServerRead(d, m)
}

日志为空,但第二次调用有日志并且正常工作。这是怎么可能的?

英文:

I'm trying to develop a Terraform provider but I have a problem of the first request body. Here is the code:

type Body struct {
    id string
}

func resourceServerCreate(d *schema.ResourceData, m interface{}) error {
    key := d.Get("key").(string)
    token := d.Get("token").(string)
    workspace_name := d.Get("workspace_name").(string)
    board_name := d.Get("board_name").(string)


    resp, err := http.Post("https://api.trello.com/1/organizations?key="+key+"&token="+token+"&displayName="+workspace_name,"application/json",nil)

    if err != nil {
            log.Fatalln(err)
    }

    defer resp.Body.Close()

    //lettura body.
    body := new(Body)
    json.NewDecoder(resp.Body).Decode(body)

    log.Println("[ORCA MADONNA] il log funzia "+body.id)
    d.Set("board_id",body.id)

    resp1, err1 := http.Post("https://api.trello.com/1/boards?key="+key+"&token="+token+"&idOrganization="+body.id+"&=&name="+board_name,"application/json",nil)
    
    if err1 != nil {
            log.Fatalln(resp1)
    }

    defer resp1.Body.Close()
    
    d.SetId(board_name)
    


    return resourceServerRead(d, m)

}

In the log is empty, but the second call have it and work fine. How is it possible?

答案1

得分: 1

Go语言不强制检查错误响应,因此很容易犯一些愚蠢的错误。如果你检查了Decode()的返回值,你就会立即发现一个问题。

err := json.NewDecoder(resp.Body).Decode(body)
if err != nil {
    log.Fatal("Decode error: ", err)
}

> Decode error: json: Unmarshal(non-pointer main.Body)

所以你最直接的修复方法是使用&来传递Decode()的指针:

json.NewDecoder(resp.Body).Decode(&body)

另外需要注意的是,一些编程编辑器会为你突出显示这个错误:

变量一开始是空的,但后来有了一个值。


这里有一个工作示例,包括一个修正后的Body结构,如json.Marshal(struct) returns "{}"所述:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "time"
)

type JSON = map[string]interface{}
type JSONArray = []interface{}

func ErrFatal(err error, msg string) {
    if err != nil {
        log.Fatal(msg+": ", err)
    }
}

func handleTestRequest(w http.ResponseWriter, req *http.Request) {
    w.Write(([]byte)("{\"id\":\"yourid\"}"))
}

func launchTestServer() {
    http.HandleFunc("/", handleTestRequest)
    go http.ListenAndServe(":8080", nil)
    time.Sleep(1 * time.Second) // allow server to get started
}

// Medium: "Don’t use Go’s default HTTP client (in production)"
var restClient = &http.Client{
    Timeout: time.Second * 10,
}

func DoREST(method, url string, headers, payload JSON) *http.Response {

    requestPayload, err := json.Marshal(payload)
    ErrFatal(err, "json.Marshal(payload")

    request, err := http.NewRequest(method, url, bytes.NewBuffer(requestPayload))
    ErrFatal(err, "NewRequest "+method+" "+url)

    for k, v := range headers {
        request.Header.Add(k, v.(string))
    }

    response, err := restClient.Do(request)
    ErrFatal(err, "DoRest client.Do")
    return response
}

type Body struct {
    Id string `json:"id"`
}

func clientDemo() {
    response := DoREST("POST", "http://localhost:8080", JSON{}, JSON{})
    defer response.Body.Close()
    var body Body
    err := json.NewDecoder(response.Body).Decode(&body)
    ErrFatal(err, "Decode")
    fmt.Printf("Body: %#v\n", body)
}

func main() {
    launchTestServer()
    for i := 0; i < 5; i++ {
        clientDemo()
    }
}
英文:

Go doesn't force you to check error responses, therefore it's easy to make silly mistakes. Had you checked the return value from Decode(), you would have immediately discovered a problem.

err := json.NewDecoder(resp.Body).Decode(body)
if err != nil {
log.Fatal(&quot;Decode error: &quot;, err)
}

> Decode error: json: Unmarshal(non-pointer main.Body)

So your most immediate fix is to use &amp; to pass a pointer to Decode():

json.NewDecoder(resp.Body).Decode(&amp;body)

Also of note, some programming editors will highlight this mistake for you:

变量一开始是空的,但后来有了一个值。


Here's a working demonstration, including a corrected Body structure as described at json.Marshal(struct) returns “{}”:

package main
import (
&quot;bytes&quot;
&quot;encoding/json&quot;
&quot;fmt&quot;
&quot;log&quot;
&quot;net/http&quot;
&quot;time&quot;
)
type JSON = map[string]interface{}
type JSONArray = []interface{}
func ErrFatal(err error, msg string) {
if err != nil {
log.Fatal(msg+&quot;: &quot;, err)
}
}
func handleTestRequest(w http.ResponseWriter, req *http.Request) {
w.Write(([]byte)(&quot;{\&quot;id\&quot;:\&quot;yourid\&quot;}&quot;))
}
func launchTestServer() {
http.HandleFunc(&quot;/&quot;, handleTestRequest)
go http.ListenAndServe(&quot;:8080&quot;, nil)
time.Sleep(1 * time.Second) // allow server to get started
}
// Medium: &quot;Don’t use Go’s default HTTP client (in production)&quot;
var restClient = &amp;http.Client{
Timeout: time.Second * 10,
}
func DoREST(method, url string, headers, payload JSON) *http.Response {
requestPayload, err := json.Marshal(payload)
ErrFatal(err, &quot;json.Marshal(payload&quot;)
request, err := http.NewRequest(method, url, bytes.NewBuffer(requestPayload))
ErrFatal(err, &quot;NewRequest &quot;+method+&quot; &quot;+url)
for k, v := range headers {
request.Header.Add(k, v.(string))
}
response, err := restClient.Do(request)
ErrFatal(err, &quot;DoRest client.Do&quot;)
return response
}
type Body struct {
Id string `json:&quot;id&quot;`
}
func clientDemo() {
response := DoREST(&quot;POST&quot;, &quot;http://localhost:8080&quot;, JSON{}, JSON{})
defer response.Body.Close()
var body Body
err := json.NewDecoder(response.Body).Decode(&amp;body)
ErrFatal(err, &quot;Decode&quot;)
fmt.Printf(&quot;Body: %#v\n&quot;, body)
}
func main() {
launchTestServer()
for i := 0; i &lt; 5; i++ {
clientDemo()
}
}

huangapple
  • 本文由 发表于 2021年7月30日 22:07:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/68592318.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定