文章目录
结构体
go语言的面向对象由结构体实现,结构体是值类型,可以使用new来创建。
定义
结构体定义如下所示:
type identifier struct{
filed1 type
filed2 type
}
filed就是结构体的字段名字,type是字段的类型,如果暂时不知道命名,可以使用 _ 来进行占位。字段可以使用任何类型,甚至是结构体本身,也可以是函数或者接口。
初始化
初始化类似c++,可以直接声明后赋值,也可以用new关键字分配,具体如下操作
package main
type ListNode struct {
Val int
Next *ListNode
}
func main() {
//直接声明
var node ListNode
node.Val =1
//new出来
node2:=new(ListNode)
node2.Val=2
}
成员方法
结构体内定义,外部实现
在定义时,你可以发现,type可以是func,所以就为结构体的成员方法提供了一个实现渠道。
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
toString func()
}
func doSth() {
fmt.Println("do something")
}
func main() {
var node ListNode
node.Val =1
node.toString=doSth
node.toString()
}
虽然写完发现写得挺离谱的,要说是成员方法,却无法访问node的属性,必须传进去才可以。
结构体外实现真正的成员方法
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
//值传递下的成员方法,无法改变node真正的属性
func (node ListNode)setVal(val int) {
node.Val=val
}
//引用传递下的成员方法,可以改变node的真正属性
func (node *ListNode)setVal2(val int) {
node.Val=val
}
func main() {
var node ListNode
node.Val =1
node.setVal(2)
fmt.Println(node.Val)
(&node).setVal2(2)
fmt.Print(node.Val)
}
字段的辅助字符串
字段的辅助字符串是与字段声明在同一行的字符串,只能通过反射获取
package main
import (
"fmt"
"reflect"
)
type Person struct {
Name string "Name"
Age int "Age"
Sex int "Sex"
}
func main() {
person := Person{}
person.Name = "Tim"
person.Age = 10
person.Sex = 1
for i := 0; i < 3; i++ {
refTag(person, i)
}
}
func refTag(p Person, i int) {
pType := reflect.TypeOf(p)
iFiled := pType.Field(i)
fmt.Println(iFiled.Tag)
}
reflect.TypeOf可以获取变量的正确类型,如果变量是一个结构体,就可以通过Filed来索引该结构体的字段,然后就可以使用Tag属性。
匿名字段
go结构体还支持一个特殊字段,匿名字段。这些字段没有显式的名字,只有字段类型,此时字段类型也就是字段的名字,匿名字段也可以是一种结构体。所以相同种类的匿名字段只能有一个。
type Test1 struct {
t1 int
t2 int
}
type Test struct {
a int
b string
bool
Test1
}
func main() {
test := new(Test)
test.a = 1
test.b = "2"
test.bool = true
test.t1 = 2
test.t2 = 3
fmt.Println(test)
}
继承
一个结构体嵌到另一个结构体,称作组合
匿名和组合的区别
如果一个struct嵌套了另一个匿名结构体,那么这个结构可以直接访问匿名结构体的方法,从而实现继承
如果一个struct嵌套了另一个【有名】的结构体,那么这个模式叫做组合
如果一个struct嵌套了多个匿名结构体,那么这个结构可以直接访问多个匿名结构体的方法,从而实现多重继承
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
//组合
type TreeNode struct {
lnode ListNode
}
//继承
type GraphNode struct {
ListNode
}
//值传递下的成员方法,无法改变node真正的属性
func (node ListNode)setVal(val int) {
node.Val=val
}
//引用传递下的成员方法,可以改变node的真正属性
func (node *ListNode)setVal2(val int) {
node.Val=val
}
func main() {
var treeNode TreeNode
treeNode.lnode.setVal2(1)
var graphNode GraphNode
graphNode.setVal2(2)
}