当前位置: 首页 > news >正文

Go-知识struct

Go-知识struct

  • 1. struct 的定义
    • 1.1 定义字段
    • 1.2 定义方法
  • 2. struct的复用
  • 3. 方法受体
  • 4. 字段标签
    • 4.1 Tag是Struct的一部分
    • 4.2 Tag 的约定
    • 4.3 Tag 的获取

githupio地址:https://a18792721831.github.io/

1. struct 的定义

Go 语言的struct与Java中的class类似,可以定义字段和方法,但是不能继承。

1.1 定义字段

struct定义字段非常简单,只需要将字段写在struct的结构中,比如:

type tes struct {a intName string
}

需要注意的是,在Go里面,访问权限是通过name的大小写指定的,小写表示包内可见,如果是大写则表示包外可见。
所以上面的struct如果用Java翻译:

class tes {private int a;public String Name;
} 

同样的,如果创建的struct想让包外可见,那么必须是大写开头。

type Tes struct{id intName string
}

1.2 定义方法

在Go里面一般不会区分函数和方法,或者更好理解的话,可以认为方法是受限的函数,限制了函数调用者,那么就是方法。
定义方法:

func (a tes) test() {fmt.Println(a.id)
}

同样的,上述方法包内可见。

func (a tes) Test() {fmt.Println(a.Name)
}

上述方法虽然包外可见,但是没有意义,因为tes是包内可见,如果没有对外提供函数,那么是没有意义的。
如果想保证安全,可以使用包内可见的struct配合包内字段加包外方法,另外额外提供包外可见的struct获取函数,实现类似于Java的可见性控制。

package testype person struct {id   intname stringage  int
}func (this *person) GetId() int {return this.id
}func (this *person) GetName() string {return this.name
}func (this *person) GetAge() int {return this.age
}func (this *person) SetId(id int) {this.id = id
}func (this *person) SetName(name string) {this.name = name
}func (this *person) SetAge(age int) {this.age = age
}func NewPerson() *person {return &person{}
}func NewPersonWithId(id int) *person {return &person{id: id}
}func NewPersonWithName(name string) *person {return &person{name: name}
}

因为Go不支持函数重载,所以需要用不同的函数名字区分。
上述代码实际上就是一个基本的JavaBean的实现。
但是实际使用上,基本上对外可见的字段都是直接用.来访问和赋值的。
在使用上,struct是否对外可见,则和编码风格相关,业务系统一般不会考虑封闭性,基本上struct都是可见的;而第三方包等为了保证安全性,则会将部分struct设置为包内可见,在结合interface来保证扩展性。

2. struct的复用

在其他编程语言中,使用继承或组合实现代码的复用。
而Go语言中没有继承,只能使用组合实现复用。
比较特别的是,在Go语言中,组合复用的struct可以认为拷贝了被组合的struct的字段到需要的struct中。

type Man struct {personsex string
}func (this *Man) ToString() string {return fmt.Sprintf("id=%d, name=%s, age=%d, sex=%s\n", this.person.id, this.person.name, this.person.age, this.sex)
}func (this *Man) GetToString() string {return fmt.Sprintf("id=%d, name=%s, age=%d, sex=%s\n", this.id, this.name, this.age, this.sex)
}

在struct中组合其他struct,相当于是创建了一个同名的隐式字段,在使用的时候,可以指明隐式字段,也可以不指明隐式字段。
想一想,在Java中,如果当前class和父class中有同名的字段,那么在使用父类中的字段时,需要使用super指明使用的是父类中的字段。
同理的,当struct中有一个id,那么在使用的时候,可以使用隐式字段指明:

type Man struct {id intpersonsex string
}func (this *Man) GetSuperId() int {return this.person.id
}func (this *Man) GetManId() int {return this.id
}

隐式字段如果显示的定义了,那么就无法像使用自己的字段一样使用内嵌字段了:

type Woman struct {person personsex    string
}func (this *Woman) ToString() string {return fmt.Sprintf("id=%d, name=%s, age=%d, sex=%s\n", this.person.id, this.person.name, this.person.age, this.sex)
}func (this *Woman) GetString() string {return fmt.Sprintf("id=%d, name=%s, age=%d, sex=%s\n", this.id)
}

如果还像使用自己的字段一样使用内嵌字段,就会找不到
在这里插入图片描述

3. 方法受体

方法本质上还是函数,只是限制了函数的调用者。
那么你有没有好奇,为什么上面的例子中,方法的调用者都是指针类型而不是struct类型,这有什么区别?

type person struct {id   intname stringage  int
}func (this *person) SetIdPtr(id int) {this.id = id
}func (this person) SetId(id int) {this.id = id
}func (this *person) GetIdPtr() int {return this.id
}func (this person) GetId() int {return this.id
}func TestPerson(t *testing.T) {p := person{id:   1,name: "zhangsan",age:  10,}fmt.Printf("%+v\n", p)p.SetId(2)fmt.Printf("%+v\n", p)p.SetIdPtr(3)fmt.Printf("%+v\n", p)p.id = 4fmt.Printf("%+v\n", p.GetIdPtr())p.id = 5fmt.Printf("%+v\n", p.GetId())
}

在这里插入图片描述

没错,区别在于是否会影响原数据。
函数调用过程中,会将函数压入调用栈,在入栈过程中,会对函数参数进行拷贝。
在Java中,如果是基本类型参数,那么拷贝值,如果是复杂类型参数,那么拷贝指针。
在Go语言中,可以由程序员指定,如果方法调用者是指针,那么表示方法可以修改外部数据,如果方法调用者是struct,那么不会修改外部数据。
如果是数据的读取,那么不管是指针还是struct,都能读取到数据。
在换一个角度看,方法的调用者,在方法调用的时候,也进行了参数拷贝,所以可以认为方法调用者就是一个特殊的参数。

type person struct {id   intname stringage  int
}func (this person) GetNameS() string {return this.name
}func GetName(this *person) string {return this.name
}func TestPerson(t *testing.T) {p := person{id:   1,name: "zhangsan",age:  10,}fmt.Println(p.GetNameS())fmt.Println(GetName(&p))
}

运行都能获取到结果
在这里插入图片描述

只是无法使用.的方式触发了。

4. 字段标签

在Go语言的struct的字段后面,可以使用标签。

type person struct {id   int    `tagKey:"tagValue1,tageValue2"`name string `tagKey:"tagValue1,tageValue2"`age  int    `tagKey:"tagValue1,tageValue2"`
}

4.1 Tag是Struct的一部分

Tag用于标识字段的额外属性,类似注释。标准库reflect包中提供了操作Tag的方法。

// A StructField describes a single field in a struct.
type StructField struct {// Name is the field name.Name string// PkgPath is the package path that qualifies a lower case (unexported)// field name. It is empty for upper case (exported) field names.// See https://golang.org/ref/spec#Uniqueness_of_identifiersPkgPath stringType      Type      // field typeTag       StructTag // field tag stringOffset    uintptr   // offset within struct, in bytesIndex     []int     // index sequence for Type.FieldByIndexAnonymous bool      // is an embedded field
}

StructTag其实就是字符串:
在这里插入图片描述

4.2 Tag 的约定

Tag本质上是个字符串,那么任何字符串都是合法的,但是在实际使用中,有一个约定:key:"value.."格式,如果有多个,中间用空格区分。

type person struct {id   int    `tagKey:"tagValue1,tageValue2" tagKey1:"tagValue1,tageValue2"`name string `tagKey:"tagValue1,tageValue2" tagKey1:"tagValue1,tageValue2"`age  int    `tagKey:"tagValue1,tageValue2" tagKey1:"tagValue1,tageValue2"`
}

key: 必须是非空字符串,字符串不能包含控制字符、空格、引号、冒号。
value: 以双引号标记的字符串。
key和value之间使用冒号分割,冒号前后不能有空格。
多个key-value之间用空格分割。

key一般用于表示用途,value一般表示控制指令。
比如:
json:"name,omitempty"
表示json转换的时候,使用name作为名字,如果字段值为空,那么json转换该字段的时候忽略。

4.3 Tag 的获取

reflectStructField提供了GetLookup方法:
在这里插入图片描述

比如获取上面person的Tag

func TestPerson(t *testing.T) {p := person{id:   1,name: "zhangsan",age:  10,}st := reflect.TypeOf(p)stf, ok := st.FieldByName("id")if !ok {fmt.Println("not found")return}nameTag := stf.Tagfmt.Printf("tagKey=%s\n", nameTag.Get("tagKey"))tagValue, ok := nameTag.Lookup("tagKey1")if !ok {fmt.Println("not found")return}fmt.Printf("tagKey1=%s\n", tagValue)
}

在这里插入图片描述

在Java中有一个非常强大,也经常使用的插件lombok,通过在class的字段上添加注解,进而实现一些控制方法。
区别在于,lombok是在编译时,通过操作字节码,实现方法的写入,而Tag是在运行时,通过反射赋值。
所以Tag只能操作已有的字段和函数,不能动态的增加或者减少字段和函数。
除了使用第三方库,借助上述语法,自己也可以定义需要的操作比如判空。

相关文章:

Go-知识struct

Go-知识struct 1. struct 的定义1.1 定义字段1.2 定义方法 2. struct的复用3. 方法受体4. 字段标签4.1 Tag是Struct的一部分4.2 Tag 的约定4.3 Tag 的获取 githupio地址:https://a18792721831.github.io/ 1. struct 的定义 Go 语言的struct与Java中的class类似&am…...

SpringMVC 学习(十一)之数据校验

目录 1 数据校验介绍 2 普通校验 3 分组校验 4 参考文档 1 数据校验介绍 在实际的项目中,一般会有两种校验数据的方式:客户端校验和服务端校验 客户端校验:这种校验一般是在前端页面使用 JS 代码进行校验,主要是验证输入数据…...

软考55-上午题-【数据库】-数据库设计步骤1

一、数据库设计的步骤 新奥尔良法,四个主要阶段: 1、用户需求分析:手机用户需求,确定系统边界; 2、概念设计(概念结构设计):是抽象概念模型,较理想的是采用E-R方法。 …...

速盾:使用cdn后速度慢是怎么回事?

CDN(内容分发网络)是一种通过将网站的静态内容分布到全球各地的服务器,从而提供更快速度和更好用户体验的技术。然而,有时候用户会遇到使用CDN后速度变慢的问题,下面将探讨几种可能的原因。 服务器选择错误: CDN服务通…...

考研复试类比社团招新,无所谓“公平”,导师选谁都是他的权力

这篇文章是抖音和b站上上传的同名视频的原文稿件,感兴趣的csdn用户可以关注我的抖音和b站账号(GeekPower极客力量)。同时这篇文章也为视频观众提供方便,可以更加冷静地分析和思考。文章同时在知乎发表。 我考研一战的时候计算机考…...

阿里面试,有点焦虑。。

恭喜发现宝藏!搜索公众号【TechGuide】回复公司名,解锁更多新鲜好文和互联网大厂的笔经面经,目前已更新至美团、字节… 作者TechGuide【全网同名】 聊聊春招 春招来了,有些24届校招生可能还在做最后的努力,有些25届的…...

24计算机考研调剂 | 石家庄铁道大学

01石家庄铁道大学 智慧交通研究室招少量调剂学术型硕士(数一英一320分以上工科专业) 考研调剂招生信息 学校:石家庄铁道大学 专业:工学->计算机科学与技术->计算机应用技术 工学->测绘科学与技术->地图制图学与地理信息工程 工学->交…...

勇敢尝鲜之Springboot3大坑-集成Mybatisplus报错:ddlApplicationRunner

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 往期热门专栏回顾 专栏…...

linux高级编程:线程(二)、进程间的通信方式

线程: 回顾线程(一): 1.线程间通信问题 线程间共享同一个资源(临界资源) 互斥: 排他性访问 linux系统 -- 提供了Posix标准的函数库 -- 互斥量(互斥锁) 原子操作&#x…...

Unity 佳能SDK 及数据获取

1. 填写信息跟官方申请SDK,大概1-2个工作日会邮件回复你 佳能(中国)- 佳定制(佳能影像产品),SDK,EDSDK,CCAPI,软件开发包下载 2. 将SDK这两个文件放到 Unity Plugins文件夹 3. 把CameraControl 下面只要是绿色的 .cs 文件都复制到Unity 中...

Unity(第二十三部)导航

你可以使用 unity官方提供的 unity导航组件或第三方 unity导航组件,以实现游戏中角色或其他物体的导航。 unity导航组件通常具有多种导航模式,如飞行模式、步行模式、车辆模式等,可以根据不同的需求选择合适的模式。同时,unity导…...

根据建表sql语句生成go的struct代码工具

sql2struct 一个根据"CREATE TABLE"建表语句生成对应的Go语言结构体的工具,暂只支持 MySQL 表。 开发目的 在 github 中找到一些 sql2struct,但要么是 chrome 插件,要么是在线工具,要么是需要连接 MySQL,…...

Qt 自定义长条进度条(类似播放器进度条)

1.运行界面 2.步骤 其实很简单。 2.1绘制底图圆角矩形 2.2绘制播放进度圆角矩形 参考&#xff1a;painter绘图 3.源码 #pragma once#include <QWidget> #include <QLabel> #include <QHBoxLayout> #include <QMouseEvent> #include <QDebug&g…...

休息日的思考与额外题——双指针、原地哈希day28

文章目录 前言一、11. 盛最多水的容器二、41. 缺失的第一个正数三、42. 接雨水总结 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招&#xff0c;计划二刷完卡子哥的刷题计划&#xff0c;加油&#xff01; 二刷决定精刷了&#xff0c;于是参加了卡子哥的刷题班&#xff0c…...

数据修改

Oracle 目录 数据修改 将员工编号的 7369 的员工工资修改为 810&#xff0c;佣金改为 100 将工资最低的员工工资修改为公司的平均工资 将所有在 1981 年雇佣的员工的雇佣日期修改为今天&#xff0c;工资增长 20% 数据的更新操作 Oracle从入门到总裁:https://blog.csdn.n…...

Android JNI复杂用法,回调,C++中调用Java方法

Android JNI复杂用法&#xff0c;回调&#xff0c;C中调用Java方法 一、前言 Android JNI的 普通用法估计很多人都会&#xff0c;但是C中调用Java方法很多人不熟悉&#xff0c;并且网上很多介绍都是片段的。 虽然C/C调用Java不常用&#xff0c;但是掌握多一点还是有好处的。…...

C++从零开始的打怪升级之路(day41)

这是关于一个普通双非本科大一学生的C的学习记录贴 在此前&#xff0c;我学了一点点C语言还有简单的数据结构&#xff0c;如果有小伙伴想和我一起学习的&#xff0c;可以私信我交流分享学习资料 那么开启正题 今天分享的是关于继承的知识点 1.派生类的默认成员函数 首先我…...

uni-app app实现web-view H5图片长按下载

问题和使用场景描述&#xff1a; uniapp app web-view中图片无法长按保存&#xff0c;IOS下是正常的&#xff0c;但是Android下长按无反应 解决方案&#xff1a; 下载mui.min.js&#xff0c;放到项目中的static下(下载见最上面的压缩包) 在static目录下新建script.js mui.…...

全量知识系统问题及SmartChat给出的答复 之5

Q15. 支持前端&#xff08;知识表征&#xff09;的自然语言能力 需要一个 元语言注释工具 以及两个库&#xff08;叙词库和语料库&#xff09;和主题词表。请 1)设计 两个库和主题词表的结构 &#xff0c;2&#xff09;分别设计它们的接口&#xff0c;3&#xff09;通过调用它们…...

DolphinScheduler——工作流实例的生命周期

目录 一、DolphinScheduler架构原理 1.1 系统架构图 1.2 DolphinScheduler核心概念 1.2 创建工作流 1.2.1 如何触发一个工作流实例 1.2.2 任务调度链路监控 1.2.3 Workflow-DAG解析 DAG解析 Dispatch分发流程 Master和Worker的交互过程 1.3 任务运行状态 该篇文章主…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...