GO自定义类型与指针

指针
定义:将地址形象化的称为“指针”。将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。一个指针变量指向了一个值的内存地址。意思是通过它能找到以它为地址的内存单元。一个指针变量指向了一个值的内存地址。
注意:Go语言支持指针类型*T,指针的指针**T,以及包含包名前缀的*package.T。
1、指针声明
a) 声明一个int类型指针
         var ip *int
         b)声明一个string类型指针
         var sp *string
         c) 通过 := 语法来定义指针
               var str string = "oldboy"
               sp := &str    
         d)声明一个int值的指针的指针变量(即,指针的指针)
          var p **int
         e) 声明一个time.Time值的指针变量
          var t *time.Time

2、空指针
定义:当一个指针被定义后没有分配到任何变量时,它的值为 nil。nil 指针也称为空指针
注意:nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值
3、指针类型转换
    注意:    
            a)Go语言是不允许两个指针类型进行转换的。
            b)unsafe.Pointer类型用于表示任意类型的指针。有4个特殊的只能用于Pointer类型的操作:
               1、 任意类型的指针可以转换为一个Pointer类型值
               2、 一个Pointer类型值可以转换为任意类型的指针
               3、 一个uintptr类型值可以转换为一个Pointer类型值
               4、 一个Pointer类型值可以转换为一个uintptr类型值
    

结构体
定义:结构体是由一系列具有相同类型或不同类型的数据构成的数据集合
特点:
1、用来自定义复杂数据结构
2、struct里面可以包含一个或多个字段(属性)
3、struct类型可以定义方法,注意和函数的区分
4、struct类型是值类型
5、struct类型可以嵌套
6、结构体是用户单独定义的类型,不能和其他类型进行强制转换
7、Go中的struct没有构造函数,一般可以使用工厂模式来解决这个问题
8、我们可以为struct中的每个字段,写上一个tag。tag可以通过反射的机制获取,常用的场景就是json序列化和反序列化
9、访问结构体成员, 用 "." 来连接,格式为:"结构体.成员名"
1、struct定义
a)定义一个新的数据类型,结构体中只有一个成员。
               type bigint int64
               type smallint int8         
         b) 定义一个新的数据类型,结构体中有多个成员
              type oldboy struct {
                     Linux  string
                     Python string
                     Golang string
               }         
         c) 定义一个新的数据类型,指向结构体的指针
              type Linux string
              type oldboy struct {
                      *Linux
               }

2、struct 初始化
注意:
有序初始化: 结构体中的多个成员的值,必须一一对应。
无序初始化: 结构体中的多个成员的值,无须一一对应,可初始化部分值。
a)方式一
1、定义
             type oldboy struct {
                  Linux  string
                  Python string
                  Golang string
             }    
            2、初始化
               var ordered = oldboy{"linux", "python", "golang"}  // 有序初始化
               var disordered = oldboy{Golang: "golang"}  // 无序初始化

b)方式二
1、定义
            type oldboy struct {
                  int
                  string
             }
            2、初始化
               two := new(oldboy) //同 var two *oldboy = new(oldboy)  //指针变量
               three := oldboy{1, "three"}
               four := oldboy{}
               five := &oldboy{}  //指针变量
               six := &oldboy{2, "six"} //同 var six *oldboy = &oldboy{2, "six"} //指针变量

c)结构体包含结构体初始化
1、定义
              type Person struct {
                  name string
                  age  int
                  addr string
               }
               type Employee struct {
                  Person //匿名字段
                  salary int
                  int           //用内置类型作为匿名字段
                  addr   string //类似于重载
               } 
            2、初始化
            em1 := Employee{
                  Person{"oldboy", 18, "北京"},
                  10,
                  100,
                  "首都",
             }

3、struct与tag应用
注意:tag声明struct结构的时候,在属性的右侧用小米点括起来的内容叫标签(Tag),
在转换成其它数据格式的时候,会使用其中特定的字段作为键值,一般在序列化和反序列化使用
a)定义
            type User struct {
               UserId   int
               UserName string
            }
            type UserTag struct {
               UserId   int    `json:"user_id" bson:"user_id"`
               UserName string `json:"user_name" bson:"user_name"`
            }
         b)初始化
            user := &User{UserId: 1, UserName: "oldboy"}
            json_user, _ := json.Marshal(user)
            fmt.Printf("struct User echo : %v\n", string(json_user))

            user_tag := &UserTag{UserId: 1, UserName: "oldboy"}
            json_user_tag, _ := json.Marshal(user_tag)