2016-09-21 7 views
0

最近私はゴランのループのために私を投げつけた何かを見つけました。ゼロがhttp.NewRequestに直接渡されたときGoLang - インターフェイスを受け入れる関数にnilを渡す

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

このコードはcreateRequestNoBody機能で動作しますが、呼び出し元の関数にnil*bytes.BufferセットでcreateRequestを呼び出すときには、パニックを生成します。 io.Readerインターフェイスをある

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

HTTPライブラリでNewRequest機能は、次のプロトタイプを持っています。

なぜ変数にnilが渡されたのかわからないので、NewRequestのbodyはNilになりません。

誰もがcreateRequestメソッドがパニックに陥る理由を説明できますか? data = createRequest("GET", "https://google.com", nil)のnilパラメータは、NewRequestメソッドの中でnil以外の値になりますか?

+3

[FAQ:なぜnilエラー値がnilと等しくないのですか?](https://golang.org/doc/faq#nil_error) – JimB

+4

[nil値を非表示にする理由、ここでゴランが失敗する理由を理解する] (http://stackoverflow.com/questions/29138591/hiding-nil-values-understanding-why-golang-fails-here) – icza

+0

リンク@ JimBありがとう、確かにそれを説明します。それがcreateRequest関数の間で渡されると、インタフェースで型を取得し、それは(nil、nil)の代わりに(* bytes.Buffer、nil)として次の関数に渡されます。 NewRequest(nil、nil)または(* bytes.Buffer、nil)を呼び出す前の 'data'の値です。私はそれがいつ(* bytes.Buffer、nil)になるかは分かりません。 – soluwalana

答えて

0

@JimBは彼のコメントで正しいです。以下のコードスニペットは

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

オブジェクトのタイプが実際に(* bytes.Buffer、NIL)であることを示しているランの出力は次のようになります。body io.Readerがインタフェースであるので

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

とポインタbytes.Buffernilポインタを渡すと、特定の型へのポインタではなく、nil以外のインターフェイスになります。

関連する問題