GoLang之網絡

GoLang之網絡

 

Go語言標準庫裏提供的net包,支持基於IP層、TCP/UDP層及更高層面(如HTTP、FTP、SMTP)的網絡操做,其中用於IP層的稱爲Raw Socket。html

net包的Dial()函數用於建立網絡鏈接,函數原型以下:web

func Dial(net, addr string) (Conn, error)

其中net參數是網絡協議的名字,addr參數是IP地址或域名;若是鏈接成功,返回鏈接對象,不然返回error。json

 

目前,Dial()函數支持以下幾種網絡協議:"tcp"、"udp"、"ip"、"ip6"等,例如:api

conn, err := net.Dial("tcp", "192.168.0.10:2100")    // TCP鏈接
conn, err := net.Dial("udp", "192.168.0.12:975")    // UDP鏈接
conn, err := net.Dial("ip4:icmp", "www.baidu.com")  // ICMP鏈接

在成功鏈接鏈接後,能夠使用conn的Write()和Read()方法讀寫數據。數組

實際上,Dial()函數是對DialTCP()、DialUDP()、DialIP()、DialUnix()函數的封裝:網絡

func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error)
func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error)
func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error)
func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err error)

 

 

下面是一個TCP示例程序:數據結構

func checkError(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) 
        os.Exit(1)
    }   
}

func readFully(conn net.Conn) ([]byte, error) {
    defer conn.Close()

    result := bytes.NewBuffer(nil)
    var buf [512]byte
    for {
        n, err := conn.Read(buf[0:]) 
        result.Write(buf[0:n])
        if err != nil {
            if err == io.EOF {
                break 
            }   

            return nil, err 
        }   
    }   

    return result.Bytes(), nil 
}

func main() {
    
    addr := "127.0.0.1:80"
    conn, err := net.Dial("tcp", addr)
    checkError(err)

    _, err = conn.Write([]byte("GET /api/v3/get HTTP/1.1\r\n\r\n"))
    checkError(err)

    result, err := readFully(conn)
    checkError(err)

    fmt.Println(string(result))

    os.Exit(0)
}

 

 

 


HTTP協議

Go語言標準庫內建提供了net/http包,涵蓋了HTTP客戶端和服務端的具體實現。tcp

HTTP客戶端

net/http包的Client類型提供了以下幾個方法:函數

func (c *Client) Get(url string) (r *Response, err error)
func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err error)
func (c *Client) PostForm(url string, data url.Values) (r *Response, err error)
func (c *Client) Head(url string) (r *Response, err error)
func (c *Client) Do(req *Request) (r *Response, err error)

 

以GET方法爲例:網站

resp, err := http.Get("http://cre.mix.sina.com.cn/api/v3/get")

if err != nil {
  fmt.Println("get failed", err)
  return
}

defer resp.Body.Close()

io.Copy(os.Stdout, resp.Body)

上面這段代碼請求一個網站首頁,並將其內容打印到標準輸出流中。

 若是但願對請求作更多的控制,能夠使用DO()方法:

req, err := http.NewRequest("GET", "http://cre.mix.sina.com.cn/api/v3/get", nil)

req.Header.Add("User-Agent", "Go GO")

client := &http.Client{}

resp, err := client.Do(req)

 

 

HTTP服務端

使用net/http包提供的下面兩個方法

func ListenAndServe(addr string, handler Handler) error
func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error

ListenAndServe()函數有2個參數,第一個參數addr即監聽地址,第二個參數表示服務端處理程序,一般爲空,使用默認的http.DefaultServeMux進行處理。

 

服務端的業務邏輯使用http.Handle()或http.HandleFunc(),會默認注入http.DefaultServeMux中,如:

http.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
    })

http.ListenAndServe(":8001", nil)

 

 


RPC協議

在Go中,標準庫提供的net/rpc包實現了PRC協議須要的相關細節,開發者能夠很方便地使用該包編寫RPC的服務端和客戶端程序。

 

 

 

 

 


 json處理

在Web開發領域中,JSON被普遍用於web服務端程序和客戶端之間的數據通訊。

Go語言內建對JSON的支持,使用encoding/json標準庫,開發者能夠輕鬆使用Go程序生成和解析JSON格式的數據。

func Marshal(v interface{}) ([]byte, error)
func Unmarshal(vdata []byte, v interface{}) error

 

JSON編碼的一個例子:

type Book struct {
    Title string
    Authors [] string
    Publisher string
    IsPublished bool
    Price float32
}

func main() {

    gobook := Book {
        "Go programming",
        []string { "XuShiwei", "HughLv", "Johnson"},
        "isturing.com.cn",
        true,
        9.99,
    }   

    
    // encode
    b, err := json.Marshal(gobook)  // 變量b 是一個[]byte類型
    if err == nil {
        fmt.Println(b)
    }   

    // decode
    var book Book
    json.Unmarshal(b, &book)
    fmt.Println(book)
}

當咱們調用json.Marshal(gobook)函數時,會遞歸遍歷gobook對象,若是發現gobook這個數據結構實現了json.Marshaler接口且包含有效的值,Marshal()就會調用其MarshalJSON()方法將該數據結構生成JSON格式的文本。

Go語言的大多數類型均可以轉化爲有效的JSON文本,但channel、complex和函數這幾種類型除外;而對於指針,會轉化爲指針所指向的值,若是指針指向的是零值,那麼null將做爲轉化後輸出的結果。具體的轉化規則以下:

  • 布爾值轉化爲JSON的bool類型;
  • 浮點數和整型轉化爲JSON的number類型;
  • 字符串將以UTF-8編碼轉化爲Unicode字符集的字符串;
  • 數組和切片轉化爲JSON的array類型,但[]byte類型的值會被轉化爲Base64編碼後的字符串,slice類型的零值會被轉化爲null;
  • 結構體轉化爲JSON的object類型,而且只有結構體中以大寫字母開頭的可被導出的字段纔會被轉化輸出;
  • 轉化一個map類型的數據結構時,該數據的類型必須是map[string] T。
相關文章
相關標籤/搜索