Golang 类型断言+反射+序列化

类型断言

什么是类型断言

  • 由于多态的存在,接口变量不知道其指向的具体类型,如果需要转为具体类型,则需要使用类型断言

类型断言语法

接口变量名.(具体类型) // 此处变量必须为 interface 类型

类型断言返回值

x := 变量名.(具体类型) // 如果转换成功则返回给x,转换失败则抛出 panic
x,ok := 变量名.(具体类型) // 如果转换成功则返回给x,ok为true,转换失败则 ok 为 false,x为类型默认值

类型断言例子

type Point struct {x inty int
}func main() {var a interface{}var point = Point{1,2}a = pointvar b Point// b = a //不行,虽然 a 指向的是Point类型,但是现在 a 是 Point 类型b = a.(Point) // 可以,这就是类型断言,表示判断 a 是否指向 Point 类型的变量// 如果是则转为 Point 类型并赋值给 b 变量,否则抛出 panic
}

类型断言的最佳实践

func checkType(items ...interface{}) {for index, x := range itmes {switch x.(type) { // 这里 type 是关键字,固定写法,只能用于 switch 语句case bool:fmt.Println("bool")case float64:fmt.Println("float64")case string:fmt.Println("string")case Student:fmt.Println("Student")case *Student:fmt.Println("*Student")}}
}

JSON/序列化/反序列化

JSON概念以及作用

  • JSON全程 JavaScript Object Notation,是一种轻量级的数据交换格式,易于阅读和书写,也方便机器进行生成和解析
  • 在数据传输前,传输的数据会经过处理变为 JSON 形式的字符串后再通过网络传输,接收方接收到 JSON 字符串后会进行处理,将 JSON字符串转为原始的数据
  • 序列化:原始数据 -> JSON字符串
  • 反序列化:JSON字符串 -> 原始数据

序列化所需的包以及函数

import "encoding/json"func Marshal(v interface{}) ([]byte, error)

结构体进行序列化

  • 将要进行序列化的结构体

    type Monster struct {Name stringAge intBirthDay stringSal float64Skill string
    }
    
  • 结构体实例化实例

    import "encoding/json"func main() {monster := {Name: "牛魔王",Age: 500,Birthday: "2011-11-11",Sal: 8000.0,Skill: "牛魔拳",}data,err := json.Marshal(monster)if err != nil {fmt.Println("序列化失败", err)} else {fmt.Println("序列化后:", string(data))}
    }
    
  • 结构体使用tag自定义序列化后 key 值的名称

    // `json:"xxx"`
    // 反引号是必须的
    type Monster struct {Name string `json:"name"`Age int     `json:"age"`BirthDay string `json:"birthday"`Sal float64 `json:"sal"`Skill string `json:"skill"`
    }
    

map进行序列化

  • 将要进行序列化的map

    var m map[string]interface{}
    m["name"] = "红孩儿"
    m["age"] = 30
    m["address"] = "洪崖洞"
    
  • map实例化实例

    import "encoding/json"func main() {var m map[string]interface{}m["name"] = "红孩儿"m["age"] = 30m["address"] = "洪崖洞"data,err := json.Marshal(m)if err != nil {fmt.Println("序列化失败", err)} else {fmt.Println("序列化后:", string(data))}
    }
    

切片进行序列化

  • 将要进行序列化的切片

    var slice []int = []int{1,2,3,4,5}
    
  • 切片实例化实例

    import "encoding/json"func main() {var slice []int = []int{1,2,3,4,5}data,err := json.Marshal(slice)if err != nil {fmt.Println("序列化失败", err)} else {fmt.Println("序列化后:", string(data))}
    }
    

序列化所需的包以及函数

import "encoding/json"func Unmarshal(s []byte, v interface{}) (err error) 

反序列化为结构体

package mainimport "encoding/json"
import "fmt"func main() {str := `{"address":"洪崖洞","age":30,"name":"红孩儿"}`var monster Monstererr := json.Unmarshal([]byte(str), &m)if err != nil {fmt.Println("序列化失败", err)} else {fmt.Println("序列化后:", m)}
}

反序列化为map

package mainimport "encoding/json"
import "fmt"func main() {str := `{"address":"洪崖洞","age":30,"name":"红孩儿"}`var m map[string]interface{}m = make(map[string]interface{})m["one"] = 1err := json.Unmarshal([]byte(str), &m)if err != nil {fmt.Println("序列化失败", err)} else {fmt.Println("序列化后:", m)}
}

反序列化为切片

package mainimport "encoding/json"
import "fmt"func main() {str := `{"address":"洪崖洞","age":30,"name":"红孩儿"}`var m map[string]interface{}err := json.Unmarshal([]byte(str), &m)if err != nil {fmt.Println("序列化失败", err)} else {fmt.Println("序列化后:", m)}
}

注意事项

  • 结构体在序列化时,非导出变量(小写字母开头)不会被 encode,因此在 decode 的时候这些非导出变量的值为其类型的零值

反射

反射的概念与作用

  • 反射可以在运行时动态获取变量的各种信息,比如变量的类型
  • 如果变量是结构体,还可以获取结构体本身的信息,比如结构体的字段,方法
  • 通过反射,可以修改变量的值,可以调用变量关联的方法

反射的使用

  • 反射包

    import "reflect"
    

reflect.Value

  • 由 reflect.ValueOf(v interface{}) (t reflect.Value) 获取某个变量的 Value

  • reflect.Value.Kind:获取变量的类别,返回的是一个常量

  • 变量,interface{},reflect.Value 之间可以任意转换

    // interface{} --> reflect.Value
    rVal := reflect.ValueOf(v)// reflect.Value --> interface{}
    iVal := rVal.Interface()// interface{} --> 变量 
    variable := iVal.(int64)// 变量 --> interface{}
    iVal = variable
    

reflect.Type

  • 由 reflect.TypeOf(v interface{}) (t reflect.Type) 获取某个变量的 Type
  • reflect.Type.Kind:获取变量的类别,返回的是一个常量,与 reflect.Value.Kind 相同
  • Type是类型,Kind是类别,它们可能相同,可能不同
    • var num int = 10 Type:int Kind:int
    • var stu Student Type:包名.Student Kind:struct

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

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

相关文章

【第三版 系统集成项目管理工程师】第4章 信息系统架构

持续更新。。。。。。。。。。。。。。。 【第三版】系统集成项目管理工程师 考情分析4.1架构基础4.1.1指导思想(非重点) P1364.1.2设计原则(非重点) P1364.1.3建设目标(非重点) P1374.1.4总体框架 P138练习…

常见的Java运行时异常

常见的Java运行时异常 1、ArithmeticException(算术异常)2、ClassCastException (类转换异常)3、IllegalArgumentException (非法参数异常)4、IndexOutOfBoundsException (下标越界异常&#xf…

Vue3 监听属性

Vue3 监听属性 Vue.js 是一个流行的前端框架,以其响应式系统和组件化开发而闻名。在 Vue3 中,监听属性(Watchers)是一个核心功能,允许开发者监控和响应数据的变化。本文将详细介绍 Vue3 中监听属性的使用方法、场景和最佳实践。 监听属性的基本概念 在 Vue3 中,监听属…

windows无法访问github

##一、如果发现windows无法访问github时 一般就是我们的dns出现了问题,此时我们需要更换一个dns访问 ##二、解决方法 首先我们访问ip查询地址, https://ipchaxun.com/github.com/ 可更换下面历史ip进行测试,在windows的cmd里面输入ping git…

VirtualBox虚拟机网络设置(四种方式)

在使用VirtualBox进行虚拟化操作时,网络配置是一个重要的环节。VirtualBox提供了四种主要的网络连接方式,每种方式都有其特定的应用场景和特点。以下是详细的介绍: 1. NAT (Network Address Translation) 特点: - 工作原理&#…

Python学习笔记31:进阶篇(二十)pygame的使用之图形绘制

前言 基础模块的知识通过这么长时间的学习已经有所了解,更加深入的话需要通过完成各种项目,在这个过程中逐渐学习,成长。 我们的下一步目标是完成python crash course中的外星人入侵项目,这是一个2D游戏项目。在这之前&#xff…

Day2用 rustlings 练习 Rust 语言-Move Semantics

大家好 今天 完成 2024年自动驾驶OS开发训练营-初阶营第四期-导学 Day2用 rustlings 练习 Rust 语言 -Move Semantics https://doc.rust-lang.org/stable/book/ch04-00-understanding-ownership.html 提交代码时候 提示 没有权限怎么出来 aciton 参考开发环境配置 https://rcor…

图片管理新纪元:高效批量横向拼接图片,一键生成灰色艺术效果,打造专业视觉体验!

在数字时代,图片已成为我们生活和工作中不可或缺的一部分。但面对海量的图片,如何高效地进行批量管理、拼接和调色,成为许多人面临的难题。今天,我们为您带来了一款颠覆性的图片管理工具,让您轻松实现图片批量横向拼接…

智慧生活新篇章,Vatee万腾平台领航前行

在21世纪的科技浪潮中,智慧生活已不再是一个遥远的梦想,而是正逐步成为我们日常生活的现实。从智能家居的温馨便捷,到智慧城市的高效运转,科技的每一次进步都在为我们的生活增添新的色彩。而在这场智慧生活的变革中,Va…

论文翻译 | (TAKE A STEP BACK) 后退一步:在大型语言模型中通过抽象来调用推理

摘要 我们介绍了STEP-BACK提示,这是一种简单的提示技术,使LLM能够进行抽象,从而从包含特定细节的实例中派生高级概念和第一原则。使用概念和原则来指导推理,LLM显着提高了他们遵循正确推理路径的能力。我们使用PaLM-2L、GPT-4和Ll…

Redis数据结构解析-RedisObject

文章目录 ☃️概述☃️源码 ☃️概述 RedisObject 是 Redis 中表示数据对象的结构体,它是 Redis 数据库中的基本数据类型的抽象。在 Redis 中,所有的数据都被存储为 RedisObject 类型的对象。 RedisObject 结构体定义如下(简化版本&#xf…

python 66 个冷知识 0706

66个有趣的Python冷知识 Python的名字来源 Python的名字不是来自蛇&#xff0c;而是来自英国的喜剧团体“蒙提派森”。 多行字符串 Python支持使用三重引号 或 """ 来创建多行字符串。 链式比较 Python允许你进行链式比较&#xff0c;例如 1 < a < 3。…

kafka中

Kafka RocketMQ概述 RabbitMQ概述 ActiveMQ概述 ZeroMQ概述 MQ对比选型 适用场景-从公司基础建设力量角度出发 适用场景-从业务场景出发 Kafka配置介绍 运行Kafka 安装ELAK 配置EFAK EFAK界面 KAFKA常用术语 Kafka常用指令 Kafka中消息读取 单播消息 group.id 相同 多播消息 g…

MyBatis-Plus-实用的功能自动填充字段

前言: java项目用到了mybatis-plus&#xff0c;在一些类里面需要在更新时候&#xff0c;统一设置&#xff0c;修改人&#xff0c;修改ID&#xff0c;修改时间。新增时候设置 创建人&#xff0c;创建时间等 基础类&#xff1a; Data public abstract class BaseModel implements…

java 公共字段填充

公共字段填充 1、mybatis-plus2、mybatis 使用注解加aop2.1 自定义注解2.2 自定义切面类2.3 在mapper上添加上自定义的注解 1、mybatis-plus 通过在类上使用如下的注解 TableField(fill FieldFill.INSERT) 是 MyBatis-Plus 中的注解&#xff0c;用于自动填充字段的值。MyBat…

简单且循序渐进地查找软件中Bug的实用方法

“Bug”这个词常常让许多开发者感到头疼。即使是经验丰富、技术娴熟的开发人员在开发过程中也难以避免遭遇到 Bug。 软件中的故障会让程序员感到挫败。我相信在你的软件开发生涯中&#xff0c;也曾遇到过一些难以排查的问题。软件中的错误可能会导致项目无法按时交付。因此&…

解决 Docker 安装时“无法获取 dpkg 前端锁”错误的有效方法

在安装 Docker 的过程中&#xff0c;不少用户可能会遇到“无法获取 dpkg 前端锁”的错误提示。这是一个较为常见但也令人困扰的问题。下面为您详细介绍几种可能的解决方法&#xff1a; 方法一&#xff1a;检查并终止相关进程 首先&#xff0c;您可以通过以下命令检查是否有正…

Linux进程、线程——保姆级助理解

目录 1、进程&#xff08;Process&#xff09; 1.1 进程基本概念&#xff1a; 1.2 进程分类 1.3 进程的特征 1.4 进程和程序的区别 1.5 进程的状态 1.6 进程的创建——Fork()函数 1.6.1 简介 1.6.2 使用 1.7 进程终止 2、线程&#xff08;Thread&#xff09; 1.1 线…

Git管理源代码、git简介,工作区、暂存区和仓库区,git远程仓库github,创建远程仓库、配置SSH,克隆项目

学习目标 能够说出git的作用和管理源代码的特点能够如何创建git仓库并添加忽略文件能够使用add、commit、push、pull等命令实现源代码管理能够使用github远程仓库托管源代码能够说出代码冲突原因和解决办法能够说出 git 标签的作用能够使用使用git实现分支创建&#xff0c;合并…

排序 -- 冒泡排序和快速排序

一、 交换排序 1、基本思想 所谓交换&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置&#xff0c;交换排序的特点是&#xff1a;将键值较大的记录向序列的尾部移动&#xff0c;键值较小的记录向序列的前部移动。 2、常见的交换排序 1、冒泡…