go语言学习之接口与动态类型

2023-01-04 14:07:58 浏览数 (1)

本学习笔记全部以代码块的形式展示,具体的内容都包含在代码里:

代码语言:javascript复制
package types

import (
  "errors"
  "fmt"
  "reflect"
)

// 接口与动态类型
// 1. interface{}(空接口) 可以当作泛型使用,可以接受任何go类型(个人理解)。
// 2. Go 没有类,数据(结构体或更一般的类型)和方法是一种松耦合的正交关系。
// 3. 接口需要提供一个指定方法集的实现,任何提供了接口方法实现代码的类型都隐式地实现了该接口,而不用显式地声明。
// 4. Go 是唯一结合了接口值,静态类型检查(是否该类型实现了某个接口),运行时动态转换的语言。(js没有静态检查真是永远的痛!)
// 5. Go 也拥有动态类型,即 duck typing(看起来像鸭子,那么就是鸭子),实现某个接口的类型可以作为实参传递给以该接口为形参的函数,并且还提供了静态检查。
// 6. 一个类型可以实现多个接口。
// 7. Go 使用可变参数间接实现 函数重载。
// 8. Go 中的接口也可以实现 继承,即当一个类型包含(内嵌)另一个类型(实现了一个或多个接口)的指针时,这个类型就可以使用(另一个类型)所有的接口方法。

// 3
type Person interface {
  getName() string
  getAge() int
}

type P struct {
  name   string
  age    int
  career string
}

// 结构体 P 实现了 Person 接口
func (p P) getName() string {
  return p.name
}
func (p P) getAge() int {
  return p.age
}

// 5
func getPerson(p Person) (name string, age int) {
  name = p.getName()
  age = p.getAge()
  return name, age
}

// 6
// 再声明 Worker 接口
type Worker interface {
  getCareer() string
}

func (p P) getCareer() string {
  return p.career
}

// 8
type Chinese struct {
  nation string
  P
}

func InterfaceAndDynamic() {
  var p1 P = P{"zdzw", 27, "front_end engineer"}

  p1_name, p1_age := getPerson(p1)

  fmt.Printf("p1_name: %s, p1_age: %d, p1_career: %sn", p1_name, p1_age, p1.getCareer())

  var c1 Chinese = Chinese{"China", p1}

  fmt.Printf("c1_nation: %s, c1_career: %sn", c1.nation, c1.getCareer())

  // 练习
  map_function(1, 2, 3, "aaa", "bbb", "ccc")
  stack_function()
}
// 实现可接口任意类型作为参数的函数,是 int 则双倍;是 string 则自身相加。
func map_function(args ...interface{}) {
  var result []interface{}
  for _, val := range args {
    t := reflect.TypeOf(val)
    v := reflect.ValueOf(val)
    switch t.Kind() {
    case reflect.Int:
      result = append(result, v.Int()*2)
    case reflect.String:
      result = append(result, v.String() v.String())
    default:
    }
  }
  fmt.Println("map_function: ", result)
}

// 实现一个可以接受任何类型的栈
type Stack interface {
  Len() int
  IsEmpty() bool
  push(x interface{})
  pop() (interface{}, error)
  Top() (interface{}, error)
}

type StackIns []interface{}

func (s StackIns) Len() int {
  return len(s)
}

func (s StackIns) IsEmpty() bool {
  return s.Len() <= 0
}

func (s *StackIns) Push(x interface{}) {
  *s = append(*s, x)
}

func (s *StackIns) Pop() (interface{}, error) {
  s_val := *s
  if len(s_val) == 0 {
    return nil, errors.New("stack is empty")
  }
  v := s_val[len(s_val)-1]
  *s = s_val[:len(s_val)-1]
  return v, nil
}

func (s StackIns) Top() (interface{}, error) {
  if len(s) == 0 {
    return nil, errors.New("stack is empty")
  }
  return s[len(s)-1], nil
}

func stack_function() {
  var s StackIns = StackIns{1, 2, 3, "a", "b", "c"}
  s.Push("d")
  fmt.Println("s.Push: ", s, len(s))
  v, _ := s.Top()
  fmt.Println("s.Top: ", v)
  v, _ = s.Pop()
  fmt.Println("s.Pop: ", v, s)
}

0 人点赞