Go 語言 獲取URL

2023-03-14 16:48 更新

原文鏈接:https://gopl-zh.github.io/ch1/ch1-05.html


1.5. 獲取URL

對于很多現(xiàn)代應(yīng)用來說,訪問互聯(lián)網(wǎng)上的信息和訪問本地文件系統(tǒng)一樣重要。Go語言在net這個強大package的幫助下提供了一系列的package來做這件事情,使用這些包可以更簡單地用網(wǎng)絡(luò)收發(fā)信息,還可以建立更底層的網(wǎng)絡(luò)連接,編寫服務(wù)器程序。在這些情景下,Go語言原生的并發(fā)特性(在第八章中會介紹)顯得尤其好用。

為了最簡單地展示基于HTTP獲取信息的方式,下面給出一個示例程序fetch,這個程序?qū)@取對應(yīng)的url,并將其源文本打印出來;這個例子的靈感來源于curl工具(譯注:unix下的一個用來發(fā)http請求的工具,具體可以man curl)。當(dāng)然,curl提供的功能更為復(fù)雜豐富,這里只編寫最簡單的樣例。這個樣例之后還會多次被用到。

gopl.io/ch1/fetch

// Fetch prints the content found at a URL.
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
)

func main() {
    for _, url := range os.Args[1:] {
        resp, err := http.Get(url)
        if err != nil {
            fmt.Fprintf(os.Stderr, "fetch: %v\n", err)
            os.Exit(1)
        }
        b, err := ioutil.ReadAll(resp.Body)
        resp.Body.Close()
        if err != nil {
            fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err)
            os.Exit(1)
        }
        fmt.Printf("%s", b)
    }
}

這個程序從兩個package中導(dǎo)入了函數(shù),net/http和io/ioutil包,http.Get函數(shù)是創(chuàng)建HTTP請求的函數(shù),如果獲取過程沒有出錯,那么會在resp這個結(jié)構(gòu)體中得到訪問的請求結(jié)果。resp的Body字段包括一個可讀的服務(wù)器響應(yīng)流。ioutil.ReadAll函數(shù)從response中讀取到全部內(nèi)容;將其結(jié)果保存在變量b中。resp.Body.Close關(guān)閉resp的Body流,防止資源泄露,Printf函數(shù)會將結(jié)果b寫出到標(biāo)準(zhǔn)輸出流中。

$ go build gopl.io/ch1/fetch
$ ./fetch http://gopl.io
<html>
<head>
<title>The Go Programming Language</title>title>
...

HTTP請求如果失敗了的話,會得到下面這樣的結(jié)果:

$ ./fetch http://bad.gopl.io
fetch: Get http://bad.gopl.io: dial tcp: lookup bad.gopl.io: no such host

譯注:在大天朝的網(wǎng)絡(luò)環(huán)境下很容易重現(xiàn)這種錯誤,下面是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函數(shù)來終止進程,并且返回一個status錯誤碼,其值為1。

練習(xí) 1.7: 函數(shù)調(diào)用io.Copy(dst, src)會從src中讀取內(nèi)容,并將讀到的結(jié)果寫入到dst中,使用這個函數(shù)替代掉例子中的ioutil.ReadAll來拷貝響應(yīng)結(jié)構(gòu)體到os.Stdout,避免申請一個緩沖區(qū)(例子中的b)來存儲。記得處理io.Copy返回結(jié)果中的錯誤。

練習(xí) 1.8: 修改fetch這個范例,如果輸入的url參數(shù)沒有 http:// 前綴的話,為這個url加上該前綴。你可能會用到strings.HasPrefix這個函數(shù)。

練習(xí) 1.9: 修改fetch打印出HTTP協(xié)議的狀態(tài)碼,可以從resp.Status變量得到該狀態(tài)碼。



以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號