(转)Go-18 Golang结构体struct详解
原文:https://www.cnblogs.com/ludundun/p/16998752.html
package main import "fmt" // Golang中的结构体详解 type newInt int // 自定义类型 type myInt = int // 类型别名 type zsInt int type person struct { name string city string age int8 } type PerSon struct { name string age int } // 匿名字段结构体 type PersonMan struct { string int } // 定义Address地址结构体 type Address struct { Province string City string } // 定义User用户结构体 type User struct { Name string Gender string Address Address // 在这里就是结构体中嵌套了另一个结构体 } // UserT 用户结构体中嵌套匿名结构体 type UserT struct { Name string Gender string Address // 匿名结构体 } // Animal 动物 type Animal struct { name string } // Dog 狗 type Dog struct { Age int8 *Animal // 通过嵌套匿名结构体实现继承 } func (a *Animal) run() { fmt.Printf("%s 会运动! \n", a.name) } func (d *Dog) wang() { fmt.Printf("%s 会汪汪汪~ \n", d.name) } // 值类型接收者 func (p PerSon) printInfo() { fmt.Printf("姓名:%v 年龄:%v \n", p.name, p.age) // 姓名:小王子 年龄:25 } // 指针类型接收者 func (p *PerSon) setInfo(name string, age int) { p.name = name p.age = age } func (m zsInt) SayHello() { fmt.Println("Hello, 我是一个int...") } func main() { /* 1.关于Golang结构体 Golang中没有"类"的概念,Golang中的结构体和其他语言中的类有点相似。和其他面向对象语言中的类相比, Golang中的结构体具有更高的扩展性和灵活性。 Golang结构体因何而出: Golang中的基础数据类型可以表示一些事物的基本属性,但是当我们想表达一个事务的全部或部分属性时,这时候再用单一的基本数据类型就无法满足 要求了,Golang中提供了一种自定义数据类型,可以封装多个基本数据类型,这种数据类型叫结构体,英文名struct。也就是我们可以通过struct 来定义我们自己的类型了。 2.Golang type 关键字自定义类型和类型别名 Golang中通过type关键字定义一个结构体。 2.1 type自定义类型 在Go语言中有一些基本的数据类型,如string、整型、浮点型、布尔等数据类型,Go语言中可以使用type关键字来定义自定义类型。 type myint int 这个表示将myint定义为int类型,通过type关键字的定义,myint就是一种新的类型,它具有int的特性。 2.2 定义类型别名 Golang1.9版本以后添加的新功能。类型别名规定:TypeAlias只是Type的别名,本质上TypeAlias与Type是同一个类型。就像 一个小孩小时候有大名、小明、英文名,但这些名字都指的是他本人。 type TypeAlias = Type ,我们之前见过的rune和byte就是类型别名,他们的底层定义如下: type byte = uint8 type rune = int32 2.3 自定义类型和类型别名的区别 类型别名与自定义类型表面上看只有一个等号的差异,我们通过下面的这段代码来理解他们之间的区别。 package main import "fmt" // 自定义类型 type newInt int // 类型别名 type myInt = int func main(){ var a newInt var b myInt fmt.Printf("自定义类型的结果是 type of a:%T \n", a) // 自定义类型的结果是 type of a:main.newInt fmt.Printf("类型别名的结果是 type of b:%T \n", b) // 类型别名的结果是 type of b:int } 结果显示a的类型是main.newInt,表示main包下定义的newInt类型。b的类型是int类型。 3.结构体定义初始化的几种方法 3.1 结构体的定义 使用type和struct关键字来定义结构体,具体代码格式如下: type 类型名 struct { 字段名 字段类型 字段名 字段类型 字段名 字段类型 ..... ...... } 其中: 1.类型名:表示自定义结构体的名称,在同一个包内不能重复。 2.字段名:表示结构体字段名。结构体中的字段名必须唯一。 3.字段类型:表示结构体字段的具体类型。 举例,我们定义一个person人类的结构体,代码如下: type person struct { name string city string age int8 } 同样类型的字段也可以写在一行: type person struct { name, city string age int8 } 注意:结构体首字母可以大写,也可以小写,大写表示这个结构体是公有的,在其他的包里面可以使用。小写表示这个结构体是私有的,只有这个包里面才能使用。 3.2 结构体实例化(第一种方法) 只有当结构体实例化时,才会真正的分配内存。也就是必须实例化后才能使用结构体的字段。结构体本身也是一种类型,我们可以 像声明内置类型一样使用var关键字声明结构体类型。 var 结构体实例 结构体类型,例如借用上面的结构体进行声明:var p1 person package main import "fmt" type person struct { name string city string age int8 } func main() { var p1 person p1.name = "张三" p1.city = "北京" p1.age = 18 fmt.Printf("p1=%v \n", p1) // p1={张三 北京 18} fmt.Printf("p1=%#v \n", p1) // p1=main.person{name:"张三",city:"北京",age:18} } 3.3 结构体实例化(第二种方法) 我们可以使用new关键字对结构体进行实例化,得到的是结构体的地址。格式如下: package main import "fmt" type person struct { name string city string age int } func main() { var p2 = new(person) p2.name = "张三" p2.city = "北京" p2.age = 20 fmt.Printf("%T \n", p2) // *main.person fmt.Printf("p2=%#v \n", p2) //p2=&main.person{name:"张三",city:"北京",age:20} } 从打印的结果中我们可以看出p2是一个结构体指针。注意:在Golang中支持对结构体指针直接使用,来访问结构体的成员。 p2.name="张三" 其实在底层是(*p2).name="张三" 3.4 结构体实例化(第三种方法) 使用&对结构体进行取地址操作。 package main import "fmt" type person struct { name string city string age int } func main() { p3 := &person{} fmt.Printf("%T \n", p3) // *main.person fmt.Printf("p3=%#v \n", p3) // p3=&main.person{name:"",city:"",age:0} p3.name = "张三" p3.city = "北京" p3.age = 20 // (*p3).age = 50 // 这样也是可以的 fmt.Printf("p3=%#v \n", p3) // p3=&main.person{name:"张三",city:"北京",age:20} } 3.5 结构体实例化(第四种方法)键值对初始化 package main import "fmt" type person struct { name string city