非零基础自学Golang 第12章 接口与类型 12.2 接口的创建与实现 12.2.1 接口创建

news2024/11/17 23:31:56

非零基础自学Golang

文章目录

      • 非零基础自学Golang
      • 第12章 接口与类型
        • 12.2 接口的创建与实现
          • 12.2.1 接口创建

第12章 接口与类型

12.2 接口的创建与实现

Go语言接口是方法的集合,使用接口是实现模块化的重要方式。

下面将重点介绍如何创建和实现一个Go语言接口。

12.2.1 接口创建

接口是用来定义行为类型的。

这些被定义的行为不由接口直接实现,而是由用户自定义的类型实现,一个实现了这些方法的具体类型就叫作这个接口类型的实例。

上一节也简单介绍了接口的定义,使用type和interface关键字即可创建一个接口。

接口内部只需要声明存在什么方法,不需要实现这些方法。

type InterfaceName interface{
 	Method()
}

比如,我们创建一个数据库操作的接口:

[ 动手写 12.2.1]

package main

type IDatabaser interface {
   Connect() error
   Disconnect() error
}

在这里插入图片描述

动手写12.2.1创建了一个叫IDatabaser的接口,这个接口声明了两个方法——Connect()和Disconnect(),只要哪个类型实现了这两个方法,就可以说该类型是IDatabaser接口的实例。

[ 动手写 12.2.2]

package main

import (
   "errors"
   "fmt"
)

// MySQL数据库
type Mysql struct {
   DBName    string
   isConnect bool
}

func (mysql *Mysql) Connect() error {

   fmt.Println("Mysql Connect DB => " + mysql.DBName)

   // do Connect
   mysql.isConnect = true

   if mysql.isConnect {
      fmt.Println("Mysql Connect Success!")
      return nil
   } else {
      return errors.New("Connect failure!")
   }
}

func (mysql *Mysql) Disconnect() error {
   
   // do Disconnect
   fmt.Println("Mysql Disconnect Success!")
   return nil
}

在这里插入图片描述

动手写12.2.2创建了一个对MySQL数据库操作的类型,这个类型实现了IDatabaser接口中的两个方法,因此Mysql类型就是IDatabaser的一个实例。

我们再来创建一个对Redis数据库操作的类型:

package main

import "fmt"

// Redis 数据库操作
type Redis struct {
   DBName string
}

func (redis *Redis) Connect() error {

   fmt.Println("Redis Connect DB => " + redis.DBName)
   // do Connect

   fmt.Println("Redis Connect Success!")
   return nil
}

func (redis *Redis) Disconnect() error {
   // do Disconnect
   fmt.Println("Redis Disconnect Success!")
   return nil
}

在这里插入图片描述

这时候,我们就可以直接使用Mysql和Redis这两个类型来完成数据库操作:

[ 动手写12.2.4]

package main

import (
	"errors"
	"fmt"
)

type IDatabaser interface {
	Connect() error
	Disconnect() error
}

// MySQL数据库
type Mysql struct {
	DBName    string
	isConnect bool
}

func (mysql *Mysql) Connect() error {

	fmt.Println("Mysql Connect DB => " + mysql.DBName)

	// do Connect
	mysql.isConnect = true

	if mysql.isConnect {
		fmt.Println("Mysql Connect Success!")
		return nil
	} else {
		return errors.New("Connect failure!")
	}
}

func (mysql *Mysql) Disconnect() error {

	// do Disconnect
	fmt.Println("Mysql Disconnect Success!")
	return nil
}

// Redis 数据库操作
type Redis struct {
	DBName string
}

func (redis *Redis) Connect() error {

	fmt.Println("Redis Connect DB => " + redis.DBName)
	// do Connect

	fmt.Println("Redis Connect Success!")
	return nil
}

func (redis *Redis) Disconnect() error {
	// do Disconnect
	fmt.Println("Redis Disconnect Success!")
	return nil
}

func main() {

	var mysql = Mysql{DBName: "student"}

	fmt.Println("开始连接")
	mysql.Connect()

	// do something
	fmt.Println("断开连接")
	mysql.Disconnect()

	var redis = Redis{DBName: "teacher"}

	fmt.Println("开始连接")
	redis.Connect()

	// do something
	fmt.Println("断开连接")
	redis.Disconnect()
}

运行结果

在这里插入图片描述

可以看到,我们虽然定义了接口,但是没有面向接口编程,所以动手写12.2.4会有很多重复的代码。

数据库类型越多,重复的代码也会越多,当我们面向接口编程时,就可以抽象出更简洁、更易于管理的代码,例如动手写12.2.5。

package main

import (
   "errors"
   "fmt"
)

type IDatabaser interface {
   Connect() error
   Disconnect() error
}

// Mysql数据库操作
type Mysql struct {
   DBName    string
   isConnect bool
}

func (mysql *Mysql) Connect() error {
   fmt.Println("Mysql Connect DB => " + mysql.DBName)

   //do Connect
   mysql.isConnect = true

   if mysql.isConnect {
      fmt.Println("Mysql Connect Success!")
      return nil
   } else {
      return errors.New("Connect failure! ")
   }
}

func (mysql *Mysql) Disconnect() error {
   //do Disconnect
   fmt.Println("Mysql Disconnect Success!")
   return nil
}

// Redis数据库操作
type Redis struct {
   DBName string
}

func (redis *Redis) Connect() error {
   fmt.Println("Redis Connect DB => " + redis.DBName)
   //do Connect
   fmt.Println("Redis Connect Success!")
   return nil
}

func (redis *Redis) Disconnect() error {
   //do Disconnect
   fmt.Println("Redis Disconnect Success!")
   return nil
}

func HandleDB(db IDatabaser) {
   fmt.Println("开始连接")
   db.Connect()
   //do something
   fmt.Println("断开连接")
   db.Disconnect()
}

func main() {
   var mysql = Mysql{DBName: "student"}
   HandleDB(&mysql)

   var redis = Redis{DBName: "teacher"}
   HandleDB(&redis)
}

运行结果

在这里插入图片描述

动手写12.2.5中,HandleDB()函数只有一个,却能实现处理多个不同类型的数据,这也称为Go的多态

【提示】

Go语言中,一个类型可以实现多个接口,反之,多个类型也可以实现同一个接口,任何一个类型都必然实现了空接口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/97775.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytest用例执行的先后顺序

[内部资源] 想拿年薪30W的软件测试人员,这份资料必须领取~ 温馨提示 「本篇约1600字,看完需3-5分钟,学习学半小时,加油!」 先看普通函数运行顺序 import pytestdef test_one():print("我是清安")def tes…

React学习27(react-redux多组件共享数据)

项目结构 准备工作 1)定义一个person组件,和count组件通过redux共享数据 2)为person组件编写:reducer ,action和contant常量 3)重点:Person的reducer和Count的reducer要用combineReducers进行…

深度学习-优化器

优化器 文章目录优化器1. 引言1. SGD1.1 vanilla SGD1.2 SGD with Momentum1.3 SGD with Nesterov Acceleration2. AdaGrad3. RMSProp4. AdaDelta5. Adam优化器选择出处1. 引言 优化算法可以分成一阶优化和二阶优化算法,其中一阶优化就是指的梯度算法及其变种&#…

Linux——vi,vim的使用

三种模式 正常模式 以vi或vim打开一个档案就直接进入一般模式了(这是默认的模式)。在这个模式中,你可以使用 【上下左右】 按键来移动光标,你可以使用 【删除字符】或 【删除整行】来处理档案内容,也可以使用 【复制,粘贴】来处…

3D激光里程计其三:点云畸变补偿

3D激光里程计其三:点云畸变补偿1. 产生原因2. 补偿方法Reference: 深蓝学院-多传感器融合 1. 产生原因 一帧点云:通常指雷达内部旋转一周扫描得到的点的集合。 优点:有足够数量的点云才能进行匹配,且一周正好是周围环境的完整采…

认识Java中的异常处理

文章目录Java异常处理异常体系的介绍常见运行时异常常见编译时异常Java异常处理 异常体系的介绍 什么事异常处理? 异常是程序在“编译”或者“执行”的过程中可能出现的问题,比如: 数组索引越界、空指针异常、 日期格式化异常,等… 注意:语…

常用损失函数

常见损失函数 文章目录常见损失函数引言回归1. 均方差2.平均绝对误差(MAE)3. 均方根误差(RMSE)4. 交叉熵分类二分类多分类引言 无论在机器学习还是深度领域中,损失函数都是一个非常重要的知识点。损失函数(Loss Function)是用来估量模型的预测值 f(x) 与…

Eslint 8.23 Flat Config 新配置迁移升级指南

前言 直入正题,eslint 目前为止的配置文件格式( 如 .eslintrc.js ) 存在很多无法避免的历史问题: 配置格式混乱,层层不明确的继承,不易理解。 插件配置时不支持实体运用(不能传 function / ob…

学完框架后的反思—为什么要使用框架?

学习前端也有一定的时间了,最近在网上看到了一个问题让我反思了很久——为什么要使用前端框架? 我发现自己当初学习框架时并没有想那么多,只是看中了其在业界企业的应用,大部分公司开发页面基本上都是使用框架进行开发的,而最为被大厂广泛接受的就是 React 框架,所以我当…

二棕榈酰磷酯酰乙醇胺-聚乙二醇-叠氮 DPPE-PEG-N3简介,可用于药物传递、基因转染和生物分子修饰。

二棕榈酰磷酯酰乙醇胺-聚乙二醇-叠氮 DPPE-PEG-N3 中文名称:二棕榈酰磷酯酰乙醇胺-聚乙二醇-叠氮基 英文名称:DPPE-PEG-N3 英文别名: 1,2-dipalmitoyl-sn-glycero-3-phosphoethanolamine-PEG-Azide 分子量(PEG)&a…

Linux——任务调度

at定时任务 基本介绍 at命令是一次性定时计划任务,at地守护线程atd会以后台模式运行,检查作业队列来运行默认情况下,atd守护进程没60秒检查作业队列,有作业时,会检查作业运行时间,如果时间于当前时间匹配…

Dubbo 1 分布式系统中的相关概念 1.2 集群和 分布式

Dubbo 【黑马程序员Dubbo快速入门,Java分布式框架dubbo教程】 1 分布式系统中的相关概念 文章目录Dubbo1 分布式系统中的相关概念1.2 集群和 分布式1.2.1 集群和分布式1.2.2 集群和分布式 【互联网 中】1.2 集群和 分布式 1.2.1 集群和分布式 集群:很…

使用synchornized和ReentrantLock来解决并发错误

文章目录什么是并发错误?并发错误是如何产生的?演示并发错误如何解决并发错误使用synchornized解决并发错误使用ReentrantLock解决并发错误什么是并发错误? 多个线程共享操作同一个对象的时候,线程体当中连续的多行操作未必能够连…

下个文档还要马内?还好我会Python,教大家来一手强制复制粘贴

前因后果 公司有人阳了,今天在家上班,突然小姨子就问我有没有baidu文库会员,想下载点东西,我心想这还要会员?用Python不是分分钟的事情! 然后我非常自信的告诉她不用会员随便下载,结果她顺势想…

10两级电力市场环境下计及风险的省间交易商最优购电模型

参考文章: 两级电力市场环境下计及风险的省间交易商最优购电模型—郭立邦(电网技术2019) 主要内容: 为进一步推动电力市场建设,促进电力资源大范围优化配置,我国正逐步建成包含省间与省内电力交易的两级…

齿轮魔方、五阶齿轮魔方

齿轮魔方 1,魔方三要素 (1)组成部件 部件和三阶魔方完全对应,但每个棱块的朝向不止2种,而是有6种。 (2)可执行操作 只有3种操作,即上下层同时旋转180度、左右180度、前后180度。…

一文助你快速理解Cookie,Session,Token的区别

目录 一、Cookie简介 1.1.cookie定义 1.2.cookie鉴权原理 1.3.cookie的分类 二、Session简介 2.1.session的定义 2.2.session会话机制 2.3.Session 的缺点 三、cookie与session区别 3.1.存储位置 3.2.安全性 3.3.占用服务器资源 3.4.存储空间 3.5.存储类型 3.6.…

编程入门宝典,刚开始学习编程新手必看的5点建议!

编程就像围城,城里的人想出去,城外的人想进来。 对于零基础的小白,要杀入代码的战场需要准备好哪些东西呢?最帅的萌宝在此给大家分享5点建议。 1、选择编程语言 编程首要还是选择好适合自己的语言。 编程语言有:C/C、java、VB、P…

零基础学Python:编程规范

1. 注释 python注释也有自己的规范,在文章中会介绍到。注释可以起到一个备注的作用,团队合作的时候,个人编写的代码经常会被多人调用,为了让别人能更容易理解代码的通途,使用注释是非常有效的。 在说规范之前我们有必…

微服务综合部署——SpringBoot项目制作Docker镜像注册在Zookeeper并利用K8S技术部署

一、如果你要从头开发一个基于微服务架构的项目,项目中的服务最终要部署在k8s管理的镜像环境中,你认为应如何创建项目?与本次实验过程相比,哪些改进可以让开发更加合理高效? 第一步:搭建项目并制作合适的j…