结构实例化
:=自动推导实例化方式
book1:= Books{value1, value2...valuen}
或
book2:= Books{ key1: value1, key2: value2..., keyn: valuen}
例子:
book1:=Books{1,"Go语言入门教程","deer","Go语言"}
或
book2:=Books{id: 2,title: "Go语言进阶教程",author: "deer",subject: "Go语言"}
package main
import "fmt"
type Books struct {
id int
title string
author string
subject string
}
func main() {
//key -> value创建结构体变量
book2 := Books{
id: 2,
title: "Go语言进阶",
author: "yu",
subject: "描述",
}
//简洁创建结构体变量
book3 := Books{3,"Go语言深入","yu","描述"}
fmt.Printf("book2=%v\n",book2)
fmt.Printf("book2.title=%s\n",book2.title)
fmt.Printf("book3=%v\n",book3)
fmt.Printf("book3.title=%s\n",book3.title)
}
/*输出结果*/
book2={2 Go语言进阶 yu 描述}
book2.title=Go语言进阶
book3={3 Go语言深入 yu 描述}
book3.title=Go语言深入
指针类型实例化方式
var struct_pointer *Books
package main
import "fmt"
type Books struct {
id int
title string
author string
subject string
}
func main() {
var book4 *Books
book4 = new(Books)
(*book4).id=4
(*book4).title="Go语言放弃"
//底层book4->(*book4)
book4.author="yu"
book4.subject="描述"
fmt.Println(book4)
}
&{4 Go语言放弃 yu 描述}
二、结构体使用
自定义类型
Go语言允许我们自定义类型,自定义类型有2种方式。
语法
自定义类型是定义了一个全新的数据类型,Go使用type关键字创建一个新的数据类型
type newtype oldtype
实例
package main
import "fmt"
//integer和int都是int类型,integer派生自int,但是在Go语言当中被认为是不同的数据类型。
type integer int
func main() {
var intvariable int
var integervariable integer
/*
integer和int是不同的数据无法相互赋值
cannot use integervariable (type integer) as type int in assignment
*/
intvariable=int(integervariable)//强制类型转换
fmt.Println(intvariable,integervariable)
}
上面例子中我们使用type关键字从int类型中派生了一个新的类型。不同的数据类型无法相互赋值,只能通过强制类型转换。
结构体定义
go语言使用struct定义一个自定义类型,当用户声明一个新的类型,告诉编译器申请多大内存
语法**
在Go语言中 将类型放在后面
type structName struct{
field fieldtype
field fieldtype
field fieldtype
}
实例
type UsersInfo struct {
//字段可以是任何类型,函数接口都可以
name string //可以说成属性,但是比较粗糙
age int
sex string
hobby []string
moreinfo map[string]interface{}
}
结构体实例化
//结构体名首字母小写表示私有,大写表示公有
type UsersInfo struct {
//字段可以是任何类型,函数接口都可以
name string //可以说成属性,但是比较粗糙
age int
sex string
hobby []string
moreinfo map[string]interface{}
}
func main() {
//基于结构体类型,创建一个变量
var boby UsersInfo //boby是UsersInfo类型
boby.name="deer"
boby.age=18
boby.sex="男"
boby.hobby=[]string{"编程","运动"}
boby.moreinfo= map[string]interface{}{
"city":"杭州",
"language":"english",
}
fmt.Printf("boby的name=%s,boby的hobby=%v\n",boby.name,boby.hobby)
}
简短方式初始化结构体变量
//:=简短声明定义一个结构体变量
huge :=UsersInfo{
name: "胡歌",
age: 35,
sex: "男",
hobby: []string{"拍电影","公益"},
moreinfo: map[string]interface{}{
"role":"演员",
},
}
lige :=UsersInfo{"55"}
fmt.Printf("hu=%v",huge)
指针类型结构体实例化
ins := new(T) //new(T)开辟指定类型的变量并赋初值,并返回该变量的内存地址
结构体内存布局
任意类型添加方法
在Go语言中,接收者的类型可以是任何类型,不仅仅是结构体,任何类型都可以拥有方法。 举个例子,我们基于内置的int类型使用type关键字可以定义新的自定义类型,然后为我们的自定义类型添加方法。
package main
import (
"fmt"
)
//使用type 将int定义为自定义的integer类型
type integer int
//为自定义integer类型添加Say方法
func (this integer)Say( ) {
fmt.Println("Hello, 我是一个int。")
}
func main( ) {
var m1 integer
m1= 100
m1.Say()
fmt.Printf("%#v %T\n", m1, m1) //100 main.integer
}
嵌套结构体(继承和多继承)
Go语言虽然没有继承,但是我们可以使用嵌套结构体达到类似继承的效果。
package main
import (
"fmt"
)
//父类
type Human struct {
Name string
Age int
Sex string
}
//学生子类
type Student struct {
StudentId int
Human
}
func main( ) {
student1:=Student{
StudentId: 1,
Human:Human{
Name: "小红",
Age: 15,
Sex: "女",
},
}
fmt.Println(student1.Name)//Go语言语法糖 底层->student1.Human.Name
}
匿名字段
定义结构体时,成员字段可以只有类型,而没有字段名,这样的字段称为匿名字段。
package main
import (
"fmt"
)
//父类
type Human struct {
Name string
Age int
Sex string
}
//学生子类
type Student struct {
StudentId int
string //匿名字段
Human //匿名结构体
//Human (Duplicate field 'Human')
}
func main( ) {
Student1:=Student{
StudentId: 1,
string: "作业",
Human: Human{
Name: "小红",
Age: 15,
Sex: "女",
},
}
fmt.Println(Student1)
{1 作业 {小红 15 女}}
一、Go结构体概念
Go语言支持面向对象编程(OOP)。但是和传统的面向对象编程有区别,并不是纯粹的面向对象编程语言。
Go语言没有其他编程语言中的类(class),但是可以使用结构体(struct)来实现面向对象特性。
提取属性,形成新的数据类型(结构),通过这种数据类型创建多个变量
1. 定义结构体
结构体定义使用type
关键字开头,结构体名,后置结构类型struct
关键字,结构体中有一个或多个成员字段。
语法:
type 结构体名 struct {
field field_type
field field_type
field field_type
}
结构体成员也可以称为属性和“字段”,这些字段有以下特性:
- 字段拥有自己的类型和值;
- 字段名必须唯一;
- 字段的类型基本数据类型,引用类型甚至另一个结构体。
结构体的定义只是一种内存布局的描述,只有当结构体实例化时,才会真正地分配内存
例子:
type Books struct {
id int
title string
author string
subject string
}
2.结构体变量(结构体实例化)
结构体本身也是一种数据类型,可以像基本数据类型一样,用来声明一个结构体类型的变量。
基本声明方式
package main
import "fmt"
type Books struct {
Id int
Title string
Author string
Subject string
}
func main() {
var book1 Books //book1是Books类型的变量
book1.Id=1
book1.Title ="Go语言"
book1.Author="cdeer"
book1.Subject="Go语言进阶"
fmt.Println(book1) //{1 Go语言 cdeer Go语言进阶}
}
编译器推导类型声明方式
package main
import "fmt"
type Books struct {
Id int
Title string
Author string
Subject string
}
func main() {
book2 := Books{1, "Go语言", "cdeer", "Go语言进阶"}
fmt.Println(book2) //{1 Go语言 cdeer Go语言进阶}
}
指针类型声明方式
3.结构体变量内存布局
4.结构体方法
Go语言中的方法和传统编程语言的方法不太一样,方法和类并非组织在一起,传统的oop类和方法放在一个文件,而Go只要在同一个包里就可,可分散在不同文件里。go的理念就是数据和实现分离,引用官方说法:
“Methods are not mixed with the data definition (the structs): they are orthogonal to types; representation(data) and behavior (methods) are independent”
Go语言中的方法(Mehod)是一种作用于特定类型上(方法和指定的数据类型绑定),因此自定义类型都可以有方法,不仅仅是结构体。
5.结构体工厂模式
与传统面向对象编程语言不同,Go语言的结构体没有构造函数,通常使用工厂模式来解决这个问题。
package model
type students struct {
stuid int
name string
sex string
class string
}
//工厂模式
func NewStudent(stuid int,name,sex,class string) *students { ///返回*students类型
return &students{stuid: stuid,name: name,sex: sex,class: class}//结构体实例化并返回地址
}
package main
import (
"fmt"
"gotest1/src/model"
)
type Books struct {
Id int
Title string
Author string
Subject string
}
func main() {
xiaohong:=model.NewStudent(1,"小红","女","1班")
fmt.Println(xiaohong)//&{1 小红 女 1班}
}
三、Go面向对象
Go语言仍然支持面向对象三大特性。Go语言实现方式与传统面向对象编程语言不同。
1.封装
Go语言的封装和传统编程语言不同。Go语言使用首字母大小写方式代表公有私有权限,大写表示包外可访问,小写表示包外不能访问。
2.继承和多继承
与C++/Java等面向对象编程语言不同,Go语言没有显式的继承,而是通过结构体嵌套另一个匿名结构实现继承。
package mypackage
import "fmt"
//父类
type person struct {
Name string
Sex string
Age int
}
//子类
type Student struct {
person //匿名结构实现继承
StudentId int
}
type Teacher struct {
person
TeacherId int
}
//工厂函数
func NewStudent(name,sex string,age,stuid int) *Student {
return &Student{person{Name: name,Sex: sex,Age: age} ,stuid}
}
//父类方法Eat()
func (this *person)Eat() {
fmt.Println(this.Name+"正在吃饭parent")
}
//子类方法 重载父类Eat()
func (this *Student)Eat() {
fmt.Println(this.Name+"正在吃饭child")
}
func main() {
stu:=mypackage.NewStudent("多多","女",15,1)
//子类拥有父类的属性和方法
fmt.Println(stu.Name)//多多
stu.Eat()//多多正在吃饭parent
//子类的属性和重载父类方法
fmt.Println(stu.StudentId)//1
stu.Eat()//多多正在吃饭child
}
3.0多态
在Go语言中使用接口来实现多态特征。