golang(07)结构体介绍

golang支持面向对象的设计,一般支持面向对象的语言都会有class的设计,但是golang没有class关键字,只有struct结构体。通过结构体达到类的效果,这叫做大成若缺,其用不弊。

struct简介

在使用struct之前,先介绍golang的一个特性,golang允许用户将类型A定义为另一种类型B,并为类型B添加方法。

1234
type Integer int func (a Integer) Less (b Integer) bool{    return a < b}

我们将int定义为一种新的类型Integer,Integer就和int不是一个类型了,这和C++不一样。然后为Integer添加了方法Less,所有Integer对象都可以使用Less方法。类似于C++的成员函数。下面我们使用一下

12345
func main() {	var varint1 Integer = 100	var varint2 Integer = 200	fmt.Println(varint1.Less(varint2))}

定义了两个变量varint1和varint2,调用了varint1的Less方法,输出true
下面介绍struct的基本定义

12345
//构造函数和初始化type Rect struct{    x,y float64    width, height float64}

定义了一个结构体Rect,Rect包含四个成员,x,y为float64类型,width, height为float64类型。
下面为Rect定义方法,计算矩形面积

123
func (r* Rect) Area() float64{    return r.width* r.height}

golang结构体没有public,private等字段,是通过成员的大小写区分权限的。大写的结构体成员,别的包可以访问,小写的成员不可被别的包访问。
Rect的成员都为小写,所以别的包无法访问,但是可以通过定义大写的方法,提供给别的包访问

12345678910111213141516171819
func (r *Rect) GetX() float64 {	return r.x}

func (r *Rect) GetY() float64 {	return r.y}

func (r *Rect) Area() float64 {	return r.width * r.height}

func (r *Rect) GetWidth() float64 {	return r.width}

func (r *Rect) GetHeight() float64 {	return r.height}

这样其他的包就可以通过Rect的方法访问Rect内部变量值了。

结构体方法和函数的区别

结构体方法就好比是C++的成员函数,是类对象调用的方法。函数和结构体对象无关,可以自由编写。
二者定义也有区别

1234567
func (this* 结构体类型) 方法名(方法参数列表) 方法返回值{    //方法内部实现}

func 函数名(函数参数列表) 函数返回值{    //函数内部实现}

golang的精髓是组合

123456789
type Inner struct {	Name string	Num  int}

type Wrappers struct {	inner Inner	Name  string}

Wrappers 包含了Inner结构体,golang中叫做组合。下面写代码打印信息,我们先为Wrappers添加方法

12345
func (wp *Wrappers) PrintInfo() {	fmt.Println(wp.Name)	fmt.Println(wp.inner.Name)	fmt.Println(wp.inner.Num)}

定义变量调用方法

1234
func main() {	wp := &Wrappers{Name: "wrapper", inner: Inner{Name: "inner", Num: 100}}	wp.PrintInfo()}

打印结果如下

123
wrapperinner100

组合后,打印内部成员inner的Name需要显示指定wp.inner.Name,因为默认打印wp.Name是Wrappers的。

匿名组合实现继承(派生)

12345678910111213141516171819202122
//匿名组合和派生type Base struct {	Name string}

func (base *Base) Foo() {	fmt.Println("this is Base Foo")}

func (base *Base) Bar() {	fmt.Println("this is Base Bar")}

type Foo struct {	//匿名组合	Base}

func (foo *Foo) Foo() {	foo.Base.Foo()	fmt.Println("this is Foo Foo")}

Foo内部组合了Base,但是并没有显示指定成员名,Foo内部只写了Base类型,这叫做匿名组合,
匿名组合会在Foo内部自动生成Base同名的成员变量Base,golang根据匿名组合,会认为Foo继承自Base,
从而Foo拥有Base的方法和成员。下面写代码看看效果

1234567891011
func main() {	foo := &Foo{}	//Foo继承Base,所以拥有Name属性	foo.Name = "foobase"	//Foo 重写(覆盖)了Base的Foo	foo.Foo()	//Foo继承了Base的Bar函数	foo.Bar()	//显示调用基类Base的Foo	foo.Base.Foo()}

由于Foo继承Base后重写了Foo方法,所以想要调用Base的Foo方法,需要显示调用。

匿名指针组合

匿名组合如果是指针类型,在子类对象定义时需要显示初始化基类指针,否则会出问题。
先定义匿名组合结构体

12345678910
//匿名指针组合type DerivePoint struct {	*Base}

func (derivep *DerivePoint) Foo() bool {	fmt.Println("this is DerivePoint Foo")	fmt.Println("inherit base ,name is ", derivep.Name)	return true}

定义了DerivePoint类,和方法Foo,在Foo内部打印了derivep的Name,该Name继承自*Base
下面调用

12
dr := &DerivePoint{Base: &Base{Name: "base"}}dr.Foo()

输出如下

12
this is DerivePoint Fooinherit base ,name is  base

可见输出了Name值。

匿名组合造成命名冲突

123456
//重复定义,因为匿名组合默认用类型做变量名type MyJob struct {	*Logger	Name string	*log.Logger // duplicate field Logger}

MyJob匿名组合了Logger类和log.Logger类,由于匿名组合默认用类型做变量名,所以编译器会认为定义了两个Logger名的成员,
从而报错,所以匿名组合一定要注意这一点。

多重继承

golang 支持多重继承,实现多重继承只需要多个匿名组合即可。

原文地址:https://www.cnblogs.com/secondtonone1/p/11510965.html

时间: 2024-10-10 13:25:14

golang(07)结构体介绍的相关文章

Golang 入门 : 结构体(struct)

Go 通过类型别名(alias types)和结构体的形式支持用户自定义类型,或者叫定制类型.试图表示一个现实世界中的实体. 结构体由一系列命名的元素组成,这些元素又被称为字段,每个字段都有一个名称和一个类型. 结构体的目的就是把数据聚集在一起,以便能够更加便捷地操作这些数据.结构体的概念在 C 语言里很常见,被称为 struct.Golang 中的结构体也是 struct.Go 语言中没有类的概念,因此在 Go 中结构体有着更为重要的地位.结构体是复合类型(composite types),当

[Windows内核分析]KPCR结构体介绍 (CPU控制区 Processor Control Region)

Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 逆向分析操作系统内核代码至少需要具备两项技能: 段页汇编代码非常懂. 至少掌握三个结构体:EPROCESS.ETHRAEAD.KPCR(注意:EPROCESS.ETHREAD是在R0,在R3的是PEB与TEB.) 一.KPCR结构体介绍 当线程进入0环时,FS:[0]指向KPCR(3环时 FS:[0] --> TEB,如果想了解这个信息,可以看这篇博客利用C++实

libEvent结构体介绍

1 event_base 01.struct event_base { 02. const struct eventop *evsel; 03. void *evbase; 04. int event_count; 05. int event_count_active; 06. int event_gotterm; 07. int event_break; 08. // active event management 09. struct event_list **activequeues; 1

golang之结构体和方法

结构体的定义 结构体是将零个或者多个任意类型的命令变量组合在一起的聚合数据类型.每个变量都叫做结构体的成员. 其实简单理解,Go语言的结构体struct和其他语言的类class有相等的地位,但是GO语言放弃了包括继承在内的大量面向对象的特性,只保留了组合这个基础的特性.所有的Go语言类型除了指针类型外,都可以有自己的方法. 先通过一个下的例子理解struct. package main import "fmt" type Student struct { Name string Age

golang中结构体的初始化方法(new方法)

自定义一个结构体 type Rect struct { x, y float64 width, height float64 } 初始化方法: rect1 := new(Rect) rect2 := &Rect{} rect3 := &Rect{0, 0, 100, 200} rect4 := &Rect{width:100, height:200} 注意这几个变量全部为指向Rect结构的指针(指针变量),因为使用了new()函数和&操作符.而如果使用方法 a := Rec

golang之结构体

构造函数 Go语言的结构体没有构造函数,我们可以自己实现. 例如,下方的代码就实现了一个person的构造函数. 因为struct是值类型,如果结构体比较复杂的话,值拷贝性能开销会比较大,所以该构造函数返回的是结构体指针类型. type person struct { name string city string age int8 } func newPerson(name, city string, age int8) *person { return &person{ name: name

golang结构体json的时间格式化解决方案

最近开发项目时候发现一个结构体的Json转换的时间格式问题. 即这种1993-01-01T20:08:23.000000028+08:00 这种表示UTC方法.从我们习惯来说,更喜欢希望的是 1993-01-01 20:08:23这种格式. 重新复现代码如下: package main import (     "time"     "encoding/json" ) type Student struct {     Name string     `json:&

Foundation框架—结构体

一.基本知识 Foundation—基础框架.框架中包含了很多开发中常用的数据类型,如结构体,枚举,类等,是其他ios框架的基础. 如果要想使用foundation框架中的数据类型,那么包含它的主头文件就可以了. 即#import<foundation/foundation.h> 补充:core foundation框架相对底层,里面的代码几乎都是c语言的,而foundation中是OC的. 二.常用的结构体介绍及简单使用 常用的结构体: (一)NSRang的基本使用 创建变量 (二)NSPo

「Foundation」结构体

一.基本知识 Foundation—基础框架.框架中包含了很多开发中常用的数据类型,如结构体,枚举,类等,是其他ios框架的基础. 如果要想使用foundation框架中的数据类型,那么包含它的主头文件就可以了. 即#import<foundation/foundation.h> 补充:core foundation框架相对底层,里面的代码几乎都是c语言的,而foundation中是OC的. 二.常用的结构体介绍及简单使用 常用的结构体: (一)NSRang的基本使用   (二)NSPoint