十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
目录
汉南网站制作公司哪家好,找创新互联!从网页设计、网站建设、微信开发、APP开发、响应式网站设计等网站项目制作,到程序开发,运营维护。创新互联2013年至今到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联。
一、结构体详解
1. 结构体定义
2. 实例化结构体的7种方法
二、结构体方法
1. 结构体的方法定义
2. 结构体内自定义方法的引用
3. 任意类型添加方法
三、嵌套、继承
1. 匿名结构体
2. 结构体中可以定义任意类型的字段
3. 结构体嵌套结构体
4. 结构体嵌套匿名结构体
5. 结构体嵌套多个匿名结构体
6. 结构体继承
四、结构体和JSON相互转换
1. 结构体转化成json
2. json转化成结构体
3. 结构体标签 tag
4. 嵌套结构体和json的序列化反序列化
Golang 中没有“类”的概念,Golang 中的结构体和其他语言中的类有点相似。和其他面向对 象语言中的类相比,Golang 中的结构体具有更高的扩展性和灵活性。
Golang 中的基础数据类型可以表示一些事物的基本属性,但是当我们想表达一个事物的全 部或部分属性时,这时候再用单一的基本数据类型就无法满足需求了,Golang 提供了一种 自定义数据类型,可以封装多个基本数据类型,这种数据类型叫结构体,英文名称 struct。 也就是我们可以通过 struct 来定义自己的类型了。
使用 type 和 struct 关键字来定义结构体,具体代码格式如下:
type 类型名 struct {
字段名 字段类型
字段名 字段类型 …
}
其中:
• 类型名:表示自定义结构体的名称,在同一个包内不能重复。
• 字段名:表示结构体字段名。结构体中的字段名必须唯一。
• 字段类型:表示结构体字段的具体类型。
在 go 语言中,没有类的概念但是可以给类型(结构体,自定义类型)定义方法。所谓方法 就是定义了接收者的函数。接收者的概念就类似于其他语言中的 this 或者 self。
方法的定义格式如下:
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
函数体
}
注意:想改变结构体内的值,必须先变成指针。
在 Go 语言中,接收者的类型可以是任何类型,不仅仅是结构体,任何类型都可以拥有方法。 举个例子,我们基于内置的 int 类型使用 type 关键字可以定义新的自定义类型,然后为我们 的自定义类型添加方法。
注意:匿名结构体中不允许出现多个重复的类型
注意:如果结构体里面有私有属性也就是小写定义的字段,则不会被json使用
作为C语言家族的一员,go和c一样也支持结构体。可以类比于java的一个POJO。
在学习定义结构体之前,先学习下定义一个新类型。
新类型 T1 是基于 Go 原生类型 int 定义的新自定义类型,而新类型 T2 则是 基于刚刚定义的类型 T1,定义的新类型。
这里要引入一个底层类型的概念。
如果一个新类型是基于某个 Go 原生类型定义的, 那么我们就叫 Go 原生类型为新类型的底层类型
在上面的例子中,int就是T1的底层类型。
但是T1不是T2的底层类型,只有原生类型才可以作为底层类型,所以T2的底层类型还是int
底层类型是很重要的,因为对两个变量进行显式的类型转换,只有底层类型相同的变量间才能相互转换。底层类型是判断两个类型本质上是否相同的根本。
这种类型定义方式通常用在 项目的渐进式重构,还有对已有包的二次封装方面
类型别名表示新类型和原类型完全等价,实际上就是同一种类型。只不过名字不同而已。
一般我们都是定义一个有名的结构体。
字段名的大小写决定了字段是否包外可用。只有大写的字段可以被包外引用。
还有一个点提一下
如果换行来写
Age: 66,后面这个都好不能省略
还有一个点,观察e3的赋值
new返回的是一个指针。然后指针可以直接点号赋值。这说明go默认进行了取值操作
e3.Age 等价于 (*e3).Age
如上定义了一个空的结构体Empty。打印了元素e的内存大小是0。
有什么用呢?
基于空结构体类型内存零开销这样的特性,我们在日常 Go 开发中会经常使用空 结构体类型元素,作为一种“事件”信息进行 Goroutine 之间的通信
这种以空结构体为元素类建立的 channel,是目前能实现的、内存占用最小的 Goroutine 间通信方式。
这种形式需要说的是几个语法糖。
语法糖1:
对于结构体字段,可以省略字段名,只写结构体名。默认字段名就是结构体名
这种方式称为 嵌入字段
语法糖2:
如果是以嵌入字段形式写的结构体
可以省略嵌入的Reader字段,而直接访问ReaderName
此时book是一个各个属性全是对应类型零值的一个实例。不是nil。这种情况在Go中称为零值可用。不像java会导致npe
结构体定义时可以在字段后面追加标签说明。
tag的格式为反单引号
tag的作用是可以使用[反射]来检视字段的标签信息。
具体的作用还要看使用的场景。
比如这里的tag是为了帮助 encoding/json 标准包在解析对象时可以利用的规则。比如omitempty表示该字段没有值就不打印出来。
GO是编译性语言,所以函数的顺序是无关紧要的,为了方便阅读,建议入口函数 main 写在最前面,其余函数按照功能需要进行排列
GO的函数 不支持嵌套,重载和默认参数
GO的函数 支持 无需声明变量,可变长度,多返回值,匿名,闭包等
GO的函数用 func 来声明,且左大括号 { 不能另起一行
一个简单的示例:
输出为:
参数:可以传0个或多个值来供自己用
返回:通过用 return 来进行返回
输出为:
上面就是一个典型的多参数传递与多返回值
对例子的说明:
按值传递:是对某个变量进行复制,不能更改原变量的值
引用传递:相当于按指针传递,可以同时改变原来的值,并且消耗的内存会更少,只有4或8个字节的消耗
在上例中,返回值 (d int, e int, f int) { 是进行了命名,如果不想命名可以写成 (int,int,int){ ,返回的结果都是一样的,但要注意:
当返回了多个值,我们某些变量不想要,或实际用不到,我们可以使用 _ 来补位,例如上例的返回我们可以写成 d,_,f := test(a,b,c) ,我们不想要中间的返回值,可以以这种形式来舍弃掉
在参数后面以 变量 ... type 这种形式的,我们就要以判断出这是一个可变长度的参数
输出为:
在上例中, strs ...string 中, strs 的实际值是b,c,d,e,这就是一个最简单的传递可变长度的参数的例子,更多一些演变的形式,都非常类似
在GO中 defer 关键字非常重要,相当于面相对像中的析构函数,也就是在某个函数执行完成后,GO会自动这个;
如果在多层循环中函数里,都定义了 defer ,那么它的执行顺序是先进后出;
当某个函数出现严重错误时, defer 也会被调用
输出为
这是一个最简单的测试了,当然还有更复杂的调用,比如调试程序时,判断是哪个函数出了问题,完全可以根据 defer 打印出来的内容来进行判断,非常快速,这种留给你们去实现
一个函数在函数体内自己调用自己我们称之为递归函数,在做递归调用时,经常会将内存给占满,这是非常要注意的,常用的比如,快速排序就是用的递归调用
本篇重点介绍了GO函数(func)的声明与使用,下一篇将介绍GO的结构 struct
黑马程序员最近刚出了一套go语言的教程,我刚看了一些,从基础讲起,很适合新手学,听说,黑马的c/c++的课程中,将加入go语言的教学。