Skip to content

Latest commit

 

History

History
215 lines (169 loc) · 4.33 KB

2.5.md

File metadata and controls

215 lines (169 loc) · 4.33 KB

2.5 结构体(struct)

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
}

注:如从效率和可维护出发,不建议试用此方法。

links