获取URL
对于很多现代应用来说,访问互联网上的信息和访问本地文件系统一样重要。Go
语言在 net
这个强大 package
的帮助下提供了一系列的 package
来做这件事情,使用这些包可以更简单地用网络收发信息,还可以建立更底层的网络连接,编写服务器程序。在这些情景下,Go
语言原生的并发特性(在第八章中会介绍)显得尤其好用。
为了最简单地展示基于 HTTP
获取信息的方式,下面给出一个示例程序 fetch
,这个程序将获取对应的 url
,并将其源文本打印出来;这个例子的灵感来源于 curl
工具(译注:unix
下的一个用来发 http
请求的工具,具体可以 man curl
)。当然,curl
提供的功能更为复杂丰富,这里只编写最简单的样例。这个样例之后还会多次被用到。
Unresolved include directive in modules/ROOT/pages/ch1/ch1-05.adoc - include::example$/ch1/fetch/main.go[]
这个程序从两个 package
中导入了函数,net/http
和 io/ioutil
包,http.Get
函数是创建 HTTP
请求的函数,如果获取过程没有出错,那么会在 resp
这个结构体中得到访问的请求结果。resp
的 Body
字段包括一个可读的服务器响应流。 ioutil.ReadAll
函数从 response
中读取到全部内容;将其结果保存在变量 b
中。resp.Body.Close
关闭 resp
的 Body
流,防止资源泄露,Printf
函数会将结果 b
写出到标准输出流中。
$ go build gopl.io/ch1/fetch
$ ./fetch http://gopl.io
<html>
<head>
<title>The Go Programming Language</title>title>
...
HTTP
请求如果失败了的话,会得到下面这样的结果:
$ ./fetch http://bad.gopl.io
fetch: Get http://bad.gopl.io: dial tcp: lookup bad.gopl.io: no such host
译注:在大天朝的网络环境下很容易重现这种错误,下面是 Windows
下运行得到的错误信息:
$ go run main.go http://gopl.io
fetch: Get http://gopl.io: dial tcp: lookup gopl.io: getaddrinfow: No such host is known.
无论哪种失败原因,我们的程序都用了 os.Exit
函数来终止进程,并且返回一个 status
错误码,其值为 1
。
练习 1.7: 函数调用 io.Copy(dst, src)
会从 src
中读取内容,并将读到的结果写入到 dst
中,使用这个函数替代掉例子中的 ioutil.ReadAll
来拷贝响应结构体到 os.Stdout
,避免申请一个缓冲区(例子中的 b
)来存储。记得处理 io.Copy
返回结果中的错误。
练习 1.8: 修改 fetch
这个范例,如果输入的 url
参数没有 http://
前缀的话,为这个 url
加上该前缀。你可能会用到 strings.HasPrefix
这个函数。
练习 1.9: 修改 fetch
打印出 HTTP
协议的状态码,可以从 resp.Status
变量得到该状态码。
Unresolved include directive in modules/ROOT/pages/ch1/ch1-05.adoc - include::example$/ch1/exercise/main.go[]