目录

接口的定义

interface 是一组 method 的集合。接口做的事情就像是定义一个协议(规则)。不关心属性(数据),只关心行为(方法)。

接口(interface)是一种类型!

type MyInterface interface{
 FunctionOne(interface{})(interface{})
 FunctionTow(data string)(bool)
}

接口中定义的函数,参数列表和返回值列表中的变量名都可以省略!

接口可以嵌套

type Sayer interface{
 say()
}
type Mover interface{
 move()
}
type People interface{
 Sayer
 Mover
}

实现接口的条件

一个对象只要全部实现了接口中的方法,那么就实现了这个接口。也就是说: 接口是一个需要实现的一系列方法的列表。

重要!

值接收者和指针接收者接口实现接口是有区别的!

  • 值接收者实现的接口不管是结构体、还是结构体指针都能赋值给对应实现的接口变量(这是因为Go中有对指针类型变量求值的语法糖,结构体指针内部会自动求值*结构体指针
  • 指针类型接收者实现的接口只能传递*结构体类型值赋值给接口

下面的验证类接口中有具体指针类型接收者实现接口的例子。

接口的用途

列子

编写验证数字和字符串长度的类

  • main.go
package main

import (
 "demo/validate"
 "fmt"
)
type user struct {
 Name     string `valida:"required,min=22,max=100"`
 Password string `valida:"-"`
 Age      int    `valida:"required,min=1,max=120"`
}
func main() {
 u := user{
  Name:     "Hello",
  Password: "Password",
  Age:      1,
 }
 v := validate.NewValidate(u)
 v.Validate()
 for _, err := range v.Error {
  fmt.Println(err)
 }
}
  • validate.go
package validate

import (
 "fmt"
 "reflect"
 "strconv"
 "strings"
)
const validatorTagName = "valida"
type Validate struct {
 Data  interface{}
 Error []error
}

func NewValidate(data interface{}) *Validate {
 return &Validate{Data: data}
}
func (v *Validate) Validate() {
 var errs []error
 valueOf := reflect.ValueOf(v.Data)
 //只支持结构体验证
 if valueOf.Kind() != reflect.Struct {
  panic("只支持struct类型验证")
 }
 //循环结构体,获取每一行的相关属性
 for i := 0; i < valueOf.NumField(); i++ {
  //获取对应的tag数据
  tag := valueOf.Type().Field(i).Tag.Get(validatorTagName)
  //获取对应类型的数据类(其实是一个验证类接口的实例化)
  validate := v.getValidate(valueOf.Field(i).Kind().String(), valueOf.Type().Field(i).Name, tag)
  //实例化的验证类开始验证数据
  validator, err := validate.Validator(valueOf.Field(i).Interface())
  if !validator && err != nil {
   errs = append(errs, err)
  }
 }
 v.Error = errs
}
// 不能返回指针类型接口 结构体是指针类型的实现,需要访问结构体指针类型的值
// 指针类型接收者实现的接口只能传递`*结构体`类型值赋值给接口
func (v *Validate) getValidate(fieldType, fieldName, tag string) Validator {
 tagArgs := strings.Split(tag, ",")
 //过滤不需要验证的字段
 if tagArgs[0] == "-" || tagArgs[0] == "" {
  return &DefaultValidator{}
 }
 switch fieldType {
 case "string":
  strValidator := &StringValidator{}
  strValidator.FieldName = fieldName
  for _, val := range tagArgs {
   if val == "required" {
    strValidator.Required = true
   }
   if strings.Contains(val, "min") {
    valArgs := strings.Split(val, "=")
    strValidator.Min, _ = strconv.Atoi(valArgs[1])
   }
   if strings.Contains(val, "max") {
    valArgs := strings.Split(val, "=")
    strValidator.Max, _ = strconv.Atoi(valArgs[1])
   }
  }
  if strValidator.Max < strValidator.Min {
   panic("max value must be greater than min value!")
  }
  return strValidator
 case "int":
  intValidator := &IntValidator{}
  intValidator.FieldName = fieldName
  for _, val := range tagArgs {
   if val == "required" {
    intValidator.Required = true
   }
   if strings.Contains(val, "min") {
    valArgs := strings.Split(val, "=")
    intValidator.Min, _ = strconv.Atoi(valArgs[1])
   }
   if strings.Contains(val, "max") {
    valArgs := strings.Split(val, "=")
    intValidator.Max, _ = strconv.Atoi(valArgs[1])
   }
  }
  if intValidator.Min > intValidator.Max {
   panic("max value must be greater than min value!")
  }
  return intValidator
 }
 return &DefaultValidator{}
}

//验证类接口
type Validator interface {
 Validator(interface{}) (bool, error)
}
type DefaultValidator struct{}
type StringValidator struct {
 FieldName string
 Max, Min  int
 Required  bool
}
type IntValidator struct {
 FieldName string
 Max, Min  int
 Required  bool
}
func (d *DefaultValidator) Validator(interface{}) (bool, error) {
 return true, nil
}
func (s *StringValidator) Validator(data interface{}) (bool, error) {
 str := data.(string)
 length := len(str)
 if s.Required && length == 0 {
  return false, fmt.Errorf("%s 为必填字段", s.FieldName)
 }
 if length < s.Min {
  return false, fmt.Errorf("%s 长度不能小于 %d", s.FieldName, s.Min)
 }
 if length > s.Max {
  return false, fmt.Errorf("%s 长度不能大于 %d", s.FieldName, s.Max)
 }
 return true, nil
}
func (i *IntValidator) Validator(data interface{}) (bool, error) {
 integer := data.(int)
 if i.Required && integer == 0 {
  return false, fmt.Errorf("%s 不能为0", i.FieldName)
 }
 if integer < i.Min {
  return false, fmt.Errorf("%s 不能小于 %d", i.FieldName, i.Min)
 }
 if integer > i.Max {
  return false, fmt.Errorf("%s 不能大于 %d", i.FieldName, i.Max)
 }
 return true, nil
}

接口断言

函数的参数是空接口时可以使用断言来获取实际传入的数据

func main {
  var x interface{}
  x = "Hello Golang"
  v,ok := x.(string)
  if ok {
   fmt.Println(v)
  else{
   fmt.Println("不是string类型")
  }
}