1

最近、golang でループに陥る何かに出くわしました。

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")
   }
}

このコードは、createRequestNoBodynil が直接渡された場合に機能しますが、呼び出し元の関数でset を使用して呼び出すとhttp.NewRequestパニックが発生します。createRequest*bytes.Buffernil

http ライブラリの NewRequest 関数には、次のプロトタイプがあります。

func NewRequest(method, urlStr string, body io.Reader) (*Request, error)

インターフェイスはどこio.Readerにありますか。

nil が変数を介して渡されるとbody、NewRequest が非 nil になる理由がわかりません。

createRequestメソッドがパニックになる理由を誰か説明できますか? メソッドdata = createRequest("GET", "https://google.com", nil)内で非 nil になるときの nil パラメータはどのようになっていますか?NewRequest

4

1 に答える 1

0

@JimB のコメントは正しかった。以下のコード スニペットは、オブジェクトの型が実際に (*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")
   }
}

実行の出力は次のようになります。

Body Is Nil
First Request Ok
Type Of data is  bytes.Buffer
data is nil
bytes.Buffer
Second Request Not OK

はインターフェースであり、特定のタイプへのポインターではないため、タイプのポインターbody io.Readerを渡すと、非インターフェースになります。 nilbytes.Buffernil

于 2016-09-22T17:22:38.450 に答える