Golang匿名结构体的使用

2023-11-19

一、结构体基础

结构体 (struct) 将多个不同类型的字段集中组成一种复合类型,按声明时的字段顺序初始化。

type user struct {
  name string
  age byte
}

user := user {"Tom", 2}

定义匿名结构体时没有 type 关键字,与其他定义类型的变量一样,如果在函数外部需在结构体变量前加上 var 关键字,在函数内部可省略 var 关键字。

// 在函数外部定义匿名结构体并赋值给 
var config struct {
  APIKey string
  OAuthConfig oauth.Config
}// 定义并初始化并赋值给 
datadata := struct {
  Title string
  Users []*User
}{
  title,
  users
}

二、匿名结构体使用场景

匿名结构体在四种常见情景下的用法。

1、组织全局变量

属于同一类的全局变量可通过匿名结构体组织在一起。

var config struct {
    APIKey      string
    OAuthConfig oauth.Config
}

config.APIKey = "BADC0C0A"

2、数据模版

可在后端把数据组织成前端需要的格式传给渲染模版

package mainimport (    "html/template"
    "net/http"
    "strings")type Paste struct {
    Expiration string
    Content    []byte
    UUID       string}func pasteHandler(w http.ResponseWriter, r *http.Request) {
    paste_id := strings.TrimPrefix(r.URL.Path, "/paste")
    paste := &Paste{UUID: paste_id}
    keep_alive := false
    burn_after_reading := false

    data := struct {
        Paste *Paste
        KeepAlive bool
        BurnAfterReading bool
    } {
        paste,
        keep_alive,
        burn_after_reading,
    }
    t, _ := template.ParseFiles("templates/paste.html")
    t.Execute(w, data)
}

匿名函授定义并初始化之后赋值给 data 变量,除了把 Paste 结构体对象的值传给前端之外,还额外添加了必要的字段。
写过前后端的同学应该知道,前端有时需要后端返回一个标志变量作为判断条件是否显示某一块内容。

Expiration: {{ .Paste.Expiration }}
UUID: {{ .Paste.UUID}}
{{ if .BurnAfterReading }}
BurnAfterReading: True{{ else }}
BurnAfterReading: False{{ end }}

3、测试案例数据

在写测试代码时,经常用到匿名结构体生成用例的输入输出,为了覆盖各个测试维度,通常结合切片使用,构成了测试样例尽可能地覆盖所有可能发生情况。

var indexRuneTests = []struct {
    s    string
    rune rune    out  int}{
    {"a A x", 'A', 2},
    {"some_text=some_value", '=', 9},
    {"a", 'a', 3},
    {"ab", '', 4},
}

4、嵌入式锁 (Embedded lock)

var hits struct {
    sync.Mutex
    n int}

hits.Lock()
hits.n++
hits.Unlock()

三、案例

手机拥有屏幕、电池、指纹识别等信息,将这些信息填充为 JSON 格式的数据。如果需要选择性地分离 JSON 中的数据则较为麻烦。Golang中的匿名结构体可以方便地完成这个操作。

首先给出完整的代码,然后再讲解每个部分。

package main

import (
	"encoding/json"
	"fmt"
)
//定义手机屏幕
type Screen01 struct {
	Size       float64 //屏幕尺寸
	ResX, ResY int //屏幕分辨率 水平 垂直
}
//定义电池容量
type Battery struct {
	Capacity string
}

//返回json数据
func getJsonData() []byte {
	//tempData 接收匿名结构体(匿名结构体使得数据的结构更加灵活)
	tempData := struct {
		Screen01
		Battery
		HashTouchId bool  // 是否有指纹识别
	}{
		Screen01:    Screen01{Size: 12, ResX: 36, ResY: 36},
		Battery:     Battery{"6000毫安"},
		HashTouchId: true,
	}
	jsonData, _ := json.Marshal(tempData)  //将数据转换为json
	return jsonData
}
func main() {
	jsonData := getJsonData() //获取json数据
	fmt.Println(jsonData)
	fmt.Println("=========解析(分离)出的数据是===========")
	//自定义匿名结构体,解析(分离)全部数据
	allData := struct {
		Screen01
		Battery
		HashTouchId bool
	}{}
	json.Unmarshal(jsonData, &allData)
	fmt.Println("解析(分离)全部结构为:", allData)
	//自定义匿名结构体,通过json数据,解析(分离)对应的结构(可以是部分结构)
	screenBattery := struct {
		Screen01
		Battery
	}{}
	json.Unmarshal(jsonData, &screenBattery) //注意:此处只能为结构体指针(一般参数为interface{},都采用地址引用(即地址传递))
	fmt.Println("解析(分离)部分结构:", screenBattery)
	//自定义匿名结构体,解析(分离)部分结构
	batteryTouch := struct {
		Battery
		isTouch bool
	}{}
	json.Unmarshal(jsonData, &batteryTouch)
	fmt.Println("解析(分离)部分结构:", batteryTouch)
	//自定义匿名结构体,解析(分离)部分不存在的结构
	temp1 := struct {
		Battery
		Detail struct {
			Name  string
			Price uint16
		}
	}{}
	json.Unmarshal(jsonData, &temp1)
	fmt.Println("解析(分离)部分不存在的结构", temp1)
	//自定义匿名结构体,解析(分离)完全不存在的结构
	temp2 := struct {
		User  string
		Price uint16
	}{}
	json.Unmarshal(jsonData, &temp2)
	fmt.Println("解析(分离)完全不存在的结构:", temp2)
}

注:匿名结构体可以组合不同类型的数据,使得处理数据变得更为灵活。尤其是在一些需要将多个变量、类型数据组合应用的场景,匿名结构体是一个不错的选择。

json.Unmarshal(data []byte, v interface{})

//注意:参数 v 只能为结构体指针(一般参数为interface{},都采用地址引用(即地址传递))

代码分析说明:

定义数据结构

首先,定义手机的各种数据结构体,如屏幕和电池,参考如下代码:

  1. // 定义手机屏幕
  2. type Screen struct {
  3. Size float32 // 屏幕尺寸
  4. ResX, ResY int // 屏幕水平和垂直分辨率
  5. }
  6.  
  7. // 定义电池
  8. type Battery struct {
  9. Capacity int // 容量
  10. }

上面代码定义了屏幕结构体和电池结构体,它们分别描述屏幕和电池的各种细节参数。

准备JSON数据

准备手机数据结构,填充数据,将数据序列化为 JSON 格式的字节数组,代码如下:

  1. // 生成JSON数据
  2. func genJsonData() []byte {
  3. // 完整数据结构
  4. raw := &struct {
  5. Screen
  6. Battery
  7. HasTouchID bool // 序列化时添加的字段:是否有指纹识别
  8. }{
  9. // 屏幕参数
  10. Screen: Screen{
  11. Size: 5.5,
  12. ResX: 1920,
  13. ResY: 1080,
  14. },
  15.  
  16. // 电池参数
  17. Battery: Battery{
  18. 2910,
  19. },
  20.  
  21. // 是否有指纹识别
  22. HasTouchID: true,
  23. }
  24.  
  25. // 将数据序列化为JSON
  26. jsonData, _ := json.Marshal(raw)
  27.  
  28. return jsonData
  29. }

代码说明如下:

  • 第 4 行定义了一个匿名结构体。这个结构体内嵌了 Screen 和 Battery 结构体,同时临时加入了 HasTouchID 字段。
  • 第 10 行,为刚声明的匿名结构体填充屏幕数据。
  • 第 17 行,填充电池数据。
  • 第 22 行,填充指纹识别字段。
  • 第 26 行,使用 json.Marshal 进行 JSON 序列化,将 raw 变量序列化为 []byte 格式的 JSON 数据。

分离JSON数据

调用 genJsonData 获得 JSON 数据,将需要的字段填充到匿名结构体实例中,通过 json.Unmarshal 反序列化 JSON 数据达成分离 JSON 数据效果。代码如下:

  1. func main() {
  2.  
  3. // 生成一段JSON数据
  4. jsonData := genJsonData()
  5.  
  6. fmt.Println(string(jsonData))
  7.  
  8. // 只需要屏幕和指纹识别信息的结构和实例
  9. screenAndTouch := struct {
  10. Screen
  11. HasTouchID bool
  12. }{}
  13.  
  14. // 反序列化到screenAndTouch中
  15. json.Unmarshal(jsonData, &screenAndTouch)
  16.  
  17. // 输出screenAndTouch的详细结构
  18. fmt.Printf("%+v\n", screenAndTouch)
  19.  
  20. // 只需要电池和指纹识别信息的结构和实例
  21. batteryAndTouch := struct {
  22. Battery
  23. HasTouchID bool
  24. }{}
  25.  
  26. // 反序列化到batteryAndTouch
  27. json.Unmarshal(jsonData, &batteryAndTouch)
  28.  
  29. // 输出screenAndTouch的详细结构
  30. fmt.Printf("%+v\n", batteryAndTouch)
  31. }

代码说明如下:

  • 第 4 行,调用 genJsonData() 函数,获得 []byte 类型的 JSON 数据。
  • 第 6 行,将 jsonData 的 []byte 类型的 JSON 数据转换为字符串格式并打印输出。
  • 第 9 行,构造匿名结构体,填充 Screen 结构和 HasTouchID 字段,第 12 行中的 {} 表示将结构体实例化。
  • 第 15 行,调用 json.Unmarshal,输入完整的 JSON 数据(jsonData),将数据按第 9 行定义的结构体格式序列化到 screenAndTouch 中。
  • 第 18 行,打印输出 screenAndTouch 中的详细数据信息。
  • 第 21 行,构造匿名结构体,填充 Battery 结构和 HasTouchID 字段。
  • 第 27 行,调用 json.Unmarshal,输入完整的 JSON 数据(jsonData),将数据按第 21 行定义的结构体格式序列化到 batteryAndTouch 中。
  • 第 30 行,打印输出 batteryAndTouch 的详细数据信息。
  •  

了解更多Go语言知识https://study.163.com/course/introduction/1210620804.htm

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Golang匿名结构体的使用 的相关文章

  • ADS2020.2安装

    双击安装包中的 exe文件 开始安装 安装结束后 直接点击退出 然后将crack文件夹中的两个文件夹 分别复制到刚刚的安装路径下 分别替换12个和2个同名文件 注意 这两个文件夹的名字要和刚刚安装的文件夹的名字一致 就是将Crack文件夹中

随机推荐

  • C++头文件

    作为一个二手的 net程序员 你看到了C 头文件一定就犯迷糊了 这到底是个啥玩意 再我纠结了24个小时 google20次 度娘10下 看过10来骗文章以后 我可能稍微开窍了 我对C 头文件总结 与 net比较如下 一 C 头文件究竟是什么
  • onvif协议服务器,Onvif第四课 服务器端发现实现

    场景 需要开发一个服务器发现模块 等待客户端的探测报文 在Linux服务器下组播地址imr interface可以不绑定 mcast imr multiaddr s addr inet addr 239 255 255 250 mcast
  • Python实现企业微信群告警

    Python实现企业微信告警 1 创建企业微信群机器人 1 1 什么是企业微信群机器人 企业微信群机器人是企业微信平台提供的一种功能 可以通过Webhook方式将消息发送到指定的企业微信群中 它可以用于自动化发送通知 告警等信息 实现监控和
  • 证据理论(1)—— DS证据理论基本理论

    证据理论 证据理论 Theory of Evidence 是由 Dempster 首先提出 由Shafer进一步发展起来的一种不精确推理理论 也称为 Dempster Shafer DS 证据理论 证据理论可以在没有先验概率的情况下 灵活并
  • 基于Matlab分析的电力系统可视化研究

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码及数据 1 概述 电力系统可视化研究是电力系统分析中一项具
  • IKE协议与实现

    一 IKE的作用 当应用环境的规模较小时 可以用手工配置SA 当应用环境规模较大 参与的节点位置不固定时 IKE可自动地为参与通信的实体协商SA 并对安全关联库 SAD 维护 保障通信安全 二 IKE的机制 IKE属于一种混合型协议 由In
  • php curl ajax get请求,PHP的curl的get,post请求-Fun言

    GET请求如下 param string url return mixed public function doGet url 初始化 ch curl init curl setopt ch CURLOPT URL url 执行后不直接打印
  • 面试题:从用户在浏览器输入域名,到浏览器显示出页面,这中间发生了什么(工作过程)?

    这是一道很基础的题 但是也容易被忽视 主要是要进行域名解析 1 在浏览器中输入地址 如 www baidu com 2 向DNS服务器查询网站IP地址 3 DNS服务器返回网站IP地址 如 119 75 217 56 4 浏览器得到IP地址
  • 使用pipeline加速Redis

    面试官 怎么快速删除10万个key 某厂面试题 prod环境 如何快速删除10万个key 带着思考 我们一来研究Redis pipeline why pipeline Redis客户端与server的请求 响应模型 前面的文章 Redis底
  • C#开发WinForm之DataGridView开发

    C 开发WinForm之DataGridView开发 原文 https blog csdn net achenyuan article details 84632751 文章目录 C 开发WinForm之DataGridView开发 基本的
  • 在Linux中使用selenium(环境部署)

    在Linux中使用selenium 环境部署 1 安装chrome 用下面的命令安装Google Chrome yum install https dl google com linux direct google chrome stabl
  • 【单片机笔记】K型热电偶单运放放大,单片机ADC采集电路

    以下内容来自百科 K型热电偶作为一种温度传感器 K型热电偶通常和显示仪表 记录仪表和电子调节器配套使用 K型热电偶可以直接测量各种生产中从0 到1300 范围的液体蒸汽和气体介质以及固体的表面温度 高清K型热电偶图片 K型热电偶是目前用量最
  • 【RuoYi-Vue-Plus】学习笔记 09 - 数据权限调用流程分析(参照 Mybatis Plus 数据权限插件)

    文章目录 前言 参考目录 代码分析 1 数据权限配置 MybatisPlusConfig 2 数据权限拦截器 PlusDataPermissionInterceptor 3 数据权限处理器 PlusDataPermissionHandler
  • 20-Docker-常用命令详解-docker attach

    常用命令详解 docker attach 前言 docker attach 语法格式 options 说明 使用示例 进入容器 和docker exec 的区别 前言 本篇来学习docker attach命令 docker attach 作
  • 解决 -bash: ifconfig: command not found 实测有效

    1 查看是否已经联网 输入ip addr 或 ip a 发现ens33 中不包含IP内容 2 修改配置步骤 1 输入 cd etc sysconfig network scripts 回车 找到ifcfg ens33 注意 cd后面有空格
  • 坐标系和投影 知识的内容介绍

    回想一下 接触遥感专业也有几个年头了 而现在越来越偏离遥感了 突然想着把自己脑中的遥感知识整理出来 首先想到的便是坐标系和投影 我想这个东西困扰着80 以上的测绘 遥感和GIS领域的从业人员吧 群里经常有人问 我自己曾经也很迷糊 什么大地坐
  • Java测试题_1

    单选题 1 class Base Base System out print Base public class Alpha extends Base public static void main String args new Alph
  • JavaScript 获取 input 输入框内容的方法

    在 JavaScript 中获取 input 输入框内容的方法有以下几种 使用 document getElementById 方法获取输入框元素 再通过 value 属性获取输入框内容 示例代码如下 var input document
  • 吴恩达老师深度学习视频课笔记:逻辑回归公式推导及C++实现

    逻辑回归 Logistic Regression 是一个二分分类算法 逻辑回归的目标是最小化其预测与训练数据之间的误差 为了训练逻辑回归模型中的参数w和b 需要定义一个成本函数 cost function 成本函数 cost functio
  • Golang匿名结构体的使用

    一 结构体基础 结构体 struct 将多个不同类型的字段集中组成一种复合类型 按声明时的字段顺序初始化 type user struct name string age byte user user Tom 2 定义匿名结构体时没有 ty