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

struct简介

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

1
2
3
4
type Integer int 
func (a Integer) Less (b Integer) bool{
return a < b
}

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

1
2
3
4
5
func main() {
var varint1 Integer = 100
var varint2 Integer = 200
fmt.Println(varint1.Less(varint2))
}

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

1
2
3
4
5
//构造函数和初始化
type Rect struct{
x,y float64
width, height float64
}

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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++的成员函数,是类对象调用的方法。函数和结构体对象无关,可以自由编写。
二者定义也有区别

1
2
3
4
5
6
7
func (this* 结构体类型) 方法名(方法参数列表) 方法返回值{
//方法内部实现
} func 函数名(函数参数列表) 函数返回值{
//函数内部实现
}

golang的精髓是组合

1
2
3
4
5
6
7
8
9
type Inner struct {
Name string
Num int
} type Wrappers struct {
inner Inner
Name string
}

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

1
2
3
4
5
func (wp *Wrappers) PrintInfo() {
fmt.Println(wp.Name)
fmt.Println(wp.inner.Name)
fmt.Println(wp.inner.Num)
}

定义变量调用方法

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

打印结果如下

1
2
3
wrapper
inner
100

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//匿名组合和派生
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的方法和成员。下面写代码看看效果

1
2
3
4
5
6
7
8
9
10
11
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方法,需要显示调用。

匿名指针组合

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

1
2
3
4
5
6
7
8
9
10
//匿名指针组合
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
下面调用

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

输出如下

1
2
this is DerivePoint Foo
inherit base ,name is base

可见输出了Name值。

匿名组合造成命名冲突

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

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

多重继承

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

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

  1. Golang 入门 : 结构体(struct)

    Go 通过类型别名(alias types)和结构体的形式支持用户自定义类型,或者叫定制类型.试图表示一个现实世界中的实体. 结构体由一系列命名的元素组成,这些元素又被称为字段,每个字段都有一个名称和 ...

  2. 将c语言的结构体定义变成对应的golang语言的结构体定义,并将golang语言结构体变量的指针传递给c语言,cast C struct to Go struct

    https://groups.google.com/forum/#!topic/golang-nuts/JkvR4dQy9t4 https://golang.org/misc/cgo/gmp/gmp. ...

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

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 逆向分析操作系统内核代码至少需要具备两项技能: 段页汇编代码非常懂 ...

  4. Golang操作结构体、Map转化为JSON

    结构体生成Json package main import ( "encoding/json" "fmt" ) type IT struct { Company ...

  5. golang初始化结构体数组

    最近组里新项目要求用go来写,没办法只能边看文档边写代码,今天遇到郁闷的问题,查了好久最终发现居然是一个标点符号的导致的,遂纪录之 刚刚给一个接口写单元测试时想初始化一个结构体数组,然后遍历该数组并建 ...

  6. golang之结构体使用注意事项和细节

    1. 结构体的所有字段在内在中是连续的 2. 结构体是用户单独定义的类型,和其它类型进行转换时需要有完全相同的字段(名字.个数和类型) 3. 结构体进行type重新定义(相当于取别名),Golang认 ...

  7. Golang通过结构体解析和封装XML

    Golang解析和封装XML 解析XML成结构体Demo package main import ( "encoding/xml" "fmt" ) //我们通过 ...

  8. golang 对结构体进行格式化输出

    可以使用 `return fmt.Sprintf("%+v", *conf) ` 来打印结构体,包括结构体的key值.但是由于结构体内容较多,都在一行,所以希望可以格式化输出结构体 ...

  9. golang匿名结构体

    go语言定义结构体类型时可以仅指定字段类型而不指定字段名字.这种字段叫做匿名字段(anonymous field). Go语言有一个特性允许只声明一个成员对应的数据类型而不指名成员的名字:这类成员就 ...

随机推荐

  1. sql like 拼接字符串模糊查询

    这种分割的值大家常用,如果要用like 来查询包含2,这个值的数据有哪些,这个怎么查? like '%2%'  ????,这是不行的如果是 44,125,687 同样可以查出来,那么就想到通配符, l ...

  2. 正则表达式 Regular expression为学习助跑

    这是一个Regular expression的铁路图(至少我现在是这么称呼的)的图形化界面帮助检验和理解我们所写的Regular expression是否正确. 1.官网 :https://regex ...

  3. Python twisted事件驱动网络框架 源码剖析

    一.Twisted简介 Twisted是一个事件驱动的网络框架,其中包含了诸多功能,例如:网络协议.线程.数据库管理.网络操作.电子邮件等. 事件驱动简而言之,事件驱动分为二个部分:第一,注册事件:第 ...

  4. less 分页显示文件内容

    1.命令功能 less 是more的增强版,可以分页显示文件内容,而且less打开文件的速度要比vi,more更快.less支持搜索功能,显示行号. 2.语法格式 less  option  file ...

  5. lib异步中断

    基于libusbx-1.0.18-rc1,libusbx现已重新merage到libusb.1. 初始化使用libusb_init初始化libusb,如果是单设备通信,ctx参数可以传NULL,表示使 ...

  6. IQ基础

      I: in-phase 表示同相Q: quadrature 表示正交,与I 相位差90 度. 现在来解释IQ信号的来源: 最早通讯是模拟通讯,假设载波为cos(a),信号为cos(b),那么通过相 ...

  7. MyBatis-02-第一个Mybatis程序

    2.第一个Mybatis程序 思路:搭建环境-->导入Mybatis-->编写代码-->测试! 2.1.搭建环境 搭建数据库 CREATE DATABASE `mybatis`; u ...

  8. React造轮子:拖拽排序组件「Dragact」

    先来一张图看看: 项目地址:Github地址 (无耻求星!) 在线观看(第一次加载需要等几秒):预览地址 说起来不容易,人在国外没有过年一说,但是毕竟也是中国年,虽然不放假,但是家里总会主内一顿丰盛的 ...

  9. css3属性transform-origin属性讲解

    transform是CSS3里的变换属性,常用的有translate(平移).rotate(旋转).skew(倾斜).scale(缩放)方法.而transform-origin并不是transform ...

  10. shell编程初探

    #! /bin/sh #这是神圣丁的第一个shell脚本 name="陈培昌" echo "我就喜欢\"$name\"" echo '我就喜 ...