一个命名为S的结构体类型将不能再包含S类型的成员:因为一个聚合的值不能包含它自身(但不同类型的聚合值可以相互嵌套!!!)。(该限制同样适应于数组。)但是S类型的结构体可以包含*S指针类型的成员,这可以让我们创建递归的数据结构,比如链表和树结构等 这是因为构体成员Tag所导致的。一个构体成员Tag是和在编译阶段关联到该成员的元信息字符串:结构体的成员Tag可以是任意的字符串面值,但是通常是一系列用空格分隔的key:"value"键值对序列;因为值中含义双引号字符,因此成员Tag一般用原生字符串面值的形式书写。json开头键名对应的值用于控制encoding/json包的编码和解码的行为,并且encoding/…下面其它的包也遵循这个约定。成员Tag中json对应值的第一部分用于指定JSON对象的名字,比如将Go语言中的TotalCount成员对应到JSON中的total_count对象。Color成员的Tag还带了一个额外的omitempty选项,表示当Go语言结构体成员为空或零值时不生成JSON对象(这里false为零值)。果然,Casablanca是一个黑白电影,并没有输出Color成员。 一个结构体中最多只能含有1个同类型的匿名成员(只有类型声明,没有名字的成员),因为实际上该匿名成员会被隐含的命名为该类型的名字,且如果匿名字段如果是一个struct,这个struct拥有的全部字段都被隐式引入了当前的struct(相当于当前字段自动拥有了该匿名struct的所有成员)。 如果当前struct(假设是Student)和其成员struct(Person)中都有同一个字段,那么Go会优先访问当前层的字段。例如二者都有tel字段,那么s.tel将会访问的是Student中的数据。
//其中Year名字的成员在编码后变成了released,还有Color成员编码后变成了小写字母开头的color,//且如果Color的值为false或者其他默认零值得话,被omitempty修饰的字段不会被编码Year int `json:"released"`Color bool `json:"color,omitempty"
package demo/*
@author:David Ma
@content: struct结构体相关
@Date:2020-11-30
*/type Movie struct {Title stringYear int `json:"released"`Color bool `json:"color,omitempty"`Actors []string
}type Address struct {country, city, street string
}type User struct {phone stringusername stringpassword string// 测试匿名成员和非匿名成员的区别address1 Address//在一个struct中最多只允许同时有1个同类型的匿名成员,因为匿名成员隐含的以其类型本身为名Address
}func SetUserName(user *User, name string) bool {if user == nil {return false}user.username = namereturn true
}
func SetPhone(user *User, phoneNum string) bool {if user == nil {return false}user.phone = phoneNumreturn true
}
func SetPassword(user *User, password string) bool {if user == nil {return false}user.password = passwordreturn true
}
func SetAddress(user *User, country, city, street string) bool {if user == nil {return false}user.address1.country = countryuser.address1.city = cityuser.address1.street = streetuser.country = countryuser.city = cityuser.street = streetreturn true
}func GetPhone(user *User) (phone string) {return user.phone
}func GetUserName(user *User) (name string) {return user.username
}func GetPassWord(user *User) (pwd string) {return user.password
}func GetAddress(user *User) (address1, address2 string) {//case1:通过匿名成员的特性来直接获取被嵌套的成员的属性//虽然user中的成员均不是导出的(私有的),但是因为此时同属于用一个包所以非导出成员也可以被访问到add := user.country + user.city + "市" + user.street + "街道"//case2:传统方式获取被嵌套的成员的属性add2 := user.Address.country + user.Address.city + "市" + user.Address.street + "街道"return add, add2
}
package test/*
@Author:David Ma
@Content:struct结构体相关操作
@Date:2020-12-01 15:03
*/
import ("../demo""encoding/json""fmt""log""testing"
)func TestMyStruct(t *testing.T) {// case1:使用 new()函数t.Run("如何定义并初始化一个struct之使用new()函数来初始化一个struct", func(t *testing.T) {user := new(demo.User)demo.SetPhone(user, "12345678901")demo.SetUserName(user, "Bob")demo.SetPassword(user, "11111")demo.SetAddress(user, "中国", "苏州", "平江")add1, add2 := demo.GetAddress(user)fmt.Printf("name = '%s' phone = '%s' password = '%s' address1 = '%s' address2 = '%s' \n",demo.GetUserName(user), demo.GetPhone(user), demo.GetPassWord(user), add1, add2)//case2:还可以使用字面常量的方式来定义,type Animal struct {Age int}type Person struct {AnimalName string}type Student struct {PersonClassName string}})//case2:还可以使用字面常量的方式来定义,t.Run("如何定义并初始化一个struct之使用字面常量的方式来初始化一个struct", func(t *testing.T) {type Animal struct {Age int}type Person struct {AnimalName string}type Student struct {PersonClassName string}s := Student{Person{Animal: Animal{ //注意这里匿名成名如何使用字面常量的方式来初始化Age: 18,},Name: "Bob",},"Class01",}fmt.Printf("%+v \n", s)})// 只有导出的结构体成员才会被编码,这也就是我们为什么选择用大写字母开头的成员名称t.Run("定义一个Movie类型(其成员均可导出,方便编解码操作)的切片,并展示将其编码为json以及反编码", func(t *testing.T) {data := []demo.Movie{{Title: "Casablanca", Year: 1942, Color: false,Actors: []string{"Humphrey Bogart", "Ingrid Bergman"}},{Title: "Cool Hand Luke", Year: 1967, Color: true,Actors: []string{"Paul Newman"}},{Title: "I Can Fly", Year: 1968, Color: true,Actors: []string{"Steve McQueen", "Jacqueline BBB"}},}//marshalmsg, err := json.MarshalIndent(data, "", " ")if err != nil {log.Fatalf("Json marshal faliled '%s'", err)}fmt.Printf("JSON串为:%s\n", msg)//unmarshal(下面只解码Title和Actors信息)var receivedTitles []struct {Title stringActors []string}//json.Unmarshal(@args1:json串,@argus2:一个用于接收解码后的数据的结构),这里特别注意arus2必须为指针类型,因为要对其做修改,而go又是值传递err2 := json.Unmarshal(msg, &receivedTitles)if err2 != nil {log.Fatalf("Json unmarshal faliled '%s'\n", err2)}fmt.Printf("the Title of Movies is:'%s' \n", receivedTitles)})
}