一、声明接口

 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. springcloud Finchley 版本hystrix 和 hystrix Dashboard

    hystrix的断路功能 引用上个项目,创建新的model ,cloud-hystrix pom.xml <?xml version="1.0" encoding=" ...

  2. umount:将文件设备卸载

    [root@centos57 ~]# umount /dev/hda1 用设备文件名来卸载 [root@centos57 ~]# umount /aixi                     用挂 ...

  3. OpenGL 鼠标交互响应事件

    OpenGL 鼠标.键盘交互响应事件 先来一个样例: uses gl,glu,glut; procedure InitEnvironment;cdecl; begin glClearColor();/ ...

  4. 【daydayup】ceshuChat

    时时当勉励,岁月不待人.珍惜时间伐~ 先看看项目运行的效果 这个是在本地环境打开了两个8080端口进行模拟运行的. 先放下作者的开源地址:https://github.com/ceshu/ceshuC ...

  5. 2017.1.16【初中部 】普及组模拟赛C组总结

    2017.1.16[初中部 ]普及组模拟赛C组 这次总结我赶时间,不写这么详细了. 话说这次比赛,我虽然翻了个大车,但一天之内AK,我感到很高兴 比赛 0+15+0+100=115 改题 AK 一.c ...

  6. 在vc2008 mfcC++中使用sqlite的示例

    http://owlman.org/?p=890 在C++中使用sqlite的示例 2011年8月5日admin发表评论阅读评论 最近因为工作原因,终于使我有机会腾出时间来接触了一下SQLite数据库 ...

  7. centos 7 安装dotnet core

    dotnetcore 支持的Linux 版本请看官网:https://docs.microsoft.com/zh-cn/dotnet/core/linux-prerequisites?tabs=net ...

  8. c语言学习笔记 - 结构体位域

    在学习结构体的时候遇到了位域这个概念,位域主要是为了节省内存空间,比如用一个32位,4个字节的int存储一个开关变量时,会造成空间浪费,于是干脆就考虑在这个32划分不同的区域来存储数据,例如划出1位存 ...

  9. LeeCode-Single Number III

    Given an array of numbers nums, in which exactly two elements appear only once and all the other ele ...

  10. Ajax4Jsf 简单介绍

    Ajax4jsf 允许开发人员将 Ajax 功能添加到 JSF 应用程序中,而不需要 JavaScript 或用 Ajax 图形部件替换现有的组件.这个包还允许在使用 Java 2D 库时动态地生成图 ...