一、声明接口

 type Result interface {
LastInsertId() (int64, error)
RowsAffected() (int64, error)
}

二、实现接口,这里却将接口作为成员变量,进而将接口的实现转换为接口的调用,仅仅是封装了接口,实际上并没有真的实现,而是坐等别人去实现

 //    一把锁
// 一个结果集的假接口实现,表示需要的功能,让他人来具体实现。假装实现了某个接口,其实是调用了内部接口的对应方法
type driverResult struct {
sync.Locker
resi driver.Result
}
// Result 是对已执行 SQL 命令的总结,。
// LastInsertId() 会返回一个由数据库生成的整数, 这个整数是对命令的响应。 在插入一个新的数据行时, 这个整数通常来源于数据表中的自增数据列。
// 并不是所有数据库都支持这个特性, 并且各个数据库在实现这个特性时使用的语句也会有所不同。
// RowsAffected() 返回受到更新、插入或者删除操作影响的行数量, 并不是所有数据库或者所有数据库驱动都支持这个特性。
type Result interface {
LastInsertId() (int64, error)
RowsAffected() (int64, error)
} func (dr driverResult) LastInsertId() (int64, error) {
dr.Lock()
defer dr.Unlock()
return dr.resi.LastInsertId()
} func (dr driverResult) RowsAffected() (int64, error) {
dr.Lock()
defer dr.Unlock()
return dr.resi.RowsAffected()
}

Go 中的 interface 是一种类型,更准确的说是一种抽象类型 abstract type,一个 interface 就是包含了一系列行为的 method 集合,interface 的定义很简单:

 package io

 type Writer interface {
Write(p []byte) (n int, err error)
}

如果一个 concrete type 实现了某个 interface,我们说这个 concrete type 实现了 interface 包含的所有 method,必须是所有的 method。Go 中的 interface 不同于其它语言,它是隐式的 implicitly,这意味着对于一个已有类型,你可以不用更改任何代码就可以让其满足某个 interface。

在 Go 的标准库 fmt 中有一系列的方法可以很好的诠释 interface 是如何应用到实践当中的。

 package fmt

 func Fprintf(w io.Writer, format string, args ...interface{}) (int, error)

 func Printf(format string, args ...interface{}) (int, error) {
return Fprintf(os.Stdout, format, args...)
} func Sprintf(format string, args ...interface{}) string {
var buf bytes.Buffer
Fprintf(&buf, format, args...)
return buf.String()
}

在 Printf 函数中,调用 Fprintf 时指定的输出是标准输出,这正是 Printf 的功能:Printf formats according to a format specifier and writes to standard output,根据指定的格式化要求输出到标准输出,os.Stdout 的类型是 *os.File 。Fprintf 中的前缀 F 表示 File,意思是格式化的输出被输出到函数指定的第一个 File 类型的参数中。

同样在 Sprintf 函数中,调用 Fprintf 时指定的输出是一个指向某个 memory buffer 的指针,其类似一个 *os.File

虽然 bytes.Buffer 和 os.Stdout 是不同的,但是它们都可以被用于调用同一个函数 Fprintf,就是因为 Fprintf 的第一个参数是接口类型 io.Writer ,而 bytes.Buffer 和 os.Stdout 都实现了这个 interface,即它们都实现了 Write 这个 method,这个 interface 并不是一个 File 却完成了类似 File的功能。

Fprintf 其实并不关心它的第一个参数是一个 file 还是一段 memory,它只是调用了 Write method。这正是 interface 所关注的,只在乎行为,不在乎其值,这种能力让我们可以非常自由的向 Fprintf 传递任何满足 io.Writer 的 concrete type,这是 Go interface 带来的 substitutability 可替代性,object-oriented programming 的一种重要特性。

看个例子:

 package main

 import (
"fmt"
) type ByteCounter int func (c *ByteCounter) Write(p []byte) (int, error) {
*c += ByteCounter(len(p)) // convert int to ByteCounter
return len(p), nil
} func main() { var c ByteCounter
c.Write([]byte("hello"))
fmt.Println(c) // 5 #1
fmt.Fprintf(&c, "hello") #2
fmt.Println(c) // 10 #3
}


这就是 Go 中的 interface 所具有的最基本的功能:作为一种 abstract type,实现各种 concrete type 的行为统一。ByteCounter
 实现了 Write method,它满足 io.Writer interface,Write method 计算传给它的 byte slice 的长度并且赋值给自身,所以 #1 输出到标准输出的是它的值 5,正如前文所言,调用 fmt.Fprintf 时再次调用了 c 的 Write method,所以 #3 输出是 10。

golang接口的封装的更多相关文章

  1. Golang 接口与反射知识要点

    目录 Golang 接口与反射知识要点 1. 接口类型变量 2. 类型断言 3. 鸭子类型 4. 反射机制 5. reflect 包 TypeOf().ValueOf() Type().Kind() ...

  2. Golang 接口

    1 接口是什么 Golang中没有像Python.Java拥有类和对象的概念,其封装对象或说明对象是通过接口来实现的.比如谁能够实现什么样的功能,便能够将其抽象化封装. 接口定义了一组方法(抽象方法集 ...

  3. C#开发微信门户及应用(23)-微信小店商品管理接口的封装和测试

    在上篇<C#开发微信门户及应用(22)-微信小店的开发和使用>里面介绍了一些微信小店的基础知识,以及对应的对象模型,本篇继续微信小店的主题,介绍其中API接口的封装和测试使用.微信小店的相 ...

  4. <<海闻电子发票接口 ESB 封装 代码指示 文档>>

    <<海闻电子发票接口 ESB 封装 代码指示 文档>> isValid 是否有效标志 代码 中文 说明 true 成功 false 失败   code 海闻错误说明 代码 中文 ...

  5. <<海闻电子发票接口 ESB 封装文档>>

    <<海闻电子发票接口 ESB 封装文档>> 章节目录结构: 发票验证接口 发票开具接口 ESB请求地址: 发票验证接口: http://10.15.22.120:8866/42 ...

  6. 微信公众平台消息接口开发-封装weixin.class.php

    原文:微信公众平台消息接口开发-封装weixin.class.php 一.封装weixin.class.php 由于微信公众平台的通信使用的是特定格式的XML数据,每次接受和回复都要去做一大堆的数据处 ...

  7. 【Golang 接口自动化06】微信支付md5签名计算及其优化

    前言 可能看过我博客的朋友知道我主要是做的支付这一块的测试工作.而我们都知道现在比较流行的支付方式就是微信支付和支付宝支付,当然最近在使用低手续费大力推广的京东金融(已改名为京东数科)以后也可能站到第 ...

  8. 【Golang 接口自动化00】为什么要用Golang做自动化?

    为什么使用Golang做自动化 顺应公司的趋势学习了Golang之后,因为没有开发那么多的时间和项目来实践,怕步此前学习Java缺少练习遗忘殆尽的后尘,决定利用工作之余的时间把此前用Python的写的 ...

  9. 接口API封装中常见的HTTP状态码

    在进行后端接口API封装的过程中,需要考虑各种错误信息的输出.一般情况下,根据相应问题输出适合的HTTP状态码,可以方便前端快速定位错误,减少沟通成本. HTTP状态码有很多,每个都有对应的含义,下面 ...

随机推荐

  1. linux centos&Ubuntu&RedHat更换软件源

    linux三大版本更换软件源 前排提示,有的源可能已经失效,如果发现请留言或自行寻找其他源. 1.centos mv /etc/yum.repos.d/CentOS-Base.repo [--path ...

  2. [Noip 2013 Day1-3] 货车运输 做法总结

    [Noip 2013 Day1-3] 货车运输 做法总结 Online Judge:Luogu-1967 Label:启发式合并,离线,整体二分,按秩合并,倍增,最大生成树 打模拟离线赛时做到,顺便总 ...

  3. MongDB4.0-入门学习之运算符

    MongDB 4.0 入门学习之运算符 基本语法:db.collection.find({<key>:{$symbol:<value>}}) 条件查询匹配运算符 符号 描述 范 ...

  4. 网络编程(client发信息给server)

    client发信息给server

  5. 高斯消元+期望dp——light1151

    高斯消元弄了半天没弄对.. #include<bits/stdc++.h> using namespace std; #define maxn 205 #define eps 1e-8 d ...

  6. BZOJ 3668: [Noi2014]起床困难综合症

    Time Limit: 10 Sec Memory Limit: 512 MB Submit: 2693 Solved: 1563 [Submit][Status][Discuss] Descript ...

  7. 表单单选按钮input[type="radio"]

    <!DOCTYPE html> <html lang="zh"> <head> <title></title> < ...

  8. 关于群晖的sata扩展卡选择

  9. Python学习day35-并发编程(1)

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  10. Tornado demo3 - tcpecho分析

    在这个demo中,主要是使用了Tornado中异步的TCP client和server来实现一个简单的echo效果(即客户端发送的message会从server端返回到client).代码的githu ...