接口
接口
接口是自定义类型,是对其它类型行为的抽象
定义:
接口定义使用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)
}