Go的struct是字段的类型集合。
struct 主要应用两个方面:
-
可以将不同类型的数据存放到struct,我们都知道数组只能存放单一的数据类型.
-
由于在GO中没有class的关键字,也就是其它语言经常在面向对象中使用的方面,但GO是通过struct结构与method方法组合来实现的面向对象
示例:
package main
import (
"fmt"
)
type Person struct { //结构也是一种类型
Name string //定义struct的属性
Age int
}
func main() {
a := Person{}
a.Name = "jerry" //对struct的属性进行操作,类型与class的使用方法
a.Age = 19
fmt.Println(a)
}
struct 作为一种类型和其他类型结合用
示例:
package main
import (
"fmt"
)
type Person struct {
//结构也是一种类型
Name string //定义struct的属性
Age int
}
func main() {
m := map[string]Person{}
p := Person{Name: "jerry", Age: 12}
m["ONE"] = p
fmt.Println(m)
}
struct 面向对象示例
package main
import "fmt"
type Person struct {
//结构也是一种类型
Name string //定义struct的属性
Age int
}
func main() {
p := Person{Name: "jerry", Age: 12}
p.list()
}
func (p *Person) list() {
fmt.Println(p.Name)
}
匿名字段
package main
import "fmt"
type YellowPerson struct {
Person //anonymous field(匿名自字段,名字就是Person)
string //anonymous field(匿名自字段,名字就是string)
}
type Person struct {
//结构也是一种类型
Name string //定义struct的属性
Age int
}
func main() {
p := YellowPerson{Person: Person{Name: "jerry", Age: 12}, string: "jerry"}
fmt.Println(p.Person)
fmt.Println(p.Name)
fmt.Println(p.Age)
fmt.Println(p.string)
}
YellowPerson直接包含依赖结构,可以直接使用Person中的字段,sting 也是匿名字段,字段名字是string,不过不推荐这么使用。同时需要注意
type YellowPerson struct {
Person //anonymous field(匿名自字段,名字就是Person)
}
和
type YellowPerson struct {
Person Person
}
两者是不同的
package main
import "fmt"
type YellowPerson struct {
Person Person
string //anonymous field(匿名自字段,名字就是string)
}
type Person struct {
//结构也是一种类型
Name string //定义struct的属性
Age int
}
func main() {
p := YellowPerson{Person: Person{Name: "jerry", Age: 12}, string: "jerry"}
fmt.Println(p.Name)
fmt.Println(p.Age)
}
这个会报
p.Name undefined (type YellowPerson has no field or method Name),
p.Age undefined (type YellowPerson has no field or method Age)
错误,应为YellowPerson下没有Name 和Age这连个字段的。
匿名结构体
// 在函数外部定义匿名结构体并赋值给 config
var config struct {
APIKey string
OAuthConfig oauth.Config
}
// 定义并初始化并赋值给 data
data := struct {
Title string
Users []*User
}{
title,
users
}
结构体赋值
//将结构体source复制给dst,只复制相同名称和相同类型的
//CopyStruct(a,b) a可以传值,引用,b只能引用,且
func CopyStruct(src ,dst interface{}) interface{} {
st := reflect.TypeOf(src)
sv := reflect.ValueOf(src)
dt := reflect.TypeOf(dst)
dv := reflect.ValueOf(dst)
if st.Kind()==reflect.Ptr {//处理指针
st=st.Elem()
sv=sv.Elem()
}
if dt.Kind()==reflect.Ptr { //处理指针
dt=dt.Elem()
}
if st.Kind()!=reflect.Struct||dt.Kind()!=reflect.Struct {//如果不是struct类型,直接返回dst
return dst
}
dv = reflect.ValueOf(dv.Interface())
// 遍历TypeOf 类型
for i := 0; i < dt.NumField(); i++ { //通过索引来取得它的所有字段,这里通过t.NumField来获取它多拥有的字段数量,同时来决定循环的次数
f := dt.Field(i) //通过这个i作为它的索引,从0开始来取得它的字段
dVal := dv.Elem().Field(i)
sVal:=sv.FieldByName(f.Name)
//fmt.Println(dVal.CanSet())
//src数据有效,且dst字段能赋值,类型一致
if sVal.IsValid() && dVal.CanSet() && f.Type.Kind()==sVal.Type().Kind() {
dVal.Set(sVal)
}
}
return dst
}
注:如从效率和可维护出发,不建议试用此方法。