go语言学习-结构体
结构体
go语言中的结构体,是一种复合类型,有一组属性构成,这些属性被称为字段。结构体也是值类型,可以使用new来创建。
定义:
type name struct {
field1 type1
field2 type2
...
}
我们可以看到每一个字段都由一个名字和一个类型构成,不过实际上,如果我们如果不需要使用某个字段时,可以使用”_”来代替它的名字
并且结构体字段可以是任意类型,函数,接口,甚至是结构体本身都可以
使用结构体
定义一个Person结构体
type Person struct {
name string
age int
}
使用
// 字面量形式初始化
var p1 = Person{
name: "Tom",
age: 18,
}
var p2 = Person{"Cat", 20}
fmt.Println(p1) //{Tom 18}
fmt.Println(p1.name) // Tom
fmt.Println(p2) // {Cat 20}
p1.age = 20 // 设置p的age字段的值
fmt.Println(p1) // {Tom 20}
还可以使用new函数来给一个结构体分配内存,并返回指向已分配内存的指针
var p3 *Person // 声明一个Person类型的指针
p3 = new(Person) // 分配内存
// 上面两句相当于
p3 := new(Person)
p3.name = "Cat"
p3.age = 10
fmt.Println(p3) // &{Cat 10}
fmt.Println(p3.name) //
我们可以直接使用结构体指针通过”.”来访问结构体的字段,就像直接使用结构体实例一样, go会自动进行转换
还有一种叫做混合字面量的语法来声明,如下,这其实只是一种简写方式,底层还是调用new方法
var p4 = &Person{"Dog", 10} // 同样返回的是Person类型的指针
fmt.Println(p4) // &{Dog 10}
fmt.Println(p4.name) // Dog
匿名字段
go语言的结构体还支持匿名字段,也就是说一个只有类型而没有字段名(连”_”都没有)的字段,被匿名嵌入的也可以是任何类型,此时类型名就是字段的名字,也就是我们可以直接使用类型名为字段名来访问匿名字段.
另外如果匿名字段是另一个结构体,这就叫做内嵌结构体,这个特性可以模拟类似继承的行为。
type Person struct {
name string
age int
}
type Student struct {
Person
int
}
// 定义一个Student类型的变量
var s = Student{Person{"gdb", 10}, 10}
// 可以使用如下的方法访问内部结构体中的字段
fmt.Println(s.Person.name)
// 也可以这样访问,go将自动使用Person的name属性,不过如果在Student中也定义了name字段,这里就不能使用了
fmt.Println(s.name)
// 访问int类型的匿名字段,此时类型就是字段的名字
fmt.Println(s.int)
注意:这样如果两个字段有相同的名字时,外部的名字会覆盖内部的;如果同一级别出现相同名字的字段,会出错,需要注意;并且不能同时嵌⼊某⼀类型和其指针类型,因为它们名字相同。
标签
结构体中的字段除了可以有名称和类型以外,还可以有标签。它是一个附属于字段的字符串,可以是文档或其他的重要标记。后面说反射时再说。
方法
之前学习的面向对象语言,比如说Java, Python中,有类的概念,每个类都可以有自己的成员变量,成员方法,它们都是定义在类中的
go语言中的结构体就类似与面向对象语言的类,而结构体的字段就相当于类中的成员变量,结构体也可以有方法,但是不是直接定义在结构体中的,go语言中有一个接收者的概念,我们可以将函数作用在一个接收者,此时这个函数就被称为方法
接收者是某种类型的变量,不仅仅可以是结构体,几乎任何类型都可以是结构体,比如: int,bool, string或数组的别名类型,甚至可以是函数类型,不过不能是接口类型
定义方法的示例:
type Person struct {
name string
age int
}
// 使用Person类型的实例做接收者,这就是一个Person类型方法,方法名前面括号中的就是接收者
func (this Person) getName() string {
return this.name
}
// Peron类型的指针对象也可以作为接收者
func (this *Person) setName(name string) {
this.name = name
}
tom := Person{"Tom", 20}
fmt.Println(tom) // {Tom 20}
fmt.Println(tom.getName()) // Tom
tom.changeName("Bob")
fmt.Println(tom) // {Bob 20}
这里有一点需要注意:类型和绑定它的方法必须在同一个包中(不一定要在同一个文件中)
这里使用类型直接作为接收着 和 类型的指针作为接收者的区别,就相当于普通函数中,值类型的参数和引用类型参数的区别;即在方法中对类型的实例的操作,不会影响外部的实例的值,而使用类型指针的实例作为引用参数,在方法内部修改会影响外部的实例
匿名字段
我们也可以使用结构体内部的匿名字段,作为方法的接收者,此时这个结构体,仍然可以调用这个方法,此时编译器会负责查找
type Person struct {
name string
age int
}
type Student struct {
Person
score int
}
func (p *Person) show() {
fmt.Println("My name is " + p.name + ", I'm " + strconv.Itoa(p.age) + " years old")
}
tom := Person{"Tom", 20}
// 调用匿名字段作为接收器的方法
tom.show() // My name is Tom, I'm 20 years old
在此基础上,我们还可以在结构体上,实现与匿名字段同名的方法,就像面向对象中的重写类似,编译器会先查找结构体实例作为接收器的方法。
方法集
根据定义结构体以及方法的不同,方法集也有所不同,了解他们,对理解接口有帮助
type T struct {
name string
age int
}
type G struct {
T
action string
}
type S struct {
*T
sel string
}
- 类型 T 的方法集包含所有接收者为 T 的方法
- 类型*T的方法集包含所有接收者为 T的方法(因为go会自动解引用)和所有接收者为 *T 的方法
- 类型G包含匿名字段 T, 则G的方法集,仅仅包含T类型的方法集
- 类型S包含匿名字段 *T,则S的方法集,包含T和*T类型的方法集
go语言学习-结构体的更多相关文章
- ios开发中的C语言学习—— 结构体简介
在开发过程中,经常会需要处理一组不同类型的数据,比如学生的个人信息,由姓名.年龄.性别.身高等组成,因为这些数据是由不同数据类型组成的,因此不能用数组表示,对于不同数据类型的一组数据,可以采用结构体来 ...
- 01.C语言关于结构体的学习笔记
我对于学习的C语言的结构体做一个小的学习总结,总结如下: 结构体:structure 结构体是一种用户自己建立的数据类型,由不同类型数据组成的组合型的数据结构.在其他高级语言中称为记录(record) ...
- C语言链表结构体(学习笔记)
#include <stdio.h> #define LENTEST 100 // 采取逐步删除的方法求的素数 //先假设1-100都是素数,然后剔除2的倍数, //3的倍数,直到剔除所有 ...
- Go语言 6 结构体、方法和接口
文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ Go学习群:415660935 结构体(struct)是由一系列具有相同类型或不同类 ...
- C语言中结构体赋值问题的讨论
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- C语言的结构体和C++结构体的区别
关于C++中声明结构体中需要使用构造器创建实例对象的语法: <C++的结构体构造方法的基本概念:结构体的构造方法需要和结构体的名字相同,并且无返回值,也不要void关键字,这样的方法就是构造器的 ...
- C语言中结构体对齐问题
C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...
- 逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式
逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式 一丶了解什么是结构体,以及计算结构体成员的对其值以及总大小(类也是这样算) 结构体的特性 1.结构体(struct)是由一系列具有相同类型或不 ...
- C语言中结构体赋值问题的讨论(转载)
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
随机推荐
- 2018-2019-2 网络对抗技术 20165230 Exp4 恶意代码分析
目录 1.实验内容 2.实验过程 任务一:系统运行监控 每隔五分钟记录自己的电脑,并进行分析 安装配置sysinternals里的sysmon工具 任务二:恶意软件分析 静态分析工具 ViruScan ...
- nginx入门一
配置文件: server_name user root; worker_processes 2; error_log logs/error-test.log; #pid logs/nginx.pid; ...
- MR室内室外用户区分
mro_view_details_year中v3字段 1:室外用户 0:室内用户 主小区是室内站 主小区信号>-90dBm ==> 室内 主小区信号>-100dBm &&am ...
- AF_INET域与AF_UNIX域socket通信原理对比【转】
转自:https://www.cnblogs.com/lfxiao/p/9672797.html 1. AF_INET域socket通信过程 典型的TCP/IP四层模型的通信过程. 发送方.接收方依 ...
- linux 串口0x03,0x13的问题【转】
linux 串口0x03,0x13的问题 本人最近在调linux串口的时候,发现其他数据接收正常,但是0x13怎么也接收不到,后面发现了这篇文章,两天的bug终于解决了,原来是linux底层uart配 ...
- [ VB ] If 运算符 [ C# ] 条件运算符 (?:)
//保留了原文 ()为大概的意思 VB で使用していた IIf 関数の代わりに VB2008 からは If 演算子 を使用可能となった. また. C# では.条件演算子 (?:) で同等の記述が可 ...
- 一步步实现windows版ijkplayer系列文章之六——SDL2源码分析之OpenGL ES在windows上的渲染过程
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- 转载:为什么选择Nginx(1.2)《深入理解Nginx》(陶辉)
原文:https://book.2cto.com/201304/19610.html 为什么选择Nginx?因为它具有以下特点: (1)更快 这表现在两个方面:一方面,在正常情况下,单次请求会得到更快 ...
- convertToNodeSpace和convertToWorldSpace ---实际应用
游戏中经常会用到一些变换: 游戏中武器和角色在一个layer上,为了效率,会考虑将bullet, effect和 PhysicsParticle分别放到不用的层上,对应的层上使用batchnode来提 ...
- Linux内核移植
实验步骤:(1)准备工作(2)修改顶层Makefile(3)修改falsh 分区(4)配置编译内核 下面以Linux2.6.30.4内核移植到gec2440为例: 一.准备工作:建立工作目录,下载内核 ...