如何在Go中使用.Read函数?

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

How do I use the .Read function in Go?

问题

尝试使用Go的http包时,我无法弄清楚.Read的语法。下面被标记为HERE的部分是我唯一能编译成功的代码,尽管我尝试了其他几种方式,但都被编译器拒绝了。

package main
import "fmt";
import "http";
import "os";

func main () {
    kinopiko_flair := "http://stackoverflow.com/users/flair/181548.json";
    response, _, error := http.Get (kinopiko_flair);
    if (error != nil) {
        // 我也想打印出错误信息。
        fmt.Printf ("Error getting %s\n", kinopiko_flair);
        os.Exit (1);
    }
    fmt.Printf ("Status is %s\n", response.Status);
    var nr int;
    var buf []byte;
    nr, error = response.Body.Read (buf); // HERE
    if (error != nil) {
        // 我也想打印出错误信息。
        fmt.Printf ("Error reading response.\n");
        os.Exit (1);
    }
    response.Body.Close ();
    fmt.Printf ("Got %d bytes\n", nr);
    fmt.Printf ("Got '%s'\n", buf);
}

URL是正确的,因为wget可以正常获取它,但是当我运行这段代码时,buf只是一个空字符串,而nr始终为零。我需要做什么才能从response中获取数据?编译器拒绝了我尝试的.ReadAll和其他方法。

输出结果如下:
<pre>
Status is 200 OK
Got 0 bytes
Got ''
</pre>

英文:

Trying to use Go's http package, I can't work out the syntax of .Read. The following marked by HERE is the only thing I have got to compile, although I tried several other things which were all rejected by the compiler.

package main
import &quot;fmt&quot;;
import &quot;http&quot;;
import &quot;os&quot;;

func main () {
    kinopiko_flair := &quot;http://stackoverflow.com/users/flair/181548.json&quot;;
    response, _, error := http.Get (kinopiko_flair);
    if (error != nil) {
	    // I want to print out the error too.
	    fmt.Printf (&quot;Error getting %s\n&quot;, kinopiko_flair);
	    os.Exit (1);
    }
    fmt.Printf (&quot;Status is %s\n&quot;, response.Status);
    var nr int;
    var buf []byte;
    nr, error = response.Body.Read (buf); // HERE
    if (error != nil) {
	    // I want to print out the error too.
	    fmt.Printf (&quot;Error reading response.\n&quot;);
	    os.Exit (1);
    }
    response.Body.Close ();
    fmt.Printf (&quot;Got %d bytes\n&quot;, nr);
    fmt.Printf (&quot;Got &#39;%s&#39;\n&quot;, buf);
}

The URL is OK, since wget gets it fine, but when I run this buf is just an empty string and nr is always zero. What do I need to do to get the data out of response? The compiler rejected .ReadAll and other things I tried.

The output looks like this:
<pre>
Status is 200 OK
Got 0 bytes
Got ''
</pre>

答案1

得分: 8

尝试给切片buf指定一个大小,例如:

 buf := make([]byte,128);

Reader将读取给定缓冲区的len()个字节。

来自io.go

// Reader是包装基本Read方法的接口。
//
// Read将最多len(p)个字节读入p。它返回读取的字节数(0 <= n <= len(p))和遇到的任何错误。
// 即使Read返回n < len(p),
// 在调用期间它可能会将p的所有内容用作临时空间。
// 如果有一些数据可用但不足len(p)个字节,Read通常会返回可用的数据而不是阻塞等待更多数据。
//
// 在输入流的末尾,Read返回0, os.EOF。
// Read可能返回一个非零的字节数和一个非nil的错误。
// 特别地,用尽输入的Read可能返回n > 0, os.EOF。
英文:

Try giving the slice buf a size, e.g.

 buf := make([]byte,128);

Reader reads up to len() of the buffer it is given.

From io.go

// Reader is the interface that wraps the basic Read method.
//
// Read reads up to len(p) bytes into p.  It returns the number of bytes
// read (0 &lt;= n &lt;= len(p)) and any error encountered.
// Even if Read returns n &lt; len(p),
// it may use all of p as scratch space during the call.
// If some data is available but not len(p) bytes, Read conventionally
// returns what is available rather than block waiting for more.
//
// At the end of the input stream, Read returns 0, os.EOF.
// Read may return a non-zero number of bytes with a non-nil err.
// In particular, a Read that exhausts the input may return n &gt; 0, os.EOF.

答案2

得分: 0

尝试从教程中适应猫的例子:

fmt.Printf("状态是 %s\n", response.Status);
var nr int;

const NBUF = 512;
var buf [NBUF]byte;

for {
    switch nr, _ := response.Body.Read(&buf); true {
    case nr < 0:
        os.Exit(1);
    case nr == 0:  // EOF
        return;
    case nr > 0:
        if nw, _ := os.Stdout.Write(buf[0:nr]); nw != nr {
            fmt.Printf("错误\n");
        }
    }
}

输出:

$ ./8.out 
状态是 200 OK
{"id":181548,"gravatarHtml":"<img src=\"http://www.gravatar.com/avatar/f4a286fa31d1359ee92113823a70a738?s=50&amp;d=identicon&amp;r=PG\" height=\"50\" width=\"50\" alt=\"\">","profileUrl":"http://stackoverflow.com/users/181548/kinopiko","displayName":"Kinopiko","reputation":"4,674","badgeHtml":"<span title=\"1 gold badge\"><span class=\"badge1\">&#9679;</span><span class=\"badgecount\">1</span></span><span title=\"5 silver badges\"><span class=\"badge2\">&#9679;</span><span class=\"badgecount\">5</span></span><span title=\"21 bronze badges\"><span class=\"badge3\">&#9679;</span><span class=\"badgecount\">21</span></span>"}
英文:

Trying to adapt the cat example from the tutorial:

fmt.Printf (&quot;Status is %s\n&quot;, response.Status);
var nr int;

const NBUF = 512;
var buf [NBUF]byte;

for {
    switch nr, _ := response.Body.Read(&amp;buf); true {
    case nr &lt; 0:
        os.Exit(1);
    case nr == 0:  // EOF
        return;
    case nr &gt; 0:
        if nw, _ := os.Stdout.Write(buf[0:nr]); nw != nr {
            fmt.Printf(&quot;error\n&quot;);
        }
    }
}

Output:

$ ./8.out 
Status is 200 OK
{&quot;id&quot;:181548,&quot;gravatarHtml&quot;:&quot;\u003cimg src=\&quot;http://www.gravatar.com/avatar/f4a286fa31d1359ee92113823a70a738?s=50&amp;amp;d=identicon&amp;amp;r=PG\&quot; height=\&quot;50\&quot; width=\&quot;50\&quot; alt=\&quot;\&quot;\u003e&quot;,&quot;profileUrl&quot;:&quot;http://stackoverflow.com/users/181548/kinopiko&quot;,&quot;displayName&quot;:&quot;Kinopiko&quot;,&quot;reputation&quot;:&quot;4,674&quot;,&quot;badgeHtml&quot;:&quot;\u003cspan title=\&quot;1 gold badge\&quot;\u003e\u003cspan class=\&quot;badge1\&quot;\u003e&amp;#9679;\u003c/span\u003e\u003cspan class=\&quot;badgecount\&quot;\u003e1\u003c/span\u003e\u003c/span\u003e\u003cspan title=\&quot;5 silver badges\&quot;\u003e\u003cspan class=\&quot;badge2\&quot;\u003e&amp;#9679;\u003c/span\u003e\u003cspan class=\&quot;badgecount\&quot;\u003e5\u003c/span\u003e\u003c/span\u003e\u003cspan title=\&quot;21 bronze badges\&quot;\u003e\u003cspan class=\&quot;badge3\&quot;\u003e&amp;#9679;\u003c/span\u003e\u003cspan class=\&quot;badgecount\&quot;\u003e21\u003c/span\u003e\u003c/span\u003e&quot;}

答案3

得分: 0

这里buf的大小未定义,所以buf被创建为大小为0的切片。
创建一个指定大小的buf可能会有所帮助。
buf = make([]byte, 500)

$ cat slice.go 
package main

import (
	"fmt";
	"net/http";
	"os";
)

func main() {
	kinopiko_flair := "http://stackoverflow.com"
	response, error := http.Get(kinopiko_flair)
	if error != nil {
		// 我也想打印出错误信息。
		fmt.Printf("获取%s时出错\n", kinopiko_flair)
		os.Exit(1)
	}
	fmt.Printf("状态是%s\n", response.Status)
	var nr int
	var buf []byte
	fmt.Printf("初始时:切片的容量为%d,长度为%d\n ", cap(buf), len(buf))
	buf = make([]byte, 500) // 这样做应该会有所帮助
	fmt.Printf("更新后:切片的容量为%d,长度为%d\n ", cap(buf), len(buf))
	nr, error = response.Body.Read(buf) // 这里
	if error != nil {
		// 我也想打印出错误信息。
		fmt.Printf("读取响应时出错。\n")
		os.Exit(1)
	}
	response.Body.Close()
	fmt.Printf("获得%d字节\n", nr)
	fmt.Printf("获得'%s'\n", buf)
}

输出

$ go run slice.go 
    状态是200 OK
     初始时:切片的容量为0,长度为0 
     更新后:切片的容量为500,长度为500 
     获得500字节
    获得'<!DOCTYPE html>
    
    
        <html class="html__responsive html__unpinned-leftnav">
    
        <head>
    
            <title>Stack Overflow - Where Developers Learn, Share, &amp; Build Careers</title>
            <link rel="shortcut icon" href="https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico?v=4f32ecc8f43d">
            <link rel="apple-touch-icon image_src" href="https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon.png?v=c78bd457575a">
            <link rel="search" type="application/opensear'
英文:

Here size of buf is not defined so buf is created with 0 size.
creating buf with some size should help.
buf = make([]byte, 500)

$ cat slice.go 
package main

import (
	&quot;fmt&quot;
	&quot;net/http&quot;
	&quot;os&quot;
)

func main() {
	kinopiko_flair := &quot;http://stackoverflow.com&quot;
	response, error := http.Get(kinopiko_flair)
	if error != nil {
		// I want to print out the error too.
		fmt.Printf(&quot;Error getting %s\n&quot;, kinopiko_flair)
		os.Exit(1)
	}
	fmt.Printf(&quot;Status is %s\n&quot;, response.Status)
	var nr int
	var buf []byte
	fmt.Printf(&quot;Initially :capacity of slice is %d and length is %d \n &quot;, cap(buf), len(buf))
	buf = make([]byte, 500) // THIS SHOULD HELP
	fmt.Printf(&quot;UPDATE: capacity of slice is %d and length is %d \n &quot;, cap(buf), len(buf))
	nr, error = response.Body.Read(buf) // HERE
	if error != nil {
		// I want to print out the error too.
		fmt.Printf(&quot;Error reading response.\n&quot;)
		os.Exit(1)
	}
	response.Body.Close()
	fmt.Printf(&quot;Got %d bytes\n&quot;, nr)
	fmt.Printf(&quot;Got &#39;%s&#39;\n&quot;, buf)
}

Output

$ go run slice.go 
    Status is 200 OK
     Initially :capacity of slice is 0 and length is 0 
     UPDATE: capacity of slice is 500 and length is 500 
     Got 500 bytes
    Got &#39;&lt;!DOCTYPE html&gt;
    
    
        &lt;html class=&quot;html__responsive html__unpinned-leftnav&quot;&gt;
    
        &lt;head&gt;
    
            &lt;title&gt;Stack Overflow - Where Developers Learn, Share, &amp;amp; Build Careers&lt;/title&gt;
            &lt;link rel=&quot;shortcut icon&quot; href=&quot;https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico?v=4f32ecc8f43d&quot;&gt;
            &lt;link rel=&quot;apple-touch-icon image_src&quot; href=&quot;https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon.png?v=c78bd457575a&quot;&gt;
            &lt;link rel=&quot;search&quot; type=&quot;application/opensear&#39;

huangapple
  • 本文由 发表于 2009年11月12日 18:06:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/1721212.html
匿名

发表评论

匿名网友

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

确定