• 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
    
    "))
        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。
  • 相关阅读:
    python 类继承演示范例的代码
    C#监控指定目录的文件变化的代码
    如何开启红米手机4X的ROOT超级权限
    C# 发送电子邮件源码片段
    android中使用afinal一行源码显示网络图片
    (详细)华为畅享7 SLA-AL00的usb调试模式在哪里打开的流程
    C#自定义FTP访问类的代码
    C#的String.Split 分割字符串用法详解的代码
    红米Note 5A完美卡刷开发版获得ROOT超级权限的方法
    C# 类如何声明索引器以提供对类的类似数组的访问的代码
  • 原文地址:https://www.cnblogs.com/chenny7/p/4499164.html
Copyright © 2020-2023  润新知