石家庄网站建设浩森宇特,网站建设服务商24小时接单,平面设计的网站有哪些,服装网站建设需求分析Go语言结构体#xff0c;这一篇就够了1.结构体的概念2.结构体的定义3.结构体的实例化4.结构体初始化5.构造函数6.方法和接收者方法接收者7.嵌套结构体8.结构体的“继承”9.结构体与JSON序列化10.结构体标签#xff08;Tag#xff09;Go语言中没有“类”的概念#xff0c;也…
Go语言结构体这一篇就够了1.结构体的概念2.结构体的定义3.结构体的实例化4.结构体初始化5.构造函数6.方法和接收者方法接收者7.嵌套结构体8.结构体的“继承”9.结构体与JSON序列化10.结构体标签TagGo语言中没有“类”的概念也不支持“类”的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。
1.结构体的概念
Go语言中的基础数据类型可以表示一些事物的基本属性但是当我们想表达一个事物的全部或部分属性时这时候再用单一的基本数据类型明显就无法满足需求了Go语言提供了一种自定义数据类型可以封装多个基本数据类型这种数据类型叫结构体英文名称struct。 也就是我们可以通过struct来定义自己的类型了。 Go语言中通过struct来实现面向对象 2.结构体的定义
使用type和struct关键字来定义结构体
举个例子我们定义一个Person人结构体代码如下
type person struct {name stringcity stringage int8
}同样类型的字段也可以写在一行
type person struct {name, city stringage int8
}3.结构体的实例化
只有当结构体实例化时才会真正地分配内存。也就是必须实例化后才能使用结构体的字段。
package mainimport fmttype person struct {name stringcity stringage int8
}func main() {var p personp.name 大河p.age 18p.city 长春fmt.Println(p) // {大河 长春 18}fmt.Println(p.name) // 大河
}在定义一些临时数据结构等场景下还可以使用匿名结构体
package mainimport (fmt
)func main() {var user struct{Name string; Age int}user.Name 小王子user.Age 18fmt.Printf(%#v\n, user)
}4.结构体初始化
使用键值对对结构体进行初始化时键对应结构体的字段值对应该字段的初始值
package mainimport fmttype person struct {name stringcity stringage int8
}func main() {p : person{name: 大河,city: 北京,}fmt.Println(p) // {大河 北京 0}
}初始化结构体的时候可以简写也就是初始化的时候不写键直接写值
package mainimport fmttype person struct {name stringcity stringage int8
}func main() {p : person{张三,北京,18,}fmt.Println(p) // {张三 北京 18}
}使用这种格式初始化时需要注意
必须初始化结构体的所有字段。初始值的填充顺序必须与字段在结构体中的声明顺序一致。该方式不能和键值初始化方式混用。 5.构造函数
Go语言的结构体没有构造函数我们可以自己实现。 例如下方的代码就实现了一个person的构造函数。 因为struct是值类型如果结构体比较复杂的话值拷贝性能开销会比较大所以该构造函数返回的是结构体指针类型。
package mainimport fmttype person struct {name stringcity stringage int8
}/*
构造函数
*/
func newPerson(name, city string, age int8) *person {return person{name: name,city: city,age: age,}
}func main() {p : newPerson(大河, 北京, 22)fmt.Println(p) // {大河 北京 22}
}6.方法和接收者
方法
Go语言中的方法Method是一种作用于特定类型变量的函数。这种特定类型变量叫做接收者Receiver。接收者的概念就类似于其他语言中的this或者 self。
方法的定义格式如下
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {函数体
}接收者变量接收者中的参数变量名在命名时官方建议使用接收者类型名称首字母的小写而不是self、this之类的命名。例如Person类型的接收者变量应该命名为pConnector类型的接收者变量应该命名为c等。接收者类型接收者类型和参数类似可以是指针类型和非指针类型。方法名、参数列表、返回参数具体格式与函数定义相同。
方法使用实例
package mainimport fmttype Person struct {name stringcity stringage int8
}/*
构造函数
*/
func newPerson(name, city string, age int8) *Person {return Person{name: name,city: city,age: age,}
}func (p Person) say() {fmt.Println(我要说话了)
}func main() {p : newPerson(大河, 北京, 22)p.say()
}方法与函数的区别是函数不属于任何类型方法属于特定的类型 接收者
指针类型的接收者
指针类型的接收者由一个结构体的指针组成由于指针的特性调用方法时修改接收者指针的任意成员变量在方法结束后修改都是有效的。这种方式就十分接近于其他语言中面向对象中的this或者self。 例如我们为Person添加一个SetAge方法来修改实例变量的年龄。
package mainimport fmttype Person struct {name stringcity stringage int8
}/*
构造函数
*/
func newPerson(name, city string, age int8) *Person {return Person{name: name,city: city,age: age,}
}func (p *Person) setAge(newAge int8) {p.age newAge
}func main() {p : newPerson(大河, 北京, 22)p.setAge(33)fmt.Println(p) // {大河 北京 33}
}值类型的接收者
当方法作用于值类型接收者时Go语言会在代码运行时将接收者的值复制一份。在值类型接收者的方法中可以获取接收者的成员值但修改操作只是针对副本无法修改接收者变量本身。
package mainimport fmttype Person struct {name stringcity stringage int8
}/*
构造函数
*/
func newPerson(name, city string, age int8) *Person {return Person{name: name,city: city,age: age,}
}func (p Person) setAge(newAge int8) {p.age newAge
}func main() {p : newPerson(大河, 北京, 22)p.setAge(33)fmt.Println(p) // {大河 北京 22}
}什么时候应该使用指针类型接收者
需要修改接收者中的值接收者是拷贝代价比较大的大对象保证一致性如果有某个方法使用了指针接收者那么其他的方法也应该使用指针接收者 7.嵌套结构体
一个结构体中可以嵌套包含另一个结构体或结构体指针就像下面的示例代码那样。
package mainimport fmttype Address struct {Province stringCity string
}// User 用户结构体
type User struct {Name stringGender stringAddress Address
}func main() {user : User{Name: 小王子,Gender: 男,Address: Address{Province: 山东,City: 威海,},}fmt.Println(user) // {小王子 男 {山东 威海}}
}嵌套结构体内部可能存在相同的字段名。在这种情况下为了避免歧义需要通过指定具体的内嵌结构体字段名
package mainimport fmt// Address 地址结构体
type Address struct {Province stringCity stringCreateTime string
}// Email 邮箱结构体
type Email struct {Account stringCreateTime string
}// User 用户结构体
type User struct {Name stringGender stringAddressEmail
}func main() {var user Useruser.Name daheuser.Gender 1user.Address.CreateTime 2022user.Email.CreateTime 2023fmt.Println(user) // {dahe 1 { 2022} { 2023}}
}结构体中字段大写开头表示可公开访问小写表示私有仅在定义当前结构体的包中可访问 8.结构体的“继承”
Go语言中使用结构体也可以实现其他编程语言中面向对象的继承
例如
package mainimport fmttype Animal struct {name string
}func (a *Animal) move() {fmt.Printf(%s会动\n, a.name)
}type Dog struct {Feet int8*Animal // 通过嵌套匿名结构体实现继承
}func (d *Dog) wang() {fmt.Printf(%s会汪汪汪~\n, d.name)
}func main() {d : Dog{Feet: 4,Animal: Animal{ // 注意嵌套的是结构体指针name: 乐乐,},}d.move() // 乐乐会动d.wang() // 乐乐会汪汪汪~
}9.结构体与JSON序列化
JSON是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON键值对是用来保存JS对象的一种方式键/值对组合中的键名写在前面并用双引号包裹使用冒号:分隔然后紧接着值多个键值之间使用英文,分隔
序列化和反序列化程序实例
package mainimport (encoding/jsonfmt
)// Student 学生
type Student struct {ID intGender stringName string
}// Class 班级
type Class struct {Title stringStudents []*Student
}func main() {c : Class{Title: 101,Students: make([]*Student, 0, 200),}for i : 0; i 10; i {stu : Student{Name: fmt.Sprintf(stu%02d, i),Gender: 男,ID: i,}c.Students append(c.Students, stu)}// JSON序列化结构体--JSON格式的字符串data, err : json.Marshal(c)if err ! nil {fmt.Println(json marshal failed)return}fmt.Printf(json:%s\n, data)// JSON反序列化JSON格式的字符串--结构体str : {Title:101,Students:[{ID:0,Gender:男,Name:stu00},{ID:1,Gender:男,Name:stu01},{ID:2,Gender:男,Name:stu02},{ID:3,Gender:男,Name:stu03},{ID:4,Gender:男,Name:stu04},{ID:5,Gender:男,Name:stu05},{ID:6,Gender:男,Name:stu06},{ID:7,Gender:男,Name:stu07},{ID:8,Gender:男,Name:stu08},{ID:9,Gender:男,Name:stu09}]}c1 : Class{}err json.Unmarshal([]byte(str), c1)if err ! nil {fmt.Println(json unmarshal failed!)return}fmt.Printf(%#v\n, c1)
}10.结构体标签Tag
Tag是结构体的元信息可以在运行的时候通过反射的机制读取出来。 Tag在结构体字段的后方定义由一对反引号包裹起来具体的格式如下
key1:value1 key2:value2为结构体编写Tag时必须严格遵守键值对的规则。结构体标签的解析代码的容错能力很差一旦格式写错编译和运行时都不会提示任何错误通过反射也无法正确取值。例如不要在key和value之间添加空格 package mainimport (encoding/jsonfmt
)// Student 学生
type Student struct {ID int json:uid // 通过指定tag实现json序列化该字段时的keyGender string // json序列化是默认使用字段名作为keyname string // 私有不能被json包访问
}func main() {s : Student{ID: 1,Gender: 男,name: 沙河娜扎,}data, err : json.Marshal(s)if err ! nil {fmt.Println(json marshal failed!)return}fmt.Printf(json str:%s\n, data)// json str:{uid:1,Gender:男}
}版权声明本文教程基于李文周的Go语言博客 - 结构体篇