接口

接口

接口是自定义类型,是对其它类型行为的抽象

定义:

接口定义使用interface标识,声明了一系列的函数签名(函数名、函数参数、函数返回值)定义接口时可以指定接口名称,在后续声明接口变量时使用。

// 接口中主要定义行为和方法
type Sender interface { // 定义接口类型
	Send(to string, msg string) error
	SendAll(tos []string, msg string) error
}

type EmailSender struct {
}

func (s EmailSender) Send(to, msg string) error {
	fmt.Println("发送邮件给:", to, "消息内容是:", msg)
	return nil
}

func (s EmailSender) SendAll(tos []string, msg string) error {
	for _, to := range tos {
		s.Send(to, msg)
	}
	return nil
}

func do(send Sender) {
	send.Send("领导", "工作日志")
}

func main() {
	var sender Sender = EmailSender{}     // 将结构体赋值给接口
	fmt.Printf("%T %v\n", sender, sender) // main.EmailSender {}

	sender.Send("kk", "早上好")           // 通过接口调用结构体的方法
	sender.SendAll([]string{"汤采玉", "汤文广", "尹金秀"}, "大家早上好")
	do(sender) // 将接口传入函数作为实参,后续函数调用可以使用接口的方法

	sender = &EmailSender{}
	do(sender)                           // 发送邮件给: 领导 消息内容是: 工作日志 

}
  • 接口赋值给接口

当接口赋值给接口,新接口只能调用和老接口相同的函数方法,不能调用新借口不具备的函数。

type Sender interface {                   // 定义接口类型
	Send(to string, msg string) error
	SendAll(tos []string, msg string) error
}

type SingSend interface {
	Send(to, msg string) error
}

func (s EmailSender) Send(to, msg string) error {
	fmt.Println("发送邮件给:", to, "消息内容是:", msg)
	return nil
}

func (s EmailSender) SendAll(tos []string, msg string) error {
	for _, to := range tos {
		s.Send(to, msg)
	}
	return nil
}


func main() {
    var sender Sender = EmailSender{}
	var ssender SingSend = sender    // 将接口赋值给接口,需要两个接口具备相同类型函数
	ssender.Send("ttt", "早上好")    // 发送邮件给: ttt 消息内容是: 早上好
}

断言

判断一个接口能不能转换为具体类型

type Sender interface {               // 定义接口类型
	Send(to string, msg string) error
	SendAll(tos []string, msg string) error
}
 
type SingSend interface {
	Send(to, msg string) error
}

type EmailSender struct {
}


func (s EmailSender) Send(to, msg string) error {
	fmt.Println("发送邮件给:", to, "消息内容是:", msg)
	return nil
}

func (s EmailSender) SendAll(tos []string, msg string) error {
	for _, to := range tos {
		s.Send(to, msg)
	}
	return nil
}

func main() {
	sender = &EmailSender{}
	var ssender SingSend = sender 
	ssender.Send("ttt", "早上好")    
  
   // 让新接口变回原来的老接口,这时候sender01就有了老接口的功能
	sender01, ok := ssender.(Sender)        // 接口断言,ssender转换为Sender接口
	fmt.Printf("%T,%v\n", sender01, ok)     // *main.EmailSender,true
    sender01.SendAll([]string{"小贩"}, "你好")	// 发送邮件给: 小贩 消息内容是: 你好
}

类型查询

.(type) 只能写在case中

type SingSend interface {
	Send(to, msg string) error
}

type EmailSender struct {
}

main() {
    var sender Sender = EmailSender{}
    sender = &EmailSender{}
    var ssender SingSend = sender
        
    switch ssender.(type) {
	case EmailSender:
		fmt.Println("emailsender")
	case *EmailSender:
		fmt.Println("*emailsender")
	}   
}

/* 
*emailsender 
*/

接口匿名嵌入

type Sender interface {
	Send(msg string) error
}

type Reciver interface {
	Reciver() (string, error)
}

type Client interface {
	Sender				// 匿名嵌套Sender接口
	Reciver					
	Open() error			// 除匿名接口外的其他自定义函数
	Close() error
}

type MSNClient struct {
}

func (c MSNClient) Send(msg string) error {
	fmt.Println("send:", msg)
	return nil
}

func (c MSNClient) Reciver() (string, error) {
	fmt.Println("recive")
	return "", nil
}

func (c MSNClient) Open() error {
	fmt.Println("open")
	return nil
}

func (c MSNClient) Close() error {
	fmt.Println("error")
	return nil
}

func main() {
	msn := MSNClient{}			// 结构体初始化
	var s Sender = msn			// 结构体赋值给接口
	var r Reciver = msn
	var c Client = msn

	s.Send("1")			        // 接口调用结构体方法
	r.Reciver()
	c.Open()
	defer c.Close()
	c.Send("2")
	c.Reciver()

}

匿名接口

func (c MSNClient) Close() error {
	fmt.Println("error")
	return nil
}

type MSNClient struct {
}

main(){
    msn := MSNClient{}     // 结构体初始化
    
    var closer interface { // 定义匿名接口
		Close() error
	}
	closer = msn
	closer.Close()     // error 通过接口变量调用函数
}

空接口

在go中可以通过空接口 接收任意类型的变量

type EStruct struct {         // 定义空结构体
}

type Empty interface {        // 定义空接口
}

func main() {
	es := EStruct{}
	var e interface{} = 1 // 定义空接口为1
	fmt.Println(es, e)    // {} 1

	e = "test"
	fmt.Println(e)	      // test
	
	e = true
	fmt.Println(e)	      // true
}
  • 函数传入接口类型,遍历参数

type EStruct struct { // 定义空结构体
}



func fargs(args ...interface{}) {
	fmt.Println("----------------------------")
	for _, arg := range args {			// 传入参数遍历
		fmt.Println(arg)			// 打印传入参数
		switch v := arg.(type) {		// 接口独有的判断类型方法
		case int:
			fmt.Printf("INT: %T %v\n", v, v)
		case string:
			fmt.Printf("String: %T %v\n", v, v)
		default:
			fmt.Printf("Other: %T %v\n", v, v)
		}
	}

}

func main() {
	es := EStruct{}
	
	fargs(1, "test", true, es)
}

序列化

序列化:将数据结构或对象转换为二进制串的过程

反序列化:在序列化过程中生成的二进制串转换为数据结构或者对象的过程

func main() {
	names := []string{"汤采玉", "汤文广", "刘利纯", "憨憨"}
    users := []map[string]string{{"name": "tcy", "add": "上海"}, {"name": "twg", "add": "长沙"}, {"name": "llc", "add": "长沙"}}

	// 序列化
	bytes, err := json.Marshal(names)
	if err == nil {
		fmt.Println(string(bytes))  // ["汤采玉","汤文广","刘利纯","憨憨"]
	}


	// 序列化
	bytes, err = json.Marshal(users)
	if err == nil {
		fmt.Println(string(bytes)) // [{"add":"上海","name":"tcy"},{"add":"长沙","name":"twg"},{"add":"长沙","name":"llc"}]
	}
    
}
  • 反序列化
	names := []string{"汤采玉", "汤文广", "刘利纯", "憨憨"}
	users := []map[string]string{{"name": "tcy", "add": "上海"}, {"name": "twg", "add": "长沙"}, {"name": "llc", "add": "长沙"}}

	// 序列化
	bytes, err := json.Marshal(names)
	if err == nil {
		fmt.Println(string(bytes)) // ["汤采玉","汤文广","刘利纯","憨憨"]
	}

	// 反序列化
	var names02 []string
	err = json.Unmarshal(bytes, &names02)
	fmt.Println(err)                   // <nil>
	fmt.Println(names02)               // [汤采玉 汤文广 刘利纯 憨憨]

	// 序列化
	bytes, err = json.Marshal(users)
	if err == nil {
		fmt.Println(string(bytes)) // [{"add":"上海","name":"tcy"},{"add":"长沙","name":"twg"},{"add":"长沙","name":"l
		//lc"}]
	}

	// 反序列化
	var user02 []map[string]string
	err = json.Unmarshal(bytes, &user02)
	fmt.Println(err)
	fmt.Println(user02)               // [map[add:上海 name:tcy] map[add:长沙 name:twg] map[add:长沙 name:llc]]

}
  • json格式化
names := []string{"汤采玉", "汤文广", "刘利纯", "憨憨"}

	// 序列化并格式化
	bytes, err := json.MarshalIndent(names, "", "\t")
	if err == nil {
		fmt.Println(string(bytes)) 
	}

/*
[
        "汤采玉",
        "汤文广",
        "刘利纯",
        "憨憨"
]

*/
  • json自动类型
type Size int

const (
	Large = iota
	Medium
	Small
)

func (s Size) MarshalText() ([]byte, error) {
	switch s {
	case Large:
		return []byte("large"), nil
	case Medium:
		return []byte("medium"), nil
	case Small:
		return []byte("small"), nil
	default:
		return []byte("unknow"), nil
	}
}

func (s *Size) UnmarshalText(bytes []byte) error {
	switch string(bytes) {
	case "large":
		*s = Large
	case "medium":
		*s = Medium
	case "Small":
		*s = Small
	}
	return nil
}

func main() {
	var size Size = Medium

	// 序列化
	bytes, _ := json.Marshal(size)
	fmt.Println(string(bytes))

	// 反序列化
	var size02 Size
	json.Unmarshal(bytes, &size02)
	fmt.Println(size02)

}
  • 结构体序列化
// 需要进行序列化或反序列化的属性必须公开,也就是首字母大写,否则无法序列化
// `json:"sex,int,omitempty"` 当属性为0不进行序列化
type User struct {
	ID   int    `json:"-"`         // 属性标签json为名称,- 为值,也表示忽略
	Name string `json:"name"`      // 改变属性名,如防止属性名冲突的情况
	sex  int                       // 小写无法被json转换
	Tel  int    `json:"id,string"` // 改变属性类型,仅作用于json转换
	Addr string
}

func main() {
	user := User{1, "kk", 1, 123, "西安"}

	// 序列化结构体
	bytes, _ := json.MarshalIndent(user, "", "\t")
	fmt.Println(string(bytes))

	// 反序列化结构体
	var user02 User
	json.Unmarshal(bytes, &user02)
	fmt.Println(user02)               // {0 kk 0 123 西安}

}

/*
{
        "name": "kk",
		 "Tel": "123",
        "Addr": "西安"
}

*/

反射

反射是指在运动时动态的访问和修改任意类型对象的结构体和成员,在go语言中提供reflect包提供反射的功能,每一个变量都有两个属性,类型和值

reflect.Type是一个接口类型,用于获取变量类型的信息,可以通过reflectTypeOf函数获取某个变量类型信息:

1> 通用方法

​ Name(): 类型名

​ PkgPath(): 包路径

​ String(): Type字符串

​ Kind(): 类型枚举值

​ Comparable(): 是否可进行比较

​ Implements(): 是否实现某接口

​ AssignableTo(Type): 是否可赋值给某类型

​ ConvertibleTo(Type): 是否可转换为某类型

​ NumMethod(): 方法个数

​ Method(int): 通过索引获取方法类型

​ Method结构体常用属性:

​ Name: 方法名

​ Type: 函数类型

​ Func:方法值(Value)

​ MethodByName(string): 通过方法名字获取方法类型

  • 结构体 reflect.Struct

NumField:属性个数

Field(int):通过索引获取属性

​ StructField结构体常用属性

​ Name:属性名

​ Anonymous:是否为匿名

​ Tag标签:

​ StructTag常用方法:

​ Get(string)

​ Lookup(string)

FieldByName(string): 通过属性名获取属性

  • 结构体类型 reflect.Value

reflect.Value是一个结构体类型,用于获取变量值的信息,可以通过reflect.ValueOf函数获取某个变量值信息

1> 创建方法

2> 通用方法

  • Type(): 获取值类型
  • CanAdd(): 是否可获取地址
  • Addr(): 获取地址
  • Caninterface(): 是否可获取接口的
  • InterfaceData():
  • Interface(): 将变量转换为interface{}
  • CanSet(): 是否可更新
  • isVaild(): 是否初始化为零值
  • Kind(): 获取值类型枚举值
  • NumMethod(): 方法个数
  • Method(int): 通过索引获取方法值
  • MethodByName(string): 通过方法名字获取方法值
  • Convert(Type): 转换为对应类型的值

3> 调用方法:

  • Call
  • CalSlice

4> 修改方法

  • Set/Set*: 设置变量值

5> 特定类型方法

a) reflect.Int,reflect.Unit,

  • int(): 获取对应类型值
  • Unit(): 获取对应类型值

b)reflect.Float*

  • Float(): 获取对应类型值

c)reflect.Complex*

  • Complex(): 获取对应类型值

d) reflact.Arry

  • Len(): 获取数组长度
  • Index(int): 根据索引获取元素
  • Slice(int,int): 获取切片
  • Slice(int,int,int): 获取切片

e) reflact.Slice

  • IsNil():
  • Len():获取元素数量
  • Cap(): 获取容量
  • 根据变量,获取类型方法
func main() {
	var i int = 1
	fmt.Printf("%T\n", i) // 底层使用反射查询出对应类型你

	var typ reflect.Type = reflect.TypeOf(i) // 实现反射底层,查询类型
	fmt.Println(typ)
}
posted @ 2022-05-08 15:05  元气少女郭德纲!!  阅读(80)  评论(0编辑  收藏  举报