非零基础自学Golang 第12章 接口与类型 12.5 类型断言

news2025/1/27 13:02:17

非零基础自学Golang

文章目录

      • 非零基础自学Golang
      • 第12章 接口与类型
        • 12.5 类型断言
          • 12.5.1 ok-pattern
          • 12.5.2 switch-type

第12章 接口与类型

12.5 类型断言

类型断言是使用在接口变量上的操作。

简单来说,接口类型向普通类型的转换就是类型断言

类型断言的语法是:

t, ok := X.(T)

这里X表示一个接口变量,T表示一个类型(也可为接口类型),这句代码的含义是判断X的类型是否是T。

如果断言成功,则ok为true,t的值为接口变量X的动态值;如果断言失败,则t的值为类型T的初始值,t的类型始终为T。

举个例子:

[ 动手写12.5.1]

package main

import "fmt"

func checkType(t interface{}, ok bool) {

   if ok {
      fmt.Println("断言成功!")
   } else {
      fmt.Println("断言失败!")
   }
   fmt.Printf("变量t 的类型 = %T , 值 = %v\n", t, t)
}

func main() {

   var X interface{} = 1

   fmt.Println("第一次断言: ")
   t0, ok := X.(string)

   checkType(t0, ok)

   fmt.Println("第二次断言:")
   t1, ok := X.(float64)
   checkType(t1, ok)

   fmt.Println("第三次断言:")
   t2, ok := X.(int)
   checkType(t2, ok)
}

运行结果

在这里插入图片描述

动手写12.5.1中,我们定义了一个接口变量X,接口变量的动态类型为int,动态值为1。

第一次我们断言X的动态类型为string,断言失败,t0的类型为string,值为空字符串,所以这里没有打印出任何东西;断言类型为float64时,t1的值为0,也就是float64的初始值。

当我们断言为int时,断言成功,t2的类型变为int,值为接口变量X的动态值1。

类型断言分两种情况:

  • 第一种,如果断言的类型T是一个具体类型,类型断言X.(T)就检查X的动态类型是否和T的类型相同。

    如果这个检查成功了,类型断言的结果是一个类型为T的对象,该对象的值为接口变量X的动态值。换句话说,具体类型的类型断言从它的操作对象中获得具体的值。

    如果检查失败,接下来这个操作会抛出panic,除非用两个变量来接收检查结果,如:f, ok := w.(*os.File)。

  • 第二种,如果断言的类型T是一个接口类型,类型断言X.(T)检查X的动态类型是否满足T接口。

    如果这个检查成功,则检查结果的接口值的动态类型和动态值不变,但是该接口值的类型被转换为接口类型T。换句话说,对一个接口类型的类型断言改变了类型的表述方式,改变了可以获取的方法集合(通常更大),但是它保护了接口值内部的动态类型和值的部分。

    如果检查失败,接下来这个操作会抛出panic,除非用两个变量来接收检查结果,如:f, ok := w.(io.ReadWriter)。

我们再来看第二种情况。

[ 动手写 12.5.2]

package main

import "fmt"

type Person interface {
   Speak()
}

type Student struct {
   Name string
}

func (s Student) Speak() {
   fmt.Println("My name is ", s.Name)
}

func checkType(t interface{}, ok bool) {
   if ok {
      fmt.Println("断言成功!")
   } else {
      fmt.Println("断言失败!")
   }

   fmt.Printf("变量t 的类型 = %T , 值 = %v \n", t, t)
}

func main() {

   var student interface{} = Student{"小明"}

   fmt.Println("第一次断言: ")
   t0, ok := student.(string)

   checkType(t0, ok)

   fmt.Println("第二次断言: ")
   t1, ok := student.(Person)
   checkType(t1, ok)
}

运行结果

在这里插入图片描述

动手写12.5.2创建了一个Person接口和实现该接口的Student结构体。使用Student结构体实例化了一个student对象,第一次断言student为string类型,断言失败,第二次断言为Person接口,断言成功,并打印输出了student的值。

12.5.1 ok-pattern

接口类型断言有两种方式,一种是ok-pattern,一种是switch-type。

一般来说,当要断言的接口类型种类较少时,可以使用ok-pattern这种方式,结构如下:

if value, ok := 接口变量.(类型); ok == true {
 	//接口变量是该类型时的处理
}

举个例子:

[ 动手写 12.5.3]

package main

import "fmt"

type Person struct {
   Name string
   Age  int
}

func main() {

   s := make([]interface{}, 3)
   s[0] = 1
   s[1] = "str"
   s[2] = Person{"张三", 20}

   for index, data := range s {

      if value, ok := data.(int); ok == true {

         fmt.Printf("s[%d] Type = int, Value = %d\n", index, value)
      }
      if value, ok := data.(string); ok == true {
         fmt.Printf("s[%d] Type = string , Value = %s\n", index, value)
      }
      if value, ok := data.(Person); ok == true {
         fmt.Printf("s[%d] Type = Person , Person.Name = %v, Person.Age = %d\n", index, value.Name, value.Age)
      }
   }
}

运行结果

在这里插入图片描述

动手写12.5.3创建了一个长度为3的接口数组,分别赋值不同的变量类型,使用ok-pattern模式进行判断。【懂了!!!】

12.5.2 switch-type

当要断言的接口类型种类较多时,使用ok-pattern方式就显得很累赘,代码非常冗余,这时我们可以使用switch-type来进行批量判断,switch-type的结构如下:

switch value := 接口变量.(type) {
 	case类型1:
 	// 接口变量是类型1时的处理
 	case类型2:
 	// 接口变量是类型2时的处理
 	case类型3:
 	// 接口变量是类型3时的处理
 	...
 	default:
 	// 接口变量不是所有case中所列举的类型时的处理
}

同样拿上面的数据来举个例子:

[ 动手写 12.5.4]

package main

import "fmt"

type Person struct {
   Name string
   Age  int
}

func main() {

   s := make([]interface{}, 3)

   s[0] = 1
   s[1] = "str"
   s[2] = Person{"张三", 20}

   for index, data := range s {

      switch value := data.(type) {
      case int:
         fmt.Printf("s[%d] Type = int, Value = %d\n", index, value)
      case string:
         fmt.Printf("s[%d] Type = string , Value = %s\n", index, value)
      case Person:
         fmt.Printf("s[%d] Type = Person , Person.Name = %v, Person.Age = %d\n", index, value.Name, value.Age)
      }

   }
}

运行结果

在这里插入图片描述

动手写12.5.4使用switch-type模式进行类型断言,代码结构更加清晰,利于维护。

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

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

相关文章

【关于时间序列的ML】项目 1 :使用 Python 进行 Covid-19 病例 预测

🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃 🎁欢迎各位→点赞…

rk3568 | 瑞芯微平台GPIO引脚驱动编写

最近在玩瑞芯微平台的产品,移植了几个设备的驱动,遇到了一些问题,总结后发现大部分问题都出在了GPIO配置的问题上,写下本篇文章,用来分享一下调试的心得。 有喜欢瑞芯微的朋友,可以加我好友,拉…

JVM的作用,结构

源文件经过编译,生成字节码文件 JVM执行字节码文件(实际上就是将字节码解释成具体平台上的机器指令) jdk,jre,jvm三者的关系: jvm的组成: (1)类加载器子系统:负责将.class文件加载到JVM中 (2)…

初学编程,我们应该怎么做,十年老鸟带你入门。

问问自己学编程的真正目的,仅仅是想应付考试考证,还是真心想从事编程方面的工作。仅仅处于功利性而不是真心喜欢,人生苦短,劝不要来浪费时间,找其它真心喜欢的事情。不是社会喜欢的,不是父母喜欢的&#xf…

这6个微信隐藏功能你真的知道吗?学到就是赚到

我们常用的软件——微信,它有着许多隐藏功能,这些功能其实是很好用的,但是一直被我们忽略掉,现在我整理出来了,一起来看看吧。1.登录设备管理 我们平常在其它设备登录,第一次登录需要二次验证才能成功&…

jdk11新特性——新的Epsilon垃圾收集器

目录一、Epsilon垃圾收集器概述二、Epsilon垃圾收集器用法三、Epsilon垃圾收集器代码示例四、使用Epsilon垃圾收集器的原因五、使用Epsilon垃圾收集器的主要用途一、Epsilon垃圾收集器概述 A NoOp Garbage CollectorJDK上对这个特性的描述是: 开发一个处理内存分配但不实现任何…

【Flink】Flink GET operation failed: Server side error 从blobserver下载错误

文章目录 1.概述2.服务器端1.概述 flink 报错 Flink GET operation failed: Server side error 从blobserver下载错误 java.io.IOException: GET operation failed: Server side error: /tmp/hadoop-www/nm-lo

技术栈入门-------Redis

使用redis的准备工作 1、在虚拟机上安装redis(前提是安装了docker容器) 上面使用到的命令 docker pull redis mkdir -p /mydata/redis/confdocker run -p 6379:6379 --name redis -v /mydata/redis/data:/data \ -v /mydata/redis/conf/redis.conf:/et…

Python相关软件下载教程

前言 想要在电脑端运行python程序,需要先下载三个软件:Python解释器,编辑器(使用Visual Studio Code,简称VS Code),python软件包管理系统(简称pip)。 一、MacOS系统安装…

如何使用ArcGIS进行点抽稀(优化版)

概述 有的时候我们手上的数据很密集(比如POI数据),全部加载出来会很挤,在我们只需要部分数据的情况下就需要对其进行抽稀,这里为大家介绍一种比较简单的抽稀方法,希望能对大家有所帮助。 按百分比抽稀 在…

ICG-Hydrazide,用于光热治疗或光动力治疗

ICG能够强烈地吸收光能将其转化为热能或产生单线态氧,可用于光热治疗(PTT)或光动力治疗(PDT)。 英文名称:ICG-Hydrazide 外观:固体/粉末 质量纯度:95% 储存条件:-20℃ 结构式: 凯新生物运输说明: 极低…

Linux学习-87-LNMP一键安装过程

17.16 LNMP安装的前期准备(LNMP一键安装包下载) 手工安装 LNMP 环境,那么同样需要安装大概 10多个源码包(根据版本和功能不同而不同)。不过,现在网上非常流行的 LNMP 环境的搭建过程是采用 LNMP 一键安装包…

25岁,放弃4年所学专业,年薪20W+,我选择了转行。

25岁,没被迫转行, 是主动选择转行,放弃海外20W年薪“稳定”生活,目前已辞职,正在休整准备寻找工作中。希望我的经历可以给大家带来一点启发和借鉴。 首先自我介绍下。90后大叔,土木工程专业,2017年毕业于中南搬砖摇篮…

非零基础自学Golang 第12章 接口与类型 12.6 小结 12.7 知识拓展

非零基础自学Golang 文章目录非零基础自学Golang第12章 接口与类型12.6 小结12.7 知识拓展12.7.1 非侵入式接口第12章 接口与类型 12.6 小结 了解什么是鸭子类型。掌握接口的定义与实现。了解什么是接口嵌入。掌握空接口的常见用法,如空接口的赋值操作。掌握类型断…

C语言知识学习归纳总结(逐梦篇专栏合集)

上一专栏: 项目实战合集 逐梦编程,让中华屹立世界之巅。 简单的事情重复做,重复的事情用心做,用心的事情坚持做; 文章目录前言一、逐梦篇目录合集二、不忘初心"Hello world"总结壁纸(与你同在)前言 不知不觉中&#x…

详解事务:Mysql事务、Spring事务、分布式事务

详解事务:Mysql事务、Spring事务、分布式事务(一)Mysql事务【1】4种隔离级别【2】测试案例(二)Spring事务【1】准备测试代码(1)添加依赖(2)配置文件(3&#x…

《classnames源码》阅读笔记

源码目录总览 参考官方文档中的内容,我们可以知道classnames 有一个主要版本(index)和两个替代版本 (分别是dedupe 和 bind)。在看目录的时候也可以发现 classnames 具有多个对外暴露的入口。 index.js是classnames的主…

Spring MVC【参数的获取与数据返回】

Spring MVC【参数的获取与上传】🍎一. 获取参数🍒1.1 获取单个参数🍒1.2 获取多个参数🍒1.3 获取多个参数🍒1.4 获取URL中参数 (PathVariable)🍎二. 上传文件 (RequestPart)🍒2.1 postman模拟上…

目标检测论文解读复现【NO.23】FS-YOLOv5:轻量化红外目标检测方法

前言 此前出了目标改进算法专栏,但是对于应用于什么场景,需要什么改进方法对应与自己的应用场景有效果,并且多少改进点能发什么水平的文章,为解决大家的困惑,此系列文章旨在给大家解读最新目标检测算法论文&#xff0…

33个CadQuery程序化建模实例

本文介绍的33个建模示例可以帮助你了解如何使用 CadQuery 构建3D对象。示例是从简单到复杂组织起来的,因此按顺序学习它们是吸收它们的最佳方式。 1、简易矩形板 最简单的例子,一个矩形盒子: result cadquery.Workplane("front&qu…