在之前学过的数据类型中,数组与切片,只能存储同一类型的变量。若要存储多个类型的变量,就需要用到结构体,它是将多个任意类型的变量组合在一起的聚合数据类型。
每个变量都成为该结构体的成员变量。
可以理解为 Go语言 的结构体struct和其他语言的class有相等的地位,但是Go语言放弃大量面向对象的特性,所有的Go语言类型除了指针类型外,都可以有自己的方法,提高了可扩展性。在 Go 语言中没有没有 class 类的概念,只有 struct 结构体的概念,因此也没有继承。
结构体的声明:
type 结构体名 struct {
属性名 属性类型
属性名 属性类型
}
eg:
type Student struct{
name string
age int
gender string
deskmate *Student
roomate *Student
}
注意事项
//正确写法
zhangsan := Student{
name:"小明",
age:18,
gender: "male",
}
/* 或者
zhangsan := Student{
name:"小明",
age:18,
gender: "male"}
*/
/* 错误写法
zhangsan := Student{
name:"小明",
age:18,
gender: "male"
}
*/
/* 指定字段名的初始化正确形式
zhangsan := Student{
name:"小明",
age:18,
gender: "male",
} */
//未指定字段名的初始化正确形式
zhangsan := Student{
"小明",
18,
"male",
nil,
nil,
}
但是只有通过指定字段名,才可进行部分赋值,不指定字段名会报错。
zhangsan := Student{
"小明",
18,
"male",
}
Golang中,我们无法在结构体内定义方法,需要使用组合函数的方式来定义结构体方法。
eg:
type Student struct{
name string
age int
gender string
deskmate *Student
roomate *Student
}
//定义和结构体有关的方法
func (stu Student) StudentPrint(){
fmt.Printf("名字:%s\n",stu.name)
fmt.Printf("年龄:%d\n",stu.age)
fmt.Printf("性别:%s\n",stu.gender)
}
func main() {
zhangsan := Student{
"小明",
18,
"male",
nil,
nil,
}
/*名字:小明
年龄:18
性别:male */
zhangsan.StudentPrint()
}
那我们如何进行选择呢?以下几种情况,应当直接使用指针做为方法的接收者。
你需要在方法内部改变结构体内容的时候
出于性能的问题,当结构体过大的时候 (因为指针大小相对于传值调用方式要求将参数的一份拷贝传递给函数花费的开销较小。)
有些情况下,以值或指针做为接收者都可以,但是考虑到代码一致性,建议都使用指针做为接收者。
不管你使用哪种方法定义方法,指针实例对象、值实例对象都可以直接调用,而没有什么约束。这一点Go语言做得非常好。
当想在方法内改变实例的属性的时候,必须使用指针作为方法的接收者
func (stu *Student) changeage(){
stu.age += 1
}
由于Golang中无继承的实现,所以结构体的嵌套可以代替实现继承。
使用方法:将嵌套的结构体作为一个匿名字段
type Student struct{
name string
age int
gender string
deskmate *Student
roomate *Student
//匿名字段
school
}
type school struct{
schoolarea string
schoolmj string
}
func main() {
new_un := school{
"东南大学",
"10000",
}
zhangsan := Student{
"小明",
18,
"male",
nil,
nil,
new_un,
}
fmt.Println(zhangsan.school)
}
在 Go 语言中,函数名的首字母大小写非常重要,它被来实现控制对方法的访问权限。
当方法的首字母为大写
时,这个方法对于所有包都是Public,其他包可以随意调用
当方法的首字母为小写
时,这个方法是Private,其他包是无法访问的。
func main() {
//1.直接赋值实例化
zhangsan := Student{
"小明",
18,
"male",
nil,
nil,
}
//2.使用new实例化
ls := new(Student)
ls.name = "lisi"
//3.使用var实例化
var ww Student;
ww.name = "王五"
fmt.Println(zhangsan.name)
fmt.Println(ls.name)
fmt.Println(ww.name)
/* 小明
lisi
王五 */
}
Golang语言的结构体没有构造函数,我们可以自己实现。 例如,下方的代码就实现了一个person的构造函数。 因为struct是值类型,如果结构体比较复杂的话,值拷贝性能开销会比较大,所以该构造函数返回的是结构体指针类型。
func gz(name string,age int, gender string) *Student{
return &Student{
name: name,
age: age,
gender: gender,
}
}
func main() {
zhangsan := gz("zahngsan",19,"男")
}