Go第八课-复合数据类型:结构体

137 阅读3分钟
  1. 聚合抽象能力的类型是结构体类型,也就是 struct。

  2. 自定义新类型的方法:

    1. 使用关键字 type 来定义一个新类型 T,基于已有类型或类型字面值来定义新类型

      type T S // 定义一个新类型T
      
      type T1 int 
      type T2 T1
      type M map[int]string
      type S []string
      
    2. 第二种自定义新类型的方式是使用类型别名(Type Alias),这种类型定义方式通常用在项目的渐进式重构,还有对已有包的二次封装方面。

      type T = S // type alias
      // T 与 S 实际上就是同一种类型,它们只是一种类型的两个名字罢了
      
      type byte = uint8
      type rune = int32
      
  3. 如果一个新类型是基于某个 Go 原生类型定义的,那么我们就叫 Go 原生类型为新类型的底层类型。

  4. 底层类型被用来判断两个类型本质上是否相同(Identical)。本质上相同的两个类型,它们的变量可以通过显式转型进行相互赋值,相反,如果本质上是不同的两个类型,它们的变量间连显式转型都不可能,更不要说相互赋值了。

    type T1 int
    type T2 T1
    type T3 string
    
    func main() {
        var n1 T1
        var n2 T2 = 5
        n1 = T1(n2)  // ok
        
        var s T3 = "hello"
        n1 = T1(s) // 错误:cannot convert s (type T3) to type T1
    }
    
  5. 定义一个结构体类型,打括号包裹的是类型字面值,由若干个字段(field)聚合而成,每个字段有自己的名字与类型。

    type T struct {
        Field1 T1
        Field2 T2
        ... ...
        FieldN Tn
    }
    
  6. 定义一个空结构体。空结构体类型变量的内存占用为 0。

    type Empty struct{} // Empty是一个不包含任何字段的空结构体类型
    var s Empty
    println(unsafe.Sizeof(s)) // 0
    
  7. 使用其他结构体作为自定义结构体中字段的类型。

  8. 在结构体类型 T 的定义中不可以包含类型为 T 的字段,Go 语言不支持这种在结构体类型定义中,递归地放入其自身类型字段的定义方式。

  9. 结构体类型的变量通常都要被赋予适当的初始值后,才会有合理的意义。Go 推荐我们用“field:value”形式的复合字面值:

    var t = T{
        F2: "hello",
        F1: 11,
        F4: 14,
    }
    
  10. Go 结构体类型是既数组类型之后,第二个将它的元素(结构体字段)一个接着一个以“平铺”形式,存放在一个连续内存块中的。

  11. 所谓内存对齐,指的就是各种内存对象的内存地址不是随意确定的,必须满足特定要求。对于结构体而言,它的变量的内存地址,只要是它最长字段长度与系统对齐系数两者之间较小的那个的整数倍就可以了.

  12. 你在日常定义结构体时,一定要注意结构体中字段顺序,尽量合理排序,降低结构体对内存空间的占用