结构体的概念
在Go语言中不存在Class类的概念,但是可以通过结构体struct来实现。结构体就是一种相同类型,或者不同类型的数据构成的数据的集合。里面的每一个变量叫做成员变量。也就是结构体的字段。每一个字段拥有自己的数据类型和数值。
结构体定义之后也只是确定了这个结构长什么样子,都有哪些字段,并没有真实的数据,所以需要使用结构体时必须先实例化结构体。赋予结构体真实存在的意义。
结构体的实例化
package structDemo
import "fmt"
// 定义结构体
type Person struct {
name string
age int
address string
phone string
}
func main() {
// 实例化后并使用结构体
p := Person{} // 使用简短声明方式,后面加上{}代表这是结构体
// 为结构体赋值
p.name = "张三"
p.age = 18
p.address = "北京"
p.phone = "123456789"
// 打印结构体
fmt.Println(p.name, p.age, p.address, p.phone) // 张三 18 北京 123456789
}
还可以在结构体后面大括号内,直接给结构体成员变量赋值。
// 直接给成员变量赋值
p2 := Person{name: "李四", age: 20, address: "上海", phone: "987654321"}
fmt.Println(p2.name, p2.age, p2.address, p2.phone) // 李四 20 上海 987654321
在Go语言中有一个关键字new可以用来实例化结构体。本质上是分配了一个某种类型的内存空间,所以使用new关键字默认就会返回一个指针。使用new创建结构体,默认就是一个指针类型的结构体。
package main
import "fmt"
type Person struct {
name string
age int
address string
phone string
}
func main() {
p2 := Person{name: "李四", age: 20, address: "上海", phone: "987654321"}
// 1、使用结构体指针
var p *Person
p = &p2
fmt.Println(p) // &{李四 20 上海 987654321}
p.name = "王五"
fmt.Println(p2) // {王五 20 上海 987654321}
// 2、使用new 创建结构体指针
p3 := new(Person)
fmt.Println(p3) // &{ 0 }
p3.name = "赵六"
p3.age = 30
p3.address = "广州"
p3.phone = "123456789"
fmt.Println(p3) // &{赵六 30 广州 123456789}
}
在Go语言中,使用&符号取地址时候,默认就对该类型进行了一次实例化操作。在开发过程中经常会以下面这种使用函数封装写法,来实例化一个结构体。
package main
type Person struct {
name string
age int
address string
}
func main() {
p := newPerson("张三", 18, "北京")
println(p.name, p.age, p.address) // 张三 18 北京
}
// 使用函数来实例化结构体
func newPerson(name string, age int, address string) *Person {
return &Person{
name: name,
age: age,
address: address,
}
}
结构体初始化
结构体内的每一个字段,都有自己相应的数据类型,如果结构体被实例化后,字段的默认值就是该字段类型的零值,int就是0,string就是"",如果是指针类型,默认就是nil。
package main
type Person struct {
name string
age int
address string
}
func main() {
p := Person{name: "张三", address: "北京"}
// 年龄未初始化,默认为零值
println(p.name, p.age, p.address) // 张三 0 北京
}
初始化时可以忽略成员内的字段名,但是必须初始化所有的字段,必须和结构体内字段顺序一致,并且不能和有字段的初始化方法混用。
package main
type Person struct {
name string
age int
address string
}
func main() {
p := Person{"张三", 18, "北京"}
println(p.name, p.age, p.address) // 张三 18 北京
}
匿名结构体
匿名结构体就是没有类型名称,也不需要type关键字可以直接使用。
package main
import "fmt"
func main() {
p := struct {
name string
age int
address string
}{
name: "张三",
age: 18,
address: "北京",
}
fmt.Println(p.name, p.age, p.address) // 张三 18 北京
}
结构体嵌套
结构体可以包含多个字段,每一个字段都需要相应的数据类型,结构体也属于一种数据类型,所以结构体内部也可以包含另一个结构体。
package main
import "fmt"
// Person 结构体
type Person struct {
name string
age int
person2 Person2
}
// 结构体2
type Person2 struct {
name string
age int
}
// 也可以嵌套结构体指针
type Person3 struct {
name string
age int
person2 *Person2
}
func main() {
p := Person{}
p.name = "张三"
p.age = 18
p.person2 = Person2{
name: "李四",
age: 20,
}
fmt.Println(p) // {张三 18 {李四 20}}
// 第二种初始化的方式,定义好结构体之后使用重新赋值的方式:使用(变量.字段名=值)的格式
p2 := Person2{}
p2.name = "王五"
p2.age = 30
pre := Person3{}
pre.name = "赵六"
pre.age = 40
pre.person2 = &p2
fmt.Println(pre) // {赵六 40 0xc00000e0c0}
}
结构体与Json数据的相互转换
Json数据的相互转换
JSON是一种特殊格式的字符串,用来传输和存储数据,在使用api服务开发提供给前端的数据时,更多使用json数据交互。Go语言标准库中提供了json解析的包,使用之前导入包。
import "encoding/json"
结构体转为json字符串
需要注意的是将结构体转换为Json数据时候,定义结构体的字段必须首字母大写。否则无法正常解析。
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
Person2 *Person2
}
type Person2 struct {
Name string
Age int
}
func main() {
p := Person{}
p.Name = "张三"
p.Age = 18
p.Person2 = &Person2{
Name: "李四",
Age: 20,
}
buf, err := json.Marshal(p) // 替换为JSON,返回两个结果
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println("json = ", string(buf)) // json = {"Name":"张三","Age":18,"Person2":{"Name":"李四","Age":20}}
}
可以看出其中json字符中每一个key的首字母也是大写,最后一个没有设置数据的字段的结果为null。那么如何强制将他变为小写的。并且将不需要显示的字段隐藏掉。就需要在结构体上添加标记。
type Person struct {
Name string `json:"name"` // 重新指定json字段为小写输出
Age int `json:"age"`
Address string `json:"address"`
Phone string `json:"phone"`
Name2 string `json:"-"` // 不输出到json
Name3 string `json:"name3,omitempty"` // 如果为空则不输出到json
Name4 string `json:"name4,string"` // 强制转换为字符串输出到json
}
json字符串转为结构体
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"` // 重新指定json字段为小写输出
Age int `json:"age"` // 重新指定json字段为小写输出
}
func main() {
jsonstr := `{"name":"张三","age":18}`
p := Person{}
// 反序列化
err := json.Unmarshal([]byte(jsonstr), &p)
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println("p = ", p) // p = {张三 18}
}