Go语言七篇入门教程六网络编程

目录
  • 1. Socket 编程
    • 1.1 Dial()函数
  • 2. HTTP 编程
    • 2.1 HTTP 客户端
    • 2.2 HTTP 服务端
      • 2.2.1 处理 HTTP 请求
  • 3. RPC 编程
    • 3.1 Go 语言中的 RPC 支持与处理
    • 3.2 Gob 简介
    • 3.3 设计优雅的 RPC 接口

1. Socket 编程

在 Go 语言中编写网络程序时,我们将看不到传统的编码形式。以前我们使用 Socket 编程时,会按照如下步骤展开。

建立 Socket:使用 socket()函数。

绑定 Socket:使用 bind()函数。

监听:使用 listen()函数。或者连接:使用 connect()函数。

接受连接:使用 accept()函数。

接收:使用 receive()函数。或者发送:使用 send()函数。
Go 语言标准库对此过程进行了抽象和封装。无论我们期望使用什么协议建立什么形式的连接,都只需要调用 net.Dial()即可。

1.1 Dial()函数

Dial()函数的原型如下:

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

其中 net 参数是网络协议的名字,addr 参数是IP 地址或域名,而端口号以:的形式跟随在地址或域名的后面,端口号可选。如果连接成功,返回连接对象,否则返回 error
我们来看一下几种常见协议的调用方式。

TCP 链接:

conn, err := net.Dial("tcp", "192.168.1.8:3000")

UDP链接:

conn, err := net.Dial("udp", "192.168.1.12:975")

ICMP链接(使用协议名称):

conn, err := net.Dial("ip4:icmp", "www.baidu.com")

ICMP链接(使用协议编号):

conn, err := net.Dial("ip4:1", "10.0.0.3")

在成功建立连接后,我们就可以进行数据的发送和接收。发送数据时,使用 connWrite()成员方法,接收数据时使用 Read()方法。

2. HTTP 编程

2.1 HTTP 客户端

Go 内置的 net/http 包提供了最简洁的 HTTP 客户端实现,我们无需借助第三方网络通信库(比如 libcurl)就可以直接使用 HTTP 中用得最多的 GETPOST 方式请求数据。

基本方法

net/http 包的 Client 类型提供了如下几个方法,让我们可以用最简洁的方式实现HTTP 请求:

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) (resp *Response, err error)

下面概要介绍这几个方法。

  • http.Get()

要请求一个资源,只需调用 http.Get()方法(等价于 http.DefaultClient.Get())即可,示例代码如下:

resp, err := http.Get("http://example.com/")
if err != nil { // 处理错误 ...
	return
}
defer resp.Body.close()
io.Copy(os.Stdout, resp.Body)

上面这段代码请求一个网站首页,并将其网页内容打印到标准输出流中。

  • http.Post()

要以POST 的方式发送数据,也很简单,只需调用 http.Post()方法并依次传递下面的 3 个参数即可:

请求的目标 URL将要 POST 数据的资源类型(MIMEType)数据的比特流([]byte 形式)

下面的示例代码演示了如何上传一张图片:

resp, err := http.Post("http://example.com/upload", "image/jpeg", &imageDataBuf)
if err != nil{ // 处理错误
	return
}
if resp.StatusCode != http.StatusOK {// 处理错误
	return
}
  • http.PostForm()

http.PostForm()方法实现了标准编码格式为 application/x-www-form-urlencoded的表单提交。下面的示例代码模拟 HTML 表单提交一篇新文章:

resp, err := http.PostForm("http://example.com/posts", url.Values{"title":
{"article title"}, "content": {"article body"}})
if err != nil{ // 处理错误
	return
}
  • http.Head()

HTTP 中的 Head 请求方式表明只请求目标 URL 的头部信息,即 HTTP Header 而不返回 HTTP
Body。Go 内置的 net/http 包同样也提供了 http.Head() 方法,该方法同 http.Get() 方法一样,
只需传入目标 URL 一个参数即可。下面的示例代码请求一个网站首页的 HTTP Header 信息:

resp, err := http.Head("http://baidu.com/")
  • (*http.Client).Do()

在多数情况下,http.Get()http.PostForm() 就可以满足需求,但是如果我们发起的
HTTP 请求需要更多的定制信息,我们希望设定一些自定义的 Http Header 字段,比如:

  • 设定自定义的"User-Agent"
  • 传递 Cookie

此时可以使用 net/httphttp.Client对象的 Do()方法来实现

req, err := http.NewRequest("GET", "http://baidu.com", nil)
// ...
req.Header.Add("User-Agent", "Gobook Custom User-Agent")
// ...
client := &http.Client{ //... }
resp, err := client.Do(req)

2.2 HTTP 服务端

2.2.1 处理 HTTP 请求

使用 net/http 包提供的 http.ListenAndServe() 方法,可以在指定的地址进行监听,开启一个 HTTP,服务端该方法的原型如下:

func ListenAndServe(addr string, handler Handler) error

该方法用于在指定的 TCP 网络地址 addr 进行监听,然后调用服务端处理程序来处理传入的连接请求。该方法有两个参数:第一个参数 addr 即监听地址;第二个参数表示服务端处理程序,通常为空,这意味着服务端调用 http.DefaultServeMux 进行处理,而服务端编写的业务逻辑处理程序 http.Handle()http.HandleFunc() 默认注入 http.DefaultServeMux 中,具体代码如下:

http.Handle("/foo", fooHandler)
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServe(":8080", nil))

net/http 包还提供 http.ListenAndServeTLS() 方法,用于处理 HTTPS 连接请求:

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

ListenAndServeTLS()ListenAndServe() 的行为一致,区别在于只处理 HTTPS 请求。此外,服务器上必须存在包含证书和与之匹配的私钥的相关文件,比如 certFile 对应 SSL证书文件存放路径,keyFile 对应证书私钥文件路径。如果证书是由证书颁发机构签署的,certFile 参数指定的路径必须是存放在服务器上的经由 CA认证过的 SSL 证书

3. RPC 编程

在 Go 中,标准库提供的 net/rpc 包实现了 RPC 协议需要的相关细节,开发者可以很方便地使用该包编写 RPC 的服务端和客户端程序,这使得用 Go 语言开发的多个进程之间的通信变得非常简单。

net/rpc 包允许 RPC 客户端程序通过网络或是其他 I/O 连接调用一个远端对象的公开方法(必须是大写字母开头、可外部调用的)。在 RPC 服务端,可将一个对象注册为可访问的服务,之后该对象的公开方法就能够以远程的方式提供访问。一个 RPC 服务端可以注册多个不同类型的对象,但不允许注册同一类型的多个对象。

一个对象中只有满足如下这些条件的方法,才能被 RPC 服务端设置为可供远程访问:

  • 必须是在对象外部可公开调用的方法(首字母大写);
  • 必须有两个参数,且参数的类型都必须是包外部可以访问的类型或者是 Go 内建支持的类型;
  • 第二个参数必须是一个指针;
  • 方法必须返回一个 error 类型的值。

以上 4 个条件,可以简单地用如下一行代码表示:

func (t *T) MethodName(argType T1, replyType *T2) error

在上面这行代码中,类型 T、T1 和 T2 默认会使用 Go 内置的 encoding/gob 包进行编码解码。

该方法(MethodName)的第一个参数表示由 RPC 客户端传入的参数,第二个参数表示要返回给 RPC 客户端的结果,该方法最后返回一个 error 类型的值。
RPC 服务端可以通过调用 rpc.ServeConn 处理单个连接请求。多数情况下,通过 TCP 或是 HTTP 在某个网络地址上进行监听来创建该服务是个不错的选择。

3.1 Go 语言中的 RPC 支持与处理

在 Go 中,标准库提供的net/rpc包实现了RPC 协议需要的相关细节,开发者可以很方便地使用该包编写 RPC 的服务端和客户端程序,这使得用 Go 语言开发的多个进程之间的通信变得非常简单。

net/rpc 包允许 RPC 客户端程序通过网络或是其他 I/O 连接调用一个远端对象的公开方法(必须是大写字母开头、可外部调用的)。在RPC服务端,可将一个对象注册为可访问的服务,之后该对象的公开方法就能够以远程的方式提供访问。一个RPC服务端可以注册多个不同类型的对象,但不允许注册同一类型的多个对象。

一个对象中只有满足如下这些条件的方法,才能被RPC服务端设置为可供远程访问:

  • 必须是在对象外部可公开调用的方法(首字母大写);
  • 必须有两个参数,且参数的类型都必须是包外部可以访问的类型或者是Go内建支持的类型;
  • 第二个参数必须是一个指针;
  • 方法必须返回一个 error 类型的值。

以上 4 个条件,可以简单地用如下一行代码表示:

func (t *T) MethodName(argType T1, replyType *T2) error

在上面这行代码中,类型 T、T1 和 T2 默认会使用 Go 内置的 encoding/gob 包进行编码解码。关于 encoding/gob 包的内容,稍后我们将会对其进行介绍。

该方法(MethodName)的第一个参数表示由 RPC 客户端传入的参数,第二个参数表示要返回给 RPC 客户端的结果,该方法最后返回一个 error 类型的值。

RPC 服务端可以通过调用 rpc.ServeConn 处理单个连接请求。多数情况下,通过 TCP 或是 HTTP 在某个网络地址上进行监听来创建该服务是个不错的选择。

3.2 Gob 简介

Gob 是 Go 的一个序列化数据结构的编码解码工具,在Go标准库中内置 encoding/gob包以供使用。一个数据结构使用 Gob进行序列化之后,能够用于网络传输。

JSONXML这种基于文本描述的数据交换语言不同,Gob是二进制编码的数据流,并且 Gob 流是可以自解释的,它在保证高效率的同时,也具备完整的表达能力。

作为针对 Go的数据结构进行编码和解码的专用序列化方法,这意味着 Gob 无法跨语言使用。在 Gonet/rpc 包中,传输数据所需要用到的编码解码器,默认就是 Gob。由于Gob 仅局限于使用 Go 语言开发的程序,这意味着我们只能用 GoRPC 实现进程间通信。

然而,大多数时候,我们用Go编写的 RPC 服务端(或客户端),可能更希望它是通用的,与语言无关的,无论是 Python 、 Java 或其他编程语言实现的 RPC 客户端,均可与之通信。

3.3 设计优雅的 RPC 接口

Go 的 net/rpc 很灵活,它在数据传输前后实现了编码解码器的接口定义。这意味着,开发者可以自定义数据的传输方式以及 RPC 服务端和客户端之间的交互行为。
RPC 提供的编码解码器接口如下:

type ClientCodec interface {
	WriteRequest(*Request, interface{}) error
	ReadResponseHeader(*Response) error
	ReadResponseBody(interface{}) error
	Close() error
}

type ServerCodec interface {
	ReadRequestHeader(*Request) error
	ReadRequestBody(interface{}) error
	WriteResponse(*Response, interface{}) error
	Close() error
}

接口 ClientCodec 定义了 RPC 客户端如何在一个 RPC 会话中发送请求和读取响应。客户端程序通过 WriteRequest() 方法将一个请求写入到 RPC 连接中,并通过ReadResponseHeader()ReadResponseBody() 读取服务端的响应信息。当整个过程执行完毕后,再通过 Close()方法来关闭该连接。

接口 ServerCodec 定义了 RPC 服务端如何在一个 RPC 会话中接收请求并发送响应。服务端程序通过ReadRequestHeader()ReadRequestBody() 方法从一个 RPC 连接中读取 请求信息,然后再通过WriteResponse() 方法向该连接中的 RPC 客户端发送响应。当完成该过程后,通过 Close()方法来关闭连接。

通过实现上述接口,我们可以自定义数据传输前后的编码解码方式,而不仅仅局限于Gob。同样,可以自定义RPC服务端和客户端的交互行为。实际上,Go 标准库提供的 net/rpc/json包,就是一套实现了 rpc.ClientCodecrpc.ServerCodec 接口的 JSON-RPC 模块。

以上就是Go语言七篇入门教程六网络编程第的详细内容,更多关于Go语言网络编程的资料请关注我们其它相关文章!

(0)

相关推荐

  • Go语言编程入门超级指南

    1.序言 Golang作为一门出身名门望族的编程语言新星,像豆瓣的Redis平台Codis.类Evernote的云笔记leanote等. 1.1 为什么要学习 如果有人说X语言比Y语言好,两方的支持者经常会激烈地争吵.如果你是某种语言老手,你就是那门语言的"传道者",下意识地会保护它.无论承认与否,你都已被困在一个隧道里,你看到的完全是局限的.<肖申克的救赎>对此有很好的注脚: [Red] These walls are funny. First you hate 'em,

  • GO语言如何手动处理TCP粘包详解

    前言 一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据.TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上MTU的往往小于在应用处理的消息数据,所以就会引发一次接收的数据无法满足消息的需要,导致粘包的存在.处理粘包的唯一方法就是制定应用层的数据通讯协议,通过协议来规范现有接收的数据是否满足消息数据的需要.在应用中处理粘包的基础方法主要有两种分别是以4节字描述消息大小或以结束符,实际上也有两者相结合的如HTTP,redis的通讯协议等. 应用场景 大

  • go语言简单网络程序实例分析

    本文实例分析了go语言简单网络程序.分享给大家供大家参考.具体分析如下: 服务端代码如下: 复制代码 代码如下: package main import (     "net"     "os" ) func serve(s net.Conn) {     var buf [1024]byte     for {         n, err := s.Read(&buf)         if err != nil || n == 0 {         

  • Go语言中TCP/IP网络编程的深入讲解

    前言 大家可能乍一看,通过TCP/IP层连接两个进程会感觉可怕, 但是在Go语言中可能比你想象的要简单的多.下面话不多说了,来一起看看详细的介绍吧. TCP/IP层发送数据的应用场景 当然很多情况下,不是大多数情况下,使用更高级别的网络协议毫无疑问会更好,因为可以使用华丽的API, 它们隐藏了很多技术细节.现在根据不同的需求,有很多选择,比如消息队列协议, gRPC, protobuf, FlatBuffers, RESTful网站API, websocket等等. 然而在一些特殊的场景下,特别

  • Go语言七篇入门教程六网络编程

    目录 1. Socket 编程 1.1 Dial()函数 2. HTTP 编程 2.1 HTTP 客户端 2.2 HTTP 服务端 2.2.1 处理 HTTP 请求 3. RPC 编程 3.1 Go 语言中的 RPC 支持与处理 3.2 Gob 简介 3.3 设计优雅的 RPC 接口 1. Socket 编程 在 Go 语言中编写网络程序时,我们将看不到传统的编码形式.以前我们使用 Socket 编程时,会按照如下步骤展开. 建立 Socket:使用 socket()函数. 绑定 Socket:

  • Go语言七篇入门教程五文件及包

    目录 1. 文件处理 1.1 JSON文件 1.1.1 已知JSON结构 1.1.2 未知JSON结构 1.1.3 Encoder & Decoder 1.2 XML文件 1.3 二进制文件 1.4 zip文件 1.4.1 创建zip 1.4.2 读取zip文件 2. 包管理 2.1 包路径 2.2 包声明 如何学习Go 1. 文件处理 1.1 JSON文件 什么是json? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 也是在web开发中的前后

  • Go语言七篇入门教程四通道及Goroutine

    目录 1. 前言 2. 通道简介 2.1 声明 2.1 读写 2.3 通道详解 2.3.1 例子 2.3.2 死锁 2.3.3 关闭通道 2.3.4 缓冲区 2.3.5 通道的长度和容量 2.3.6 单向通道 2.3.7 Select 2.3.8 default case 块 2.3.9 空 select 2.3.10 Deadlock 2.3.11 nil通道 2.4 多协程协同工作 2.5 WaitGroup 2.5.1 简介 2.5.2工作池 2.5.3 Mutex 3. 结语 如何学习G

  • Go语言七篇入门教程三函数方法及接口

    目录 1. 函数 2. 方法 3. 接口 如何学习Go 参考书籍: <go语言程序设计> 1. 函数 每个函数声明都包含一个名字,一个形参列表,一个可选的返回列表以及函数体: func name(parameter-list)(result-list){ body } 形参列表:指定另一组变量的参数名和参数类型,这些局部变量都由调用者提供的提供的实参传递而来的. 返回列表:指定了函数返回值的类型.当函数返回一个未命名的返回值或者没有返回值的时候,返回列表的圆括号可以忽略. func FanOn

  • Go语言七篇入门教程一简介初识

    目录 简介 为什么是Go Go应用 Web Cloud 云 BlockChain 区块链 如何学习Go 其实我自己接触Go语言也还不到一年,20年的10月我才开始学Go的. 我自己也并不是很懂,但是我希望我能帮助到你学习Go语言,我们可以一起学习交流~ Go语言的吉祥物-金花鼠我一直以为是土拨鼠 在某搜索引擎上一搜golang一堆表情包. 简介 Go语言亦叫Golong语言,是由谷歌Goggle公司推出.Go语言的主要开发者有:肯.汤姆逊(Ken Thompson).罗布.派克(Rob Pike

  • Go语言七篇入门教程七GC垃圾回收三色标记

    目录 GC 如何判断一个对象是否可达 三色标记法 原理如下 GC GC全称Garbage Collection 目前主流的垃圾回收算法有两类,分别是追踪式垃圾回收算法(Tracing garbage collection)和引用计数法( Reference counting ). 而三色标记法是属于追踪式垃圾回收算法的一种. 追踪式算法的核心思想是判断一个对象是否可达,因为一旦这个对象不可达就可以立刻被 GC 回收了. 如何判断一个对象是否可达 分为两步: 第一步找出所有的全局变量和当前函数栈里

  • Go语言七篇入门教程二程序结构与数据类型

    目录 1. 程序结构 1.1 名称 1.2 声明 1.3 注释 1.4 单双引号 1.5 输出 2. 数据类型 2.1 整型 2.2 浮点型 2.3 复数 2.4 布尔型 2.5 字符串 2.6 常量 2.7 数组 2.8 切片 2.9 map 2.10 结构体 2.11 JSON 3. 流程控制 3.1 条件语句 3.2 选择语句 3.3 循环语句 如何学习Go 1. 程序结构 1.1 名称 如果一个实体名称在函数中声明,它只在函数局部有效.如果声明在函数外,它将对包里面的所有源文件可见. 实

  • 零基础易语言入门教程(六)之逻辑型命令

    逻辑型命令,就是非真即假的. 具体方法和步骤如下所示: 1.如果(): 属于逻辑型,不是真就是假,这种时间我们基本在编写程序时,会有两个选择方向,见下图所示: 2.如上图,如果命令属于逻辑型数据,且有两条输出方向,当我们在如果命令里填写的为真,那么我们的系统将会显示输出真的一个,反之则为假. 3.如果()命令在我们编写程序时属于常用命令,他在运行时我们需要给他一个条件,然后才能输出内容,有了条件我们在运行时给他一个输出方向即可, 以上所述是小编给大家介绍的零基础易语言入门教程(六)之逻辑型命令的

  • 零基础易语言入门教程(二)之编程思路

    易语言简介: 易语言是一门以中文作为程序代码编程语言.以"易"著称.创始人为吴涛.早期版本的名字为E语言.易语言最早的版本的发布可追溯至2000年9月11日.创造易语言的初衷是进行用中文来编写程序的实践.从2000年至今,易语言已经发展到一定的规模,功能上.用户数量上都十分可观. 上一篇跟大家讲了零基础易语言入门教程(一)编写第一个程序,然后接下来大家应该自己把支持库和易语言组件里面的控件全部认真的看一下,下面我直接跟大家分享下易语言简单编程思路. 方法和步骤如下所示: 1.易语言程序

  • Pythony运维入门之Socket网络编程详解

    Socket是什么? Socket 是电脑网络中进程间数据流的端点Socket 是操作系统的通信机制应用程序通过Socket进行网络数据的传输 首先,简单了解一下TCP通信过程: TCP三次握手(面试常考): 第一次握手:客户端 发送SYN报文,设置随机数序号X,服务器由SYN=1知道,客户端要求建立联机 第二次握手:服务器端接收到客户端的报文之后,经过处理,返回给客户端SYN+ACK报文,同时设置随机序号Y,此时返回的报文确认ACK=X+1 第三次握手:接收到报文的客户端,会在处理确认之后,再

随机推荐