Go语言- 面向 “对象” 与java的不同

955 阅读2分钟

go中没有其他语言中的继承

go认为有interface足以,不用例如java中的extends 等关键字 来表达所谓子类和父类的关系。这对一些初学者来说 可能会比较迷惑。

举例说明:

先定义一个person 代表人

type Person struct {
   Name string
   Age int
}

func (person Person) print(){
   fmt.Println("name:",person.Name," age: ",person.Age)
}

我们可以基于此 定义一个学生

可以看出来 我们是把 Person 作为一个指针的变量 封装到一个Student中

type Student struct {
   Person *Person
   //班级
   Class string

}

func (stu Student) print(){
   fmt.Println("name:",stu.Person.Name," age: ",stu.Person.Age," class:",stu.Class)
}

最后看下是如何调用的

func main() {
   person:=Person{"wuyue",18}
   person.print()

   stu:=Student{&person,"三班"}
   stu.print()
}

使用 内嵌 语法糖

type NewStudent struct {
   *Person //内嵌 语法糖
   Class string

}

func (stu NewStudent) print(){
   fmt.Println("name:",stu.Name," age: ",stu.Age," class:",stu.Class)
}

使用了内嵌这种语法糖以后 可以看出来是可以省略一些代码的。 不用stu.person 这种写法了。

“alias“ 别名 扩展已有的类型

在go语言中 type还可以充当别的语言中 别名的 作用

例如 我在这里完全可以 定义一个 实质为切片 但是功能上和队列是一个性质的 Queue 结构体

type Queue []int

func (q *Queue) Push(v int) {
   *q = append(*q, v)
}

go是没有构造函数的,一般会用工厂函数来做类似构造函数的操作

func createPersonByName(name string) *Person{
   return &Person{Name: name}
}

go的struct 遵循了严格的值传递

这一点和java有本质的不同。 从java转过来的同学 一开始可能会很不习惯

定义了2个方法

func ChangeAge(person Person,age int){
   person.Age=age
}
func ChangeAge2(person *Person,age int){
   person.Age=age
}

看下实际的调用

func main() {
   person:=Person{"wuyue",18}
   person.print()
   ChangeAge(person,100)
   person.print()
   ChangeAge2(&person,100)
   person.print()
}

看下结果:

image.png

可以看出来 函数参数不是指针的方法,修改struct的值 是完全无效的

实际上对于go语言来说,操作struct时 更推荐用指针作为参数,因为性能更好,否则会触发一次 拷贝的操作。

其余一些重要的知识点

go文件的包名可以和文件夹名称不一样,这和java不同

同一个文件夹下,所有go文件的 包名都必须一致

首字母大写 其他包才能引用到 才是public的

要理解好函数的recevier这个概念,go中的receiver与kotlin语言的receiver 十分接近

// 括号内 代表这个函数的 receiver  代表只有这个 struct 才可以调用
// 这和其他语言把方法定义在所谓class里面 是不同的
func (node TreeNode) print(){
   fmt.Println(node.value)
}