Go——结构体

        Go语言中没有类的概念,也不支持类的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。

一. 类型别名和自定义类型

        1.1 自定义类型

       在Go语言中有一些基本的数据类型,如string,整型,浮点型,布尔型等数据结构,Go中可以使用type关键字来自定义类型。

        自定义类型是定义了一个全新的类型。我们可以基于内置的基本类型来定义,也可以通过struct来定义。

        例如:

        通过type关键字定义,MyInt就是一种新的类型,它具有int的特性。

type MyInt int

        1.2 类型别名

        类型别名是Go1.9版本新加的新功能。

        类型别名规定:TypeAlias只是Type的别名,本质TypeAlias和Type是同一个类型。

type TypeAlias = Type

        内置类型rune和byte就是类型的别名:

type byte = uint8
type rune = int32

        1.3 自定义类型和类型别名的区别

        自定义类和类型别名表面上看只有一个等号的差异,实际上自定义类型是新增了一个类型,而类型别名并没有新增类型。

        下面的例子表明:a的类型为main.NewInt,表示在main包下定义的NewInt类型。b的类型为int,MyInt类型只会在代码中存在,编译完成时并不会有MyInt类型。

二.结构体

        Go语言中的基础类型可以表示一些事物的基本属性,但是我们想表达一个事物的全部或者部分属性时,这时单一的基本数据类型已经无法满足需求了,Go语言提供了一种自定义数据类型,可以封装多个基本数据类型,这种数据类型叫结构体,英文名字为struct。

        Go语言通过struct来实现面对对象。

        2.1 结构体的定义

        使用type和struct关键字来定义结构体,具体代码风格为:

type 类型名 struct{
    字段名 字段类型
    字段名 字段类型
    ...
}

其中:

  • 类型名:标识自定义结构体名称,在同一个包内不能重复。
  • 字段名:表示结构体的字段名。结构体中的字段名必须唯一。
  • 字段类型:表示结构体字段的具体类型。

        下面定义了Person和Person1自定义类型,它们拥有name,city和age三个字段,分别表示姓名,城市和年龄。这样我们使用这个Person和Person1结构体就能够很方便的在程序中存储人的信息了。 

package main

type Person struct {
	name string
	city string
	age  uint8
}

// 同样类型的可以写在一行
type Person1 struct {
	name, city string
	age        uint8
}

        2.2 结构体的实例化

        只有当结构体实例化时,才会正真的分配内存。也就是必须实例化后才能使用结构体字段。

        结构体本身也是一种类型,我们可以像声明内置类型一样使用var关键字声明结构体类型。

var 结构体实例 结构体类型
  • 基本实例化

        我们可以通过'.'来访问结构体字段(成员变量),例如user1.name和user1.age

package main

import "fmt"

type Person struct {
	name string
	city string
	age  uint8
}

func main() {
	var user1 Person

	user1.name = "张三"
	user1.city = "上海"
	user1.age = 26

	fmt.Printf("user1 : %v\n", user1)
	fmt.Printf("user1 : %#v\n", user1)
}

  • 匿名结构体

        在定义一些临时数据结构等场景下还可以使用匿名结构体。

package main

import "fmt"

func main() {
	var user struct {
		name string
		age  uint8
	}

	user.name = "张三"
	user.age = 26
	fmt.Printf("user : %#v\n", user)
}

        2.3 结构体指针

  • 使用new关键字

        我们可以通过new关键字对结构体进行实例化,得到的是结构体地址。

        需要注意的是在Go语言中支持对结构体指针直接使用"."来访问结构体成员这是Go语言的语法糖,实际底层是(*user).name = "开发"。不像C/C++需要使用"->"。

package main

import "fmt"

type Person struct {
	name string
	city string
	age  uint8
}

func main() {
	var user = new(Person)

	fmt.Printf("%T\n", user)
	fmt.Printf("user : %#v\n", user)

	//可以使用符号.来访问
	user.name = "开发"
	user.city = "上海"
	user.age = 20
	fmt.Printf("user : %#v\n", user)
}

  • 取结构体地址实例化

        使用&对结构体进行取地址操作相当于对结构体类型进行一次new实例化操作。

package main

import "fmt"

type Person struct {
	name string
	city string
	age  uint8
}

func main() {
	user := &Person{} //相当于new(Person)
	fmt.Printf("%T\n", user)
	fmt.Printf("user : %#v\n", user)

	user.name = "张三"
	user.city = "上海"
	user.age = 20
	fmt.Printf("user:%#v\n", user)
}

        2.4 结构体初始化

  • 不进行初始化,属性为默认值

  • 使用键值对进行初始化

变量:

 也可以对指针进行初始化:

  • 使用值的列表初始化

        初始化结构体时可以简写,也就是初始化的时候不写键,直接写值,但是需要注意:

  • 必须初始化结构体的所有字段
  • 初始值的填充顺序必须与字段结构体中的声明顺序一样
  • 该方式不能和键值初始化方式混用

         2.5 结构体内存布局

        结构体变量里的变量在内存中也是连续保存的。

         但是也存在内存对齐,对齐规则和C语言一样:结构体在内存中的存储(内存对齐)_结构体在内存中的存放-CSDN博客

         2.6 构造函数

        Go语言的结构体没有构造函数,但是可以自己实现。例如:下方代码就实现了Person的构造函数。因为struct是值类型,如果结构体比较复杂,值拷贝性能开销会比较大,所以构造函数返回的是结构体指针类型。

package main

import "fmt"

type Person struct {
	name string
	city string
	age  uint8
}

func newPerson(name, city string, age uint8) *Person {
	return &Person{
		name: name,
		city: city,
		age:  age,
	} //&底层也是使用的new,然后再赋值
}

func main() {
	user := newPerson("张三", "上海", 20)
	fmt.Printf("user:%#v\n", user)
}

        2.7 方法和接收者

        Go语言的方法(Method)是一种作用于特定类型变量的函数。这种特定类型变量叫做接收者(Receiver)。接收者的概念类似于其他语言中的this或者self。

        格式:

func (接收者变量 接收者类型) 方法名 (参数列表) 返回参数{
    函数体
}
  • 接收者变量:接收者的参数变量名在命名时,官方建议使用接收者类型名的第一个小写字母,而不是self,this之类的命名。例如Person类型的接收者变量应该命名为p,Connector类型的接收者变量应该命名为c等。
  • 接收者类型:接收者类型和参数类似,可以是指针类型或非指针类型
  • 方法名,参数列表,返回参数:具体格式与函数定义相同。

举个例子:

        Dream是结构体Person中的方法,可以通过接收者变量访问结构中中的变量。

方法和函数的区别:函数不属于任何类型,方法属于特定类型。 

  •  指针类型的接收者

        指针类型的接收者由一个结构体的指针组成,由于指针的特性,调用方法时修改接收者指针的任意成员变量,在方法结束后,修改是有效的。这种方式就十分接近其他语言中面向对象的this或者self。

        例如:我们为Person添加一个SetAge方法,来修改实际变量年龄。

  • 值类型接收者

        当方法作用于值类型接收者时,Go语言会在代码运行时将接收者的值复制一份。在值类型接收者的方法中可以获取接收者的成员值,但是修改只是针对副本,无法修改接收者变量本身。

 什么时候使用指针类型接收者?

  • 需要修改接收者中的值
  • 接收者的拷贝代价比较大的大对象
  • 保证一致性,如果有某个方法使用指针接收者,那么其他方法也应该使用指针接收者。
  • 任意类型添加方法

        在Go语言中,接收者类型可以是任何类型,不仅仅是结构体,任何类型都可以拥有方法。

        举个例子:我们基于内置的int类型使用type关键字可以定义新的自定义类型,然后我们为自定义类型添加方法。

注意事项:非本地类型不能定义方法,也就是说我们不能给别的包的类型定义方法。

所以上面的int我们需要自定义类型为MyInt到当前包。 

         2.8 结构体的匿名字段

        结构体允许其成员字段在声明时没有字段名,而只有类型,这种没有名字的字段就称为匿名字段。

        匿名字段默认使用类型名作为字段名,结构体要求字段名称必须唯一,因此一个结构体中同类型的匿名字段只能有一个。

        2.9 嵌套结构体

        一个结构体中可以嵌套包含另一个结构体或结构体指针:

  • 嵌套匿名结构体 

        当访问结构体成员时会先在结构体中查找该字段,找不到再去匿名结构体中查找。

  •  嵌套结构体内部可能存在相同的字段名

        这个时候为了避免歧义需要指定具体的内嵌结构体的字段。

        2.10 结构体中的继承

        Go语言中使用结构体也可以实现其他编程语言中的面向对象的继承。

        实际是通过嵌套实现的。

        2.11 结构体字段的可见性

        结构体中字段大写开头表示可以公开访问,小写表示私有(仅在定义当前结构体的包中可以访问)。

        2.12 结构体于JSON序列化

        JSON是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON键值对是用来保存JS对象的一种方式,键/值对组合中的键名写在前面并用双引号""包裹,使用冒号:分隔,然后紧接着值; 多个键值之间使用英文,分隔。

        注意结构体的变量名需要首字母大写才能被序列化和反序列化。

package main

import (
	"encoding/json"
	"fmt"
)

type Student struct {
	ID     int    `json:"ID"`
	Gender string `json:"Gender"`
	Name   string `json:"Name"`
}

type Class struct {
	//变量首字母大写才能被解析
	Title string     //不填json键默认变量名
	Stu   []*Student `json:"stu"` //序列化后的数据字段是返回指定格式的,可以小写,或随意命名
}

func main() {
	c := Class{
		Title: "101",
		Stu:   make([]*Student, 0, 200),
	}

	for i := 0; i < 10; i++ {
		stu := &Student{
			ID:     i,
			Gender: "男",
			Name:   fmt.Sprintf("stu%02d", i),
		}

		c.Stu = append(c.Stu, stu)
	}

	// for i := 0; i < len(c.Stu); i++ {
	// 	fmt.Println(c.Stu[i])
	// }
	//json序列化:结构体——>JSON格式字符串
	data, err := json.Marshal(c)
	if err != nil {
		fmt.Println("json marshal fail", err)
		return
	}

	fmt.Printf("json %s\n", data)

	//json反序列化 键需要和结构体的键对应
	str := `{"title":"101","stu":[{"ID":0,"Gender":"男","Name":"stu00"},
	{"ID":1,"Gender":"男","Name":"stu01"},{"ID":2,"Gender":"男","Name":"stu02"},
	{"ID":3,"Gender":"男","Name":"stu03"},{"ID":4,"Gender":"男","Name":"stu04"},
	{"ID":5,"Gender":"男","Name":"stu05"},{"ID":6,"Gender":"男","Name":"stu06"},
	{"ID":7,"Gender":"男","Name":"stu07"},{"ID":8,"Gender":"男","Name":"stu08"},
	{"ID":9,"Gender":"男","Name":"stu09"}]}`

	c1 := &Class{}
	err = json.Unmarshal([]byte(str), c1)
	if err != nil {
		fmt.Println("json Unmarshal fail", err)
		return
	}
	fmt.Printf("%#v\n", c1)
}

         2.13 结构体标签

        Tag是结构体的元信息,可以在运行的时候通过反射的机制读取出来。

        Tag在结构体字段的后方定义,由一对反引号包裹起来,具体格式如下:

`key1:"value1" key2:"value2"`

        结构体标签由一个或者多个键值对组成。键与值使用冒号分隔,值用双引号括起来。键值对之间使用一个空格分隔。

        注意事项:为结构体编写Tag时,必须严格遵守键值对的规则。结构体标签的解析代码的容错能力很差,一旦格式写错,编译和运行都不会有任何提示,通过反射也不会取到正确的值。例如:不要在key和value之间添加空格。

        例如:我们为Student结构体的每个字段定义json序列化时使用的Tag:

         2.14 删除map类型的结构体

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

php反序列化——pop链构造[SWPUCTF 2021 新生赛]pop [NISACTF 2022]babyserialize

构造pop链 [SWPUCTF 2021 新生赛]pop 用反推法 从后往前推 这题的最后一步很明显 只要给$admin和$passwd赋值 就会echo flag 所以反推法第一步就是要调用Getflag()函数 找到$this->w00m->{$this->w22m}(); $this->mw00->{$this->w22m}();的意思是调用当…

中科数安|企业内部核心数据、技术资料透明加密系统,防止外泄

#文件防泄密软件# 中科数安公司专为企业内部核心数据和技术资料的安全保驾护航&#xff0c;其提供的透明加密系统是一款强有力的信息安全保障工具。 中科数安 | 信息安全防泄密系统 PC地址&#xff1a;www.weaem.com 这套系统主要特点和功能包括&#xff1a; 1. **透明加密**…

你的 Python 代码需要解释一下了!

Python 是一种相对简单的编程语言。它主要以解释型语言著称&#xff0c;这意味着每行代码都要通过解释器逐行执行。不过在某些时候&#xff0c;将 Python 代码翻译成计算机可以理解的内容&#xff0c;然后再逐行执行&#xff0c;可以减少繁琐。 在这种情况下&#xff0c;编译器…

PyTorch 教程-快速上手指南

文章目录 PyTorch Quickstart1.处理数据2.创建模型3.优化模型参数4.保存模型5.加载模型 PyTorch 基础入门1.Tensors1.1初始化张量1.2张量的属性1.3张量运算1.3.1张量的索引和切片1.3.2张量的连接1.3.3算术运算1.3.4单元素张量转变为Python数值 1.4Tensor与NumPy的桥接1.4.1Tens…

langchin-chatchat部分开发笔记(持续更新)

大模型相关目录 大模型&#xff0c;包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步&#xff0c;扬帆起航。 大模型应用向开发路径及一点个人思考大模型应用开发实用开源项目汇总大模型问答项目…

uniapp 苹果支付内购示例代码

// #ifdef APPasync init() {uni.showLoading({title: 检测支付环境...});try {// 初始化&#xff0c;获取iap支付通道await this._iap.init();// 从苹果服务器获取产品列表this.productList await this._iap.getProduct();this.productList[0].checked true;this.productId …

阿里云部署宝塔,设置了安全组还是打不开。

1.在安全组是开放正确的端口好。8888要开&#xff0c;但是不只是开放8888&#xff0c;举个例子&#xff0c;https://47.99.53.222:17677/49706cf7这个&#xff0c;要开放17677这个端口号。 2.安全组要挂载到实例上&#xff0c;从三个点的进入点击管理实例&#xff0c;加到对应的…

独立站推广新策略:从精准定位到网红合作,开启品牌“长红”之路

随着互联网技术的飞速发展和消费者购物习惯的不断变化&#xff0c;独立站作为一种新型的电商模式&#xff0c;正逐渐成为品牌商家们拓展市场、提升品牌影响力的重要途径。然而&#xff0c;如何在竞争激烈的市场中脱颖而出&#xff0c;实现从短期流量吸引向长期品牌建设的转变&a…

为响应国家号召,搜维尔科技开启虚拟仿真实验室设备升级改造服务

近日&#xff0c;国务院发布了关于《推动大规模设备更新和消费品以旧换新行动方案》&#xff0c;该通知的发布表现出国家对于科技创新事业的高度重视。各行各业都在积极响应国家号召&#xff0c;加快数字化转型和设备升级与更新步伐。搜维尔科技为响应国家号召&#xff0c;将开…

如何使用CHAT-AI?

伴随着CHAT-GPT的出现&#xff0c;人们都喜欢上了CHAT-AI。嗯&#xff1f;你还不会用&#xff1f;&#xff01; 教程来喽&#xff01; 首先点这里的 … 点击扩展 接着选择“管理扩展” 点击之后搜索“wetab” 最后你需要注册一个号&#xff0c;然后就可以使用CHAT-AI啦&#x…

28位驻华大使、公使参访苏州金龙 点赞刚刚全球发布的新V系大巴

3月26日下午&#xff0c;由外交部组织的“驻华使节团参访江苏”活动走进苏州金龙。来自28个国家和国际组织的驻华大使、公使参观了苏州金龙展厅&#xff0c;并试乘体验了苏州金龙全新V系大巴。外交部中国政府欧洲事务特别代表吴红波&#xff0c;外交部礼宾司、翻译司、非洲司、…

产品力升级:揭秘产品力课程,打造竞争力强劲的爆款产品

在当今激烈的市场竞争中&#xff0c;产品力是企业成功的关键之一。那么&#xff0c;什么是产品力?什么是产品力课程&#xff1f;产品力课程如何帮助企业打造竞争力强劲的爆款产品?本文将为您一一解答。 什么是产品力? 产品力指的是一个产品在市场竞争中所具备的能力和优势。…

浏览器导出excel

做java web项目时&#xff0c;经常遇到需要在页面上点击导出按钮&#xff0c;然后直浏览器接下载下来一个excel文档。 比如一个List<Person>的集合&#xff0c;需要将每个Person当做一行&#xff0c;输出到excel中去。其中Person实体类如下&#xff1a; import lombok.…

PTA-练习9

目录 实验10-4 递归实现顺序输出整数 实验10-10 十进制转换二进制 实验10-6 递归求简单交错幂级数的部分和 实验11-1-2 输出月份英文名 实验11-1-6 指定位置输出字符串 实验11-1-8 查找子串 递归的基本思路&#xff1a; 推出递归的条件或者进入递归的条件每层递归需要执行…

手把手教你绘画原型图:Axure的安装使用

&#x1f341; 作者&#xff1a;知识浅谈&#xff0c;CSDN签约讲师&#xff0c;CSDN博客专家&#xff0c;华为云云享专家&#xff0c;阿里云专家博主 &#x1f4cc; 擅长领域&#xff1a;全栈工程师&#xff0c;大模型&#xff0c;爬虫、ACM算法 &#x1f492; 公众号&#xff…

DC-3靶机

一.环境搭建 下载地址&#xff1a; http://www.five86.com/downloads/DC-3-2.zip 下载不下来的可以用迅雷输入上面的网址进行下载 虚拟机配置&#xff1a; 切换连接桥接模式为nat模式&#xff0c;启动靶机&#xff0c;出现如下报错&#xff0c;进入虚拟机配置 选中CD/DVD&…

通过Appium和Xcode Accessibility Inspector获取iOS应用元素定位的方法

在 iOS 移动应用程序上使用选择器查找元素定位是我们在移动端 UI 自动化测试的先决条件。 但是&#xff0c;由于应用程序内容在原生 iOS 应用程序中的呈现方式&#xff0c;我们可以用来定位应用程序元素的选择器与 Web 浏览器元素有很大不同。 在本文中&#xff0c;我们将了解 …

百元开放式耳机怎么选?五款入手不亏的上乘产品推荐

耳机已经成为了我们生活中不可或缺的一部分&#xff0c;无论是通勤路上的音乐陪伴&#xff0c;还是家中观影的沉浸体验&#xff0c;一款优质的耳机都能为我们带来极大的享受。而在众多耳机类型中&#xff0c;开放式耳机因其独特的声场表现和舒适的佩戴体验&#xff0c;受到了越…

弹性伸缩 AS

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

JavaScript进阶5之垃圾回收(计算机组成、解释与编译、JavaScript引擎、垃圾回收、内存管理)、运行机制(浏览器进程分类、浏览器事件循环)

垃圾回收&运行机制 垃圾回收计算机组成解释与编译JavaScript引擎V8引擎 垃圾回收引用计数法标记清除&#xff08;mark-sweep&#xff09;算法 内存管理新生代 运行机制浏览器进程分类&#xff1a;浏览器事件循环宏任务微任务整体流程浏览器事件循环案例一案例二 垃圾回收 …