Go 笔记之面向对象

Go语言如早期的js和python一样,没有显式的类类型,但可通过结构体与函数显式绑定,隐式地组合实现面向对象编程思维。

struct类型

  • struct类型初始化
    • 按照顺序提供初始化值
    • 通过 field:value 的方式初始化,这样可以任意顺序
    • 通过 new 函数分配一个指针,此处P的类型为 *person
  • struct 的匿名字段(嵌入字段)
    • 匿名字段能够实现字段的继承
    • 所有的内置类型和自定义类型都可以作为匿名字段
    • 同名字段,外层的优先访问,可重载
  • 匿名结构体

    • 空结构值struct{}{}, 通常用在通道结束符信号,不占内存
    • struct{}{name:string} 类似如其它语言中的匿名类一样

        type Skills []string
        type Human struct {
            name string
            age int
            weight int
        }
      
        type Student struct {
            Human  // 匿名字段,那么默认 Student 就包含了 Human 的所有字段
            Skills // 匿名字段,自定义的类型 string slice
            int    // 内置类型作为匿名字段
            speciality string
        }
      
        func main() {
            // 我们初始化一个学生
            mark := Student{Human{"Mark", 25, 120}, "Computer Science"}
        }

面向对象

  • 方法 带有接收者的函数

            func (r ReceiverType) funcName(parameters) (results)
            // 自定义类型,类似于别名
            type typeName typeLiteral
            type ages int
            type months map[string]int
  • 可以在任何的自定义类型中定义任意多的 method

  • 指针作为receiver

    • go 知道是否调用指针的 method 还是非指针的 method,会自转
    • 如果一个 method 的 receiver 是 *T, 你可以在一个 T 类型的实例变量 V 上面调用method,而不需要 &V 去调用这个 method
  • 方法继承 vs 重写

    • Go使用的是内嵌式组合继承,注意区别于其它语言,Go的‘子类’并非是‘父类’类型

interface类型

  • interface 是一组 method 签名的组合
  • 空interface
    • interface{} 存储任意类型的数值 (类C void*)
    • interface 函数参数
  • interface 变量存储的类型
    • Comma-ok 断言
      • value,ok = element(T)
      • element 为interface变量,T断言的类型
    • element.(type) 语法不能在switch外的任何逻辑里面使用
  • 嵌入interface

    • 相同的逻辑引入到interface内

          type Interface interface {
              sort.Interface // 嵌入字段 sort.Interface
              Push(x interface{}) // a Push method to push elements into the heap
              Pop() interface{} // a Pop elements that pops elements from the heap
          }
      

反射

  • 结构休字段类型

      type StructField struct {
          Name string          // 字段名
          PkgPath string       // 字段路径
          Type      Type       // 字段反射类型对象
          Tag       StructTag  // 字段的结构体标签
          Offset    uintptr    // 字段在结构体中的相对偏移
          Index     []int      // Type.FieldByIndex中的返回的索引值
          Anonymous bool       // 是否为匿名字段
      }
  • 反射某一类型的值(这些值都实现了空interface)

    1. 转化为reflect对象(reflect.Type 或 reflect.Value)

          t := reflect.TypeOf(i)    // 得到类型的元数据,通过t我们能获取类型定义里面的所有元素
          v := reflect.ValueOf(i)   // 得到实际的值,通过 v 我们获取存储在里面的值,还可以去改变值
    2. 将reflect转化为相应的值

              tag := t.Elem().Field(0).Tag  // 获取定义在 struct 里面的标签
              name := v.Elem().Field(0).String()  // 获取存储在第一个字段里面的值
    3. 反射的字段必须是可修改(可寻址,即非导出字段不能被修改)

              var x float64 = 3.4
              v := reflect.ValueOf(x)
      
              fmt.Println("type:", v.Type())
              fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
              fmt.Println("value:", v.Float())
      
              //修改相应的值
              p := reflect.ValueOf(&x)
              v := p.Elem()
              v.SetFloat(7.1)
本作品采用《CC 协议》,转载必须注明作者和本文链接
pardon110
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
开发者 @ 社科大
文章
134
粉丝
24
喜欢
101
收藏
55
排名:106
访问:8.9 万
私信
所有博文
社区赞助商