package main

import (
   "fmt"
   "reflect"
)

/*

   type :关键字之定义中新类型
   struct : 结构体
   结构体并非创建面向对象代码的方式,而是一种数据结构创造方式,旨在满足数据建模需求
   允许:结构体套结构体,满足更复杂的数据结构
   比较: 结构体比较 运算符 == ,是否相等 !=, 比较结构体首先比较他们类型和值是否相同,对结构体中的每个字段值和类型都会比较。
   查询结构体是否相同,reflect.TypeOf()

    理解公用、私有值,结构体中首字母大写可以导出,要导出结构体及其字段,结构体及其字段的名称都必须是以大写字母大头!!!
   重点:这里的公有和私有,其实就是面向对象中变量继承时的 公有属性和私有属性的意思。建议,目前所有结构体都首字母都大写。 



  1.使用new 来实例化结构体; m : = new(Movie)  //Movie 是一个结构体

  2.区分指针引用和值引用,使用结构体是,明确指针引用和值引用的区别很重要。
    值引用赋值  比如 a:=b{name:"liu"} ,这样修改a.name="ls",不会影响到b.name,值引用是复制结构体,开辟一块新的内存空间
          a只是b的一个副本,而不是指向b的引用。
指针引用赋值  比如 a:=&b{name:"liu"} ,这样修改a.name="ls",会影响到b.name,指针引用是指向结构体内存地址的引用,同一块内存空间
    总结。值引用不会互相影响两个变量值的独立,指针引用则会互相影响,因为他们都指向同一块内存地址
总结:值引用只是复制的一个副本,不是指向内存地址的引用;
        指针引用,指针是指向内存地址的引用,因此使用它操作的不是结构体的副本而是本身。
        指针引用的时候,比如 b:=&a,此时b是指针,因此必须使用*b对其进行引用(打印值)
如果需要修改原始结构体实例,必须使用指针。
      如果操作一个结构体,但不想修改原始结构体实例,就使用值。
       (指针是go语言中的一种类型,指向变量所在的内存单元,指向内存地址的引用,获得指针的方法,在变量名前加&)
*/
type Students struct {
   name string
   age  int
   desc string
   address Address
}

type Address struct {
   Number int
   City string
   Street string
}

type Alarm struct {
   Time string
   Sound string
}

func main() {
   a:=Alarm{
      Time:  "8:00",
      Sound: "shanghai",
   }
   //b:=a  //这种b的值改变不了a
   b:=&a   //这种b的值能改变a的
   b.Sound = "beijing"
   fmt.Printf("%+v\n",b)    //没有改变a的值,内存地址不相同
   fmt.Printf("%+v\n",a)
   fmt.Printf("%p\n",&a)
   fmt.Printf("%p\n",&b)
   //ttest();
   //NewAlarm("07:00")

}
//嵌套结构体,在声明结构体的时候,嵌套
func ttest(){
   var a Students
   a.name = "liu"
   a.age = 11
   a.desc = "上海复旦"
   a.address.City="上海"
   a.address.Number=0712
   a.address.Street="重装路"

   kk:=new(Students)
   kk.name = "zao"
   kk.age =21
   cc:=Students{
      name:"li",
      age:12,
      desc:"我是小美丽",
   }
   fmt.Println(a)
   fmt.Println(kk)
   fmt.Println(cc)
   fmt.Printf("%v,%v岁了\n",a.name,a.age)
}


//结构体的比较用==,会对结构体的类型以及,结构体中每个字段值都做比较,最终全部相同为true,不然为flase
func NewAlarm(time string)Alarm{
a:=Alarm{
   Time:  time,
   Sound: "Klaxon",
}
b:=Alarm{
   Time:  time,
   Sound: "Klaxon",
}
fmt.Println(a)
fmt.Println(b)
fmt.Println(reflect.TypeOf(a))
fmt.Println(reflect.TypeOf(b))
if a==b{
   fmt.Println("1111")
}else{
   fmt.Println("2222")
}
return a