对于很多现代应用来说,访问互联网上的信息和访问本地文件系统一样重要。Go语言在net这个强大package的帮助下提供了一系列的package来做这件事情,使用这些包可以更简单地用网络收发信息,还可以建立更底层的网络连接,编写服务器程序。在这些情景下,Go语言原生的的并发特性显得尤其好用。
下面给出一个示例程序fetch,这个程序获取对应的url,并将其源文件打印出来。
// Fetch prints the content found at a URL
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
//读取url
var url string
if len(os.Args) != 2 {
fmt.Fprintln(os.Stderr, "Paramater number error!")
os.Exit(1)
} else {
url = os.Args[1]
}
//get请求url
resp, err := http.Get(url)
if err != nil {
fmt.Fprintf(os.Stderr, "fetch url(%s) failed: %v\n", url, err)
os.Exit(1)
}
//处理请求返回内容
data, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "fetch: reading error: %v\n", err)
os.Exit(1)
}
fmt.Printf("%s", data)
}
http.Get函数是创建HTTP请求的函数,如果获取过程没有出错,那么会在resp这个结构体中得到访问的请求结果。resp的Body字段包括一个可读的服务器响应流。ioutil.ReadAll函数从response中读取到全部内容,将其结果保存在变量data中,这是一个字节切片。resp.Body.Close关闭resp的Body流,防止资源泄露。
事实上,我们在处理服务器响应信息时只是简单的输出,当前的逻辑举个形象的例子就是:我们从输入口(服务器响应流)获取水(响应信息),放到了池子(内存)中,然后把水接到了输出口(os.Stdout)。我们完全可以直接把输入口和输出口连接起来即可,示例代码如下:
// Fetch prints the content found at a URL
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
//读取url
var url string
if len(os.Args) != 2 {
fmt.Fprintln(os.Stderr, "Paramater number error!")
os.Exit(1)
} else {
url = os.Args[1]
}
//get请求url
resp, err := http.Get(url)
if err != nil {
fmt.Fprintf(os.Stderr, "fetch url(%s) failed: %v\n", url, err)
os.Exit(1)
}
//处理请求返回内容
_, err = io.Copy(os.Stdout, resp.Body)
resp.Body.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "fetch: reading error: %v\n", err)
os.Exit(1)
}
}
因为我们没有对响应信息进行处理,因此可以直接使用os.Copy将信息从可读的服务器响应流拷贝到可写的标准输出流。