结构体是由一系列相同或不相同类型数据组成的数据集合。 结构体的成员(字段)的特性:
- 字段名必须唯一
- 字段有自己的类型和值
- 字段的类型也可以是结构体,甚至是字段所在结构体的类型
结构体定义格式如下:
type 类型名 struct{ 字段1 类型1 字段2 类型2 //... } 复制代码
结构体初始化
type Mystruct struct { Name string Address string } //方法一 var person Mystruct person.Name = "test" person.Address = "beijing" //方法二 person1 := Mystruct{"test","beijing"} //方法三 //(*person2).Name 等同于 person2.Name var person2 = new(Mystruct) person2.Name = "test" person2.Address = "beijing" //方法四 //(*Mystruct).Name 等同于 person3.Name var person3 = &Mystruct{} (*person3).Name = "test" (*person3).Address = "beijing" 复制代码
结构体排序
可以通过 sort.Slice() 函数进行结构体的排序
示例:
package main import ( "fmt" "sort" ) type Mystruct struct { Name string Address string } func main() { persons := []Mystruct{ {"test2", "aa"}, {"test1", "bb"}, {"test3", "cc"}, } fmt.Println(persons) sort.Slice(persons, func(i, j int) bool { return persons[i].Name < persons[j].Name || persons[i].Address < persons[j].Address }) fmt.Println(persons) } 复制代码
运行结果:
[{test2 aa} {test1 bb} {test3 cc}] [{test1 bb} {test2 aa} {test3 cc}] 复制代码
结构体继承
Go 语言中没有 extends 关键字,不能像其他语言那样去实现类的继承。在Go中,使用的是 interface 实现的功能组合,以组合的形式来实现继承。
如下我们创建一个父类结构体 Father,再用子类 Child 继承父类,实现在 Child 中调用父类的方法,示例:
package main import ( "fmt" ) type Father struct { Name string } func (f Father) Say(){ fmt.Println("father...") } type Child struct { Father } func main() { child := Child{} child.Father.Say() // father... //直接使用下面的写法也可以,Go语言做了相关的优化,直接调用方法也可以找到父类中的方法 child.Say() // father... } 复制代码
改写父类的方法
package main import ( "fmt" ) type Father struct { Name string } func (f Father) Say(){ fmt.Println("father...") } type Child struct { Father } func (c Child)Say(){ fmt.Println("child start...") c.Father.Say() fmt.Println("child end...") } func main() { child := Child{} child.Father.Say() //被 child 改写后,下面调用的就是自身的方法 child.Say() } 复制代码
运行结果:
father... child start... father... child end... 复制代码
匿名结构体
顾名思义,匿名结构体就是没有名字的结构体,示例如下:
package main import "fmt" func main() { book := struct { // 无需事先声明 title string id int }{ title: "Go语言", // 定义完成之后,即可进行初始化 id: 123456, } fmt.Println("title ", book.title) fmt.Println("id", book.id) } // 打印结果 // title Go语言 // id 123456 复制代码
结构体字段标签
结构体字段标签(tag)是结构体额外的信息,用于对字段进行说明。在 json 序列化及对象关系映射时,会用到此标签。标签信息都是静态的,无需实例化结构体,可以通过反射来获得。
标签在结构体后面,由一个或多个键值组成,键值间使用空格分隔:
key1:"value1" key2:"value2"
使用反射获取结构体标签信息:
package main import ( "fmt" "reflect" ) type Test struct { Name string `json:"name"` } func main() { var test = Test{} //反射获取标签信息 typeTest := reflect.TypeOf(test) testFieldName, ok := typeTest.FieldByName("Name") if ok { fmt.Println(testFieldName.Tag.Get("json")) } } // 打印结果 // name 复制代码
多态
- 继承主要在于: 解决代码的复用性和可维护性;
- 接口主要在于: 接口设计好各种规范方法,让其它自定义类型实现这些方法;
- 接口比继承更加灵活,继承是满足
is-a
的关系,接口是满足like-a
的关系;
Go 中的多态是通过接口实现的:
package main import "fmt" type People interface { Say() } type Student struct {} type Teacher struct {} func (p *Student) Say(){ fmt.Println("Student...") } func (c *Teacher) Say(){ fmt.Println("Teacher...") } func hello(p People) { p.Say() } func main(){ var student = new(Student) var teacher = new(Teacher) hello(student) hello(teacher) } 复制代码
打印结果:
Student... Teacher...