浅谈Go语言中的结构体struct & 接口Interface & 反射

2020-01-28 12:28:52王振洲

结构体struct

struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套;

go中的struct类型理解为类,可以定义方法,和函数定义有些许区别;

struct类型是值类型。

struct定义


type User struct {
 Name string
 Age int32
 mess string
}

var user User
var user1 *User = &User{}
var user2 *User = new(User)

struct使用

下面示例中user1和user2为指针类型,访问的时候编译器会自动把 user1.Name 转为 (*user1).Name


func main() {
 var user User
 user.Name = "nick"
 user.Age = 18
 user.mess = "lover"

 var user1 *User = &User{
  Name: "dawn",
  Age: 21,
 }
 fmt.Println(*user1)     //{dawn 21 }
 fmt.Println(user1.Name, (*user1).Name) //dawn dawn

 var user2 *User = new(User)
 user2.Name = "suoning"
 user2.Age = 18
 fmt.Println(user2)      //&{suoning 18 }
 fmt.Println(user2.Name, (*user2).Name) //suoning suoning
}

构造函数

golang中的struct没有构造函数,可以伪造一个


type User struct {
 Name string
 Age int32
 mess string
}

func NewUser(name string, age int32, mess string) *User {
 return &User{Name:name,Age:age,mess:mess}
}

func main() {
 //user := new(User)
 user := NewUser("suoning", 18, "lover")
 fmt.Println(user, user.mess, user.Name, user.Age)
}

内存布局

struct中的所有字段在内存是连续的


var user User
 user.Name = "nick"
 user.Age = 18
 user.mess = "lover"

 fmt.Println(user)     //{nick 18 lover}
 fmt.Printf("Name:%pn", &user.Name) //Name:0xc420016180
 fmt.Printf("Age: %pn", &user.Age) //Age: 0xc420016190
 fmt.Printf("mess:%pn", &user.mess) //mess:0xc420016198 8字节为内存对齐

方法

方法是作用在特定类型的变量上,因此自定义类型,都可以有方法,而不仅仅是struct。

方法的访问控制也是通过大小写控制。

init函数是通过传入指针实现,这样改变struct字段值,因为是值类型。


type User struct {
 Name string
 Age int
 sex string
}

func (this *User) init(name string, age int, sex string) {
 this.Name = name
 this.Age = age
 this.sex = sex
}

func (this User) GetName() string {
 return this.Name
}

func main() {
 var user User
 user.init("nick", 18, "man")
 //(&user).init("nick", 18, "man")
 name := user.GetName()
 fmt.Println(name)
}

匿名字段

如果有冲突的, 则最外的优先


type User struct {
 Name stirng
 Age int  
}

type Lover struct {
  User
  sex time.Time
  int
  Age int
}

继承 & 多重继承

一个结构体继承多个结构体,访问通过点。继承字段以及方法。

可以起别名,如下面 u1(user1),访问 user.u1.Age。

如果继承的结构体都拥有同一个字段,通过user.name访问就会报错,必须通过user.user1.name来访问。