Golang作为一种“更好的C语言“,提供了面向对象编程思想的支持。
这一篇是上一篇的补充,主要阐述了go语言面向对象的一些特性,值传递和指针传递在go语言的运用,并补充了一些golang的数据类型
目录
在go中你可以为任何类型添加相应的方法:
//为类型添加方法
type Integer int
//面向对象操作,对象是Integer这个类型的a值
func (a Integer) Less(b Integer) bool {
return a < b
}
//面向对象调用
func main() {
var a Integer = 1
if a.Less(2) {
fmt.println(a, " Less 2")
}
}
同时,我们也可以像之前一样面向过程
type Integer int
func Integer_less(a Integer, b Integer) bool {
return a < b
}
func main() {
var a Integer = 1
if Integer_less(a, 2) {
fmt.Println(a, " less 2")
}
}
所以能清楚的看出来两者的区别 有助于我们读懂并做好代码 避免有的时候自己调用自己
首先我们要知道什么是this指针
在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。
在其他语言中比如C#和java,都遵循着C++的惯例,他们的成员方法都有着隐藏的this指针,而python的成员方法中有self参数和this指针作用相同。
在go中没有隐藏的this指针
这句话的含义是:方法施加的目标(即对象),没有被隐藏起来;方法施加的目标(即对象)不需要是指针,也不用非得是this。这里可能有点绕,需要对值传递和引用传递有一定了解,上节我们知道go和C语言一样是基于值传递,要想改变该变量的指针必须传递指针,所以go只有在你需要修改对象的时候,才必须使用指针。比如下面的两个例子:
//指针传递
func (a *Integer) Add(b Integer) {
*a += b
}
//值传递
func (a Integer) Add(b Integer) {
a += b
}
//验证
func main() {
var a Integer = 1
a.Add(2)
//指针传递结果为3
//值传递结果为1
fmt.Println("a = ", a)
}
值语义:
变量赋值后,两个变量拥有的存储空间是独立的,相互之间不影响
引用语义:
变量引用赋值后,两个变量只有一份的存储空间,相互之间可以理解为是别名,操作任意一个变量,就可以认为是操作另外一个变量,效果完全一样
b = a //值类型
b.Modify() //引用类型
如果b的修改不影响a的值,那么此类型属于值类型
如果会影响a的值,那么此类型为引用类型
我们可以把go语言所有类型看成是值类型,从这个角度再深入看几个看起来像引用类型的golang类型,他们都是通过指针传递值,所以对于两个指向同一块数据的a或者b进行底层数据的修改来说,两者是互相影响的,比如a[0]=1, 这个是相当于作用于底层市局data
但是若是直接修改a或者b,比如a=[]int{},那么就相当于a对应的struct的值变了,里面的指针p变了之后,就相当于指向了另外一个data。这个时候a和b之间的操作就没有关系了
1. 数组切片
数组切片是指向数组的一个区间
我们复习一下数组切片长这样:
var slice1 []type = make([]type, len) //声明切片长度和类型的数组切片
也可以简写为
slice1 := make([]type, len)
数组切片本质是一个区间,你可以大致理解为这样一个结构:
type slice struct {
first *T
len int
cap int
}
因为数组切片内部是指向数组的指针,所以可以改变指向数组元素,其类型本身仍是值语义。
2. map
提供键值查询能力,和我们常见的数据结构相同
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
/* 你可以讲map[k]v表示为:*/
type Map_k_v struct {
//...
}
type Map[k]v struct {
impl *Map_k_v
}
3.channel
执行体(goroutine)间的通信设施,和map类似,本质上是一个指针
ch := make(chan int)
4. 接口
对一组满足某个契约的类型的抽象
//内部维持两个指针
type Interface struct {
data *void
itab *Itab
}
go的结构体(struct)放弃了大量包括继承在内的面向对象属性,只保留了组合这个最基础的属性。go语言中结构体的使用方式和C语言相同:
//定义结构
type Rect struct {
x, y float64
width, height float64
}
//使用
func (r *Rect) Area() float64 {
return r.width * r.height
}
结构初始化
在go中未显示初始化的变量会被初始化成该类型的零值,而且没有构造函数的概念,对象的创建由写在外面独立的全局的构造函数来完成:
func NewRect (x, y, width, height float64) *Rect {
return &Rect(x, y, width, height)
}
Struct 类似于 java 中的类,可以在 struct 中定义成员变量。
要访问成员变量,可以有两种方式:
1.通过 struct 变量.成员 变量来访问。
2.通过 struct 指针.成员 变量来访问。
不需要通过 getter, setter 来设置访问权限。
参考资料:Go语言编程