【Go语言学习系列10】Go基础语法(八):接口

GoLang笔记—基础语法篇 我们从计算机系统的角度来讲,变量就是一段或者多段内存,用于存储数据 注意:变量声明以关键字var开头,变量类型后置,行尾无须分号如果你学过C语言,就会体会到这样声明的好处,比如C语言这样声明:int* a, b ,那么只有a是指针,b不是,这样会使人迷惑,如果想要两个变量都为指针,需要这样定义:。 在go语言中,我们使用这样的声明方式:,就可以轻松的将a,b都声明为指针。变量的命名规则遵循驼峰命名法,即首个单词小写,每个新单词的首字母大写,例如: startDate当一个变量被声明之后,系统自动赋予它该类型 阅读详情

📚 原创系列: “Go语言学习系列”

🔄 转载说明: 本文最初发布于"Gopher部落"微信公众号,经原作者授权转载。

🔗 关注原创: 欢迎扫描文末二维码,关注"Gopher部落"微信公众号获取第一手Go技术文章。

📑 Go语言学习系列导航

本文是【Go语言学习系列】的第10篇,当前位于第一阶段(入门篇)

🚀 第一阶段:入门篇
  1. Go语言简介与环境搭建
  2. Go开发工具链介绍
  3. Go基础语法(一):变量与数据类型
  4. Go基础语法(二):流程控制
  5. Go基础语法(三):函数
  6. Go基础语法(四):数组与切片
  7. Go基础语法(五):映射
  8. Go基础语法(六):结构体
  9. Go基础语法(七):指针
  10. Go基础语法(八):接口 👈 当前位置
  11. 错误处理与异常
  12. 第一阶段项目实战:命令行工具

📚 查看完整Go语言学习系列导航

📖 文章导读

在本文中,您将学习:

  • Go接口的设计理念与隐式实现机制
  • 接口底层结构与类型信息存储方式
  • 类型断言与类型转换的正确使用方法
  • 空接口与接口值的零值处理
  • Go 1.18+泛型与接口的关系与区别
  • 常见接口设计模式与实战应用案例

接口是Go语言中最为灵活的特性之一,掌握接口不仅能让您的代码更加模块化和可扩展,还能帮助您理解标准库的设计思想。本文将带您深入理解接口的原理和各种实战技巧。

Go接口示意图


Go基础语法(八):接口详解与最佳实践

接口是Go语言中实现多态和代码复用的核心机制,它定义了一组方法签名,允许不同类型通过实现这些方法来满足接口。与其他语言不同,Go的接口是隐式实现的,这为代码提供了极大的灵活性和简洁性。本文将详细介绍Go接口的原理、使用技巧和最佳实践。

一、接口基础

1.1 接口的定义与隐式实现

在Go中,接口是一种类型,它指定了一个方法集:

// 定义一个接口
type Reader interface {
   
   
    Read(p []byte) (n int, err error)
}

// 另一个包含多个方法的接口
type Shape interface {
   
   
    Area() float64
    Perimeter() float64
}

Go接口的特别之处在于它们是隐式实现的,即如果一个类型实现了接口中定义的所有方法,它就自动满足了该接口,无需显式声明:

// Circle类型
type Circle struct {
   
   
    Radius float64
}

// 实现Shape接口的Area方法
func (c Circle) Area() float64 {
   
   
    return math.Pi * c.Radius * c.Radius
}

// 实现Shape接口的Perimeter方法
func (c Circle) Perimeter() float64 {
   
   
    return 2 * math.Pi * c.Radius
}

// Rectangle类型
type Rectangle struct {
   
   
    Width, Height float64
}

// 实现Shape接口的方法
func (r Rectangle) Area() float64 {
   
   
    return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
   
   
    return 2 * (r.Width + r.Height)
}

// 使用接口作为参数
func PrintShapeInfo(s Shape) {
   
   
    fmt.Printf("面积: %.2f, 周长: %.2f\n", s.Area(), s.Perimeter())
}

func main() {
   
   
    c := Circle{
   
   Radius: 5}
    r := Rectangle{
   
   Width: 3, Height: 4}
    
    // 都可以作为Shape传递给函数
    PrintShapeInfo(c)
    PrintShapeInfo(r)
}

隐式实现的优势:

  • 不需要显式声明实现了哪个接口,减少代码冗余
  • 实现与接口解耦,允许对已有类型实现新接口
  • 支持将第三方库类型适配到本地接口

1.2 接口值与动态类型

接口值由两部分组成:

  • 一个具体的类型(动态类型)
  • 该类型的一个值(动态值)

接口值的内部结构

var s Shape
fmt.Printf("值: %v, 类型: %T\n", s, s)  // 值: <nil>, 类型: <nil>

s = Circle{
   
   Radius: 5}
fmt.Printf("值: %v, 类型: %T\n", s, s)  // 值: {5}, 类型: main.Circle

s = Rectangle{
   
   Width: 3, Height: 4}
fmt.Printf("值: %v, 类型: %T\n", s, s)  // 值: {3 4}, 类型: main.Rectangle

接口的零值是nil,此时动态类型和动态值都是nil。

1.3 空接口与any类型

空接口(interface{})不包含任何方法,因此所有类型都实现了它:

// 空接口可以存储任何类型的值
var anything interface{
   
   }
anything = 42
anything = "hello"
anything = struct{
   
    name string }{
   
   "John"}

// 从Go 1.18开始,any是interface{}的类型别名
var something any  // 与interface{}相同

从Go 1.18开始,any是interface{}的类型别名,推荐使用any来表示空接口,更加简洁和语义化。

空接口常用于:

  • 处理未知类型或多种类型的值
  • 实现通用容器或集合
  • 动态类型处理

二、接口的高级用法

2.1 类型断言

类型断言用于检查接口值是否是特定类型,并提取其值:

var s Shape = Circle{
   
   Radius: 5}

// 方式1:直接断言,可能引发panic
circle := s.(Circle)
fmt.Println(circle.Radius) // 5

// 方式2:安全的断言,带ok值
rectangle, ok := s.(Rectangle)
if ok {
   
   
    fmt.Println("是Rectangle类型")
} else {
   
   
    fmt.Println("不是Rectangle类型") // 这行会执行
}

2.2 类型选择(Type Switch)

类型选择是类型断言的增强形式,允许一次性判断多个类型:

func describe(i interface{
   
   }) {
   
   
    switch v := i.(type) {
   
   
    
【G4基础03】2.3 How to Specify Materials in the Detector 定义探测器材料 阅读详情

相关推荐

别再凭感觉选电容了!手把手教你计算电机控制器里的母线电容(附Excel计算工具)

本文详细解析了电机控制器中母线电容的选型方法,从理论计算到工程实践,帮助工程师避免常见误区。通过精确计算纹波电压、电容容量等关键参数,并结合薄膜电容与电解电容的性能对比,提供实用的选型建议。附带的Excel计算工具可快速完成参数计算,适用于工业伺服驱动和电动车电机控制器设计。

weixin_28720573的博客 518

第1.1节 构网型 vs. 跟网型:根本区别与技术原理

构网型与跟网型变流器的本质区别在于控制哲学与等效模型。跟网型变流器采用"电压跟随,电流注入"策略,等效为受控电流源,依赖电网电压作为参考,在弱电网下存在稳定性问题。构网型变流器采用"自主同步,电压构建"策略,等效为受控电压源,能主动构建电压和频率,具备自主运行、黑启动和电网支撑能力。两者的核心差异体现在同步机制、电网依赖性、故障行为和系统支撑等方面。构网型变流器更适合高比例新能源、弱电网和微电网场景,是未来电力系统的重要发展方向。

技术工作者 1395

避坑指南:LVGL在Arduino环境编译报错?3步搞定lv_conf.h路径问题(附ST7789屏幕调试技巧)

本文详细解析了在Arduino环境中配置LVGL图形库时,如何解决常见的“lv_conf.h file not found”编译报错问题。通过三步法:定位并复制模板文件、启用核心配置并指定路径、配置基础参数,从根本上解决路径问题。文章还结合ST7789屏幕驱动,分享了使用TFT_eSPI库进行显示适配、内存优化及背光控制等实战调试技巧,帮助开发者建立清晰、可维护的嵌入式UI工程基础。

lake5的博客 860

GD32F470 DSP库移植避坑指南:从CMSIS版本冲突到AC6工程配置

本文详细解析了在GD32F470平台上移植CMSIS-DSP库的完整流程与关键避坑点。针对CMSIS版本冲突、AC6编译器下的浮点ABI配置、DSP库源文件添加等核心难题,提供了经过验证的解决方案,帮助开发者高效完成移植,确保硬件FPU正常工作并优化性能。

data3的博客 530

AMD KFD的SDMA Packet 类型和定义解析

本文详细分析了AMD GPU架构中的SDMA(System Direct Memory Access)数据传输机制,重点介绍了其核心数据结构——SDMA Packet。SDMA通过8种主要Packet类型(包括内存拷贝、数据写入、屏障同步、中断触发等)实现高效主机-设备通信。每种Packet采用位域结构和联合体封装设计,在保证功能完整性的同时实现空间优化。这些Packet支持丰富的访问属性和扩展字段,适用于高性能数据搬运、内存初始化、任务同步、性能分析等场景,为GPU计算提供了灵活高效的数据传输解决方案。

图形/计算GPU的驱动与虚拟化技术分享园地 1248

【AUTOSAR-E2E】-2.3-配置E2E:基于E2EPW配置一个RX接收的Signal Group(使用E2E Profile 1)

《共13页精讲》:此法也适用于E2E Profile 4/5/6/7/11/22 目录 1 检查CAN Matrix Arxml/DBC是否满足E2E需求 2 在DaVinci Developer中为Port添加E2E保护 3 在DaVinci Configurator settings设置 4 如何使用应用层的E2E保护 5 结尾 <--返回「Autosar_BSW高阶配置」总目录--> <--返回「Autosar_BSW高阶配置」专栏主页--> <-.

「汽车电子助手」的博客 3951

国科大作业考试资料-人工智能原理与算法-2024新编-第十一次作业整理

1、有一位教授想知道学生是否睡眠充足。每天,教授观察学生在课堂 上是否睡觉,并观察他们是否有红眼。教授获得如下的领域知识: (1)没有观察数据时,学生睡眠充足的先验概率为0.7。 (2)给定学生前一天睡眠充足为条件,学生在晚上睡眠充足的概率是0.8;如果前一天睡眠不充足,则是0.3。 (3)如果学生睡眠充足,则红眼的概率是0.2,否则是0.7。 (4)如果学生睡眠充足,则在课堂上睡觉的概率是0.1,否则是0.3。 将这些信息形式化为一个动态贝叶斯网络,使教授可以使用这个网络从观察序列中进行滤波和预

MatsumotoChrikk 1055

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

上一篇: 【Go语言学习系列09】Go基础语法(七):指针
下一篇: 【Go语言学习系列11】错误处理与异常
Gopher部落
博客等级 码龄2年 784粉丝 92原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gopher部落

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值