Go语言接口和方法

紫若丹枫 · · 998 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

因为几乎任何东西都可加以方法,几乎任何东西都可满足某界面。一个展示的例子是 http 包定义的 Handler 界面。任何物件实现了Handler 都可服务 HTTP 请求。

  type Handler interface {
      ServeHTTP(*Conn, *Request)
  }

ResponseWriter 本身是个界面,它提供一些可访问的方法来返回客户的请求。这些方法包括标准的 Write 方法。因此 http.ResponseWriter 可用在 io.Writer 可以使用的地方。Request 是个结构,包含客户请求的一个解析过的表示。

为求简短,我们忽略 POST 并假定所有 HTTP 请求都是 GET;此简化不会影响经手者的设置。下面一个小而全的经手者实现了网页访问次数的计数。

// Simple counter server.
  type Counter struct {
      n int
  }

  func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
      ctr.n++
      fmt.Fprintf(c, "counter = %d\n", ctr.n)
  }

(注意 Fprintf 怎样打印到 http.ResponseWriter)。作为参考,这里是怎样把服务者加在一个 URL 树的节点上。

 import "http"
  ...
  ctr := new(Counter)
  http.Handle("/counter", ctr)

可是为何把 Counter 作为结构呢?一个整数能够了。(接受者需是指针,使增量带回调用者)。

// Simpler counter server.
  type Counter int

  func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
      *ctr++
      fmt.Fprintf(c, "counter = %d\n", *ctr)
  }

当某页被访问时怎样通知你的程序更新某些内部状态呢?给网页贴个信道。

// A channel that sends a notification on each visit.
  // (Probably want the channel to be buffered.)
  type Chan chan *http.Request

  func (ch Chan) ServeHTTP(c *http.Conn, req *http.Request) {
      ch <- req
      fmt.Fprint(c, "notification sent")
  }

最后,让我们在 /args 显示启动服务器时的参量。写个打印参量的函数很容易:

  func ArgServer() {
      for i, s := range os.Args {
          fmt.Println(s)
      }
  }

怎样把它变成 HTTP 服务器呢?我们可以把 ArgServer 作为某个类型的方法再忽略其值,也有更干净的做法。既然我们可以给任意非指针和界面的类型定义方法,我们可以给函数写个方法。http 包里有如下代码:

 // The HandlerFunc type is an adapter to allow the use of
  // ordinary functions as HTTP handlers.  If f is a function
  // with the appropriate signature, HandlerFunc(f) is a
  // Handler object that calls f.
  type HandlerFunc func(*Conn, *Request)

  // ServeHTTP calls f(c, req).
  func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) {
      f(c, req)
  }

HandlerFunc 是个带 ServeHTTP 方法的类型, 所以此类的值都可以服务 HTTP 请求。我们来看看此方法的实现:接受者是个函数,f,方法调用 f 。看起来很怪,但和,比如,接受者是信道,而方法发送到 此信道,没什么不同。

要把 ArgServer 变为 HTTP 服务器, 我们首先改成正确的签名:

 // Argument server.
  func ArgServer(c *http.Conn, req *http.Request) {
      for i, s := range os.Args {
          fmt.Fprintln(c, s)
      }
  }

ArgServer 现在和 HandlerFunc 有同样的签名,就可以转成此类使用其方法,就像我们把 Sequence 转为 IntArray 来使用 IntArray.Sort 一样。设置代码很简短:

http.Handle("/args", http.HandlerFunc(ArgServer))

当有人访问 /args 页时,此页的经手者有值 ArgServer 和类型HandlerFunc。HTTP 服务器启动此类型的 ServeHTTP 方法,用ArgServer 作为接受者,反过来调用 ArgServer (通过启动handlerFunc.ServeHTTP 的 f(w, req) 。)参量被显示出来。

此节中我们从一个结构,整数,信道和一个函数制造出一个 HTTP 服务器,全赖于界面就是一套方法,可定义在(几乎)任何类型上。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:紫若丹枫

查看原文:Go语言接口和方法

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077

998 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传