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()
}
看下结果:
可以看出来 函数参数不是指针的方法,修改struct的值 是完全无效的。
实际上对于go语言来说,操作struct时 更推荐用指针作为参数,因为性能更好,否则会触发一次 拷贝的操作。
其余一些重要的知识点
go文件的包名可以和文件夹名称不一样,这和java不同
同一个文件夹下,所有go文件的 包名都必须一致
首字母大写 其他包才能引用到 才是public的
要理解好函数的recevier这个概念,go中的receiver与kotlin语言的receiver 十分接近
// 括号内 代表这个函数的 receiver 代表只有这个 struct 才可以调用
// 这和其他语言把方法定义在所谓class里面 是不同的
func (node TreeNode) print(){
fmt.Println(node.value)
}