GOLANG接口适配,组合方式的灵活接口演化
原文:https://gocn.io/article/326 在OO(Object Oriented)原则中,有一条叫做:优先使用组合,而不是继承。虽然GOLANG并不是OO的语言(没有继承和多态),但是不妨碍GOLANG使用这条原则,而GOLANG的作者就强调过这一点,在GOLANG中是使用组合而非继承来扩展。 装逼的说来,继承是一种名词化的语言体系,先进行业务抽象然后设计类体系和继承关系。而组合,强制使用接口,因为组合中使用的总是另外一个对象的接口,通过动词的组合,实现目标,比如不管是什么只要有 比如,GOALNG1.8支持了 class Socket {
int Write(void*,int);
int Writev(const iovec*,int);
};
对的吧?一个Socket可以写数据,也可以用writev写iovec向量,就是一次性写入多个内存块。
这样有个问题,并非所有系统都支持Writev的,并非所有Socket都支持Writev的,如果是自己写个代码,当然是可以随便这么搞的,但是作为标准库,GOLANG当然是不能这么做的。GOLANG就加了一个接口(一个新动作)叫做 conn,err := net.Dial("tcp","127.0.0.1:1935")
buffers := Buffers{
[]byte("once upon a time in "),[]byte("Gopherland ... "),}
buffers.WriteTo(conn)
在Buffers的 func (v *Buffers) WriteTo(w io.Writer) (n int64,err error) {
if wv,ok := w.(buffersWriter); ok {
return wv.writeBuffers(v)
}
实际上conn是 func (c *conn) writeBuffers(v *Buffers) (int64,error) {
n,err := c.fd.writeBuffers(v)
func (fd *netFD) writeBuffers(v *Buffers) (n int64,err error) {
iovecs = append(iovecs,syscall.Iovec{Base: &chunk[0]})
wrote,_,e0 := syscall.Syscall(syscall.SYS_WRITEV,uintptr(fd.sysfd),uintptr(unsafe.Pointer(&iovecs[0])),uintptr(len(iovecs)))
对于其他没有实现这个接口的对象,就每个向量循环的写。 在看一个例子 http.Get("http://localhost:1985/api/v1/versions") // 实际上调用的是:
func (c *Client) Get(url string) // 然后调用:
(c *Client) Do(req *Request)
在GOLANG1.7中引入了context的概念,用来支持cancel,怎么用的: ctx,cancel := context.WithCancel(context.Background())
select {
case <- ctx.Done():
// Cancelled.
case <- time.After(...):
// Timeout
case <- other events:
// Other events.
}
如何支持取消的HTTP请求呢?给 ctx,cancel := context.WithCancel(context.Background())
go func(){
req,err := http.NewRequest("http://...")
res,err := http.DefaultClient.Do(req.WithContext(ctx))
defer res.Body.Close()
// 读取res响应结果。
}()
select {
case <- ctx.Done():
case <- time.After(3 * time.Second):
cancel() // Timeout to cancel all requests.
}
使用组合,通过 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |