GoLang之網絡


GoLang之網絡

 

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

net包的Dial()函數用於創建網絡連接,函數原型如下:

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

其中net參數是網絡協議的名字,addr參數是IP地址或域名;如果連接成功,返回連接對象,否則返回error。

 

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

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客戶端和服務端的具體實現。

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。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM