Go语言学习之 Day07 接口

Go 学习 day 07

接口

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

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

interface_test
package day07

import (
	"fmt"
	"testing"
)

type User struct {
	Id   int
	Name string
}

// 定义接口 Persistent
// 行为:Save 保存User切片,Load 加载User 切片
type Persistent interface {
	Save([]User, string) error
	Load(string) ([]User, error)
}

type GobPersistent struct{}

func (p GobPersistent) Save(users []User, path string) error {
	fmt.Println("gob persistent save")
	return nil
}

func (p GobPersistent) Load(path string) ([]User, error) {
	fmt.Println("gob persistent load")
	return nil, nil
}

type CsvPersistent struct{}

func (p CsvPersistent) Save(users []User, path string) error {
	fmt.Println("csv persistent save")
	return nil
}

func (p CsvPersistent) Load(path string) ([]User, error) {
	fmt.Println("csv persistent loan")
	return nil, nil
}

func call(persistent Persistent) {
	fmt.Println("call:")
	persistent.Save(nil, "")
	persistent.Load("")
}

type JsonPersistent struct {
}

func (p *JsonPersistent) Save(users []User, path string) error {
	fmt.Println("json persistent save")
	return nil
}

func (p *JsonPersistent) Load(path string) ([]User, error) {
	fmt.Println("json persistent load")
	return nil, nil
}

type ProtobufPersistent struct {
}

func (p *ProtobufPersistent) Save(users []User, path string) error {
	fmt.Println("protobuf persistent load")
	return nil
}

func (p ProtobufPersistent) Load(path string) ([]User, error) {
	fmt.Println("protobuf persistent load")
	return nil, nil
}

func TestInterface(t *testing.T) {
	var persistent Persistent
	t.Logf("%T,%#v\n", persistent, persistent)

	// 赋值
	// 接口 不能直接通过接口类型初始化对象
	// 需要使用实现行为(实现接口的所有方法,某个对象的类型定义了接口中所有的方法)的对象

	persistent = CsvPersistent{} // 如果有接口后只需要修改实现

	t.Logf("%T,%#v\n", persistent, persistent)

	persistent.Save(nil, "")
	persistent.Load("")

	call(persistent)

	// 多态 => 某个对象赋值为不同的对象 体现出不同的行为
	fmt.Println("多态")
	fmt.Println("Csv:")
	call(CsvPersistent{})
	fmt.Println("Gob:")
	call(GobPersistent{})

	// 定义类型 与接口 是否实现 无语法上直接关联
	// 鸭子类型  你怎么判断一个动物是否是鸭子
	// ==> 看鸭子的行为:游泳,嘎嘎叫
	// 可以游泳的并且会嘎嘎叫的都是鸭子

	// 指针对象
	persistent = new(CsvPersistent)
	fmt.Printf("%T,%#v \n", persistent, persistent)
	persistent.Load("")
	persistent.Save(nil, "")

	call(&CsvPersistent{})
	call(&GobPersistent{})

	// 疑问 为什么指针对象也有Save和Load 方法
	// Go 自动为值接受者方法生成指针接收者方法

	// 是语法糖吗? 不是
	// 值接收者 指针.值接收者方法()=>  语法糖 解引用

	//类型指针接收者 如何赋值

	//JsonPersistent{} = 不可以 ==>未实现值接收者方法
	//new(JsonPersistent) = 可以
	fmt.Println("指针接收者:")
	persistent = new(JsonPersistent)

	persistent.Load("")
	persistent.Save(nil, "")

	// persistent = JsonPersistent{}
	// persistent.Load("")
	// persistent.Save(nil, "")

	// 又有指针,又有值
	// ProtobufPersistent{} => 未实现save值接收者方法
	// new(ProtobufPersistent)
	// persistent = ProtobufPersistent{}
	// persistent.Load("")
	// persistent.Save(nil, "")

	persistent = &ProtobufPersistent{}
	persistent.Load("")
	persistent.Save(nil, "")
}

interface_type
package interface_type

import (
	"fmt"
	"testing"
)

type User struct {
}

type Persistent interface {
	Save([]User, string) error
	Load(string) ([]User, error)
}

type GobPersistent struct {
	Version string
}

func (p GobPersistent) Save(users []User, path string) error {
	fmt.Println("save")
	return nil
}

func (p GobPersistent) Load(path string) ([]User, error) {
	fmt.Println("load")
	return nil, nil
}

func (p GobPersistent) Test() {
	fmt.Println("test")
}

func TestInterfaceType(t *testing.T) {
	var persistent Persistent = GobPersistent{}
	//var persistent = GobPersistent{}
	t.Logf("%T,%#v\n", persistent, persistent)

	persistent.Save(nil, "")
	persistent.Load("")
	// persistent.Test()               // 不能调用Test方法,Persistent接口无Test方法
	// fmt.Println(persistent.Version) // 不能获取Version属性
}

jsontools_test
package json_test

import (
	"encoding/json"
	"os"
	"testing"
)

func TestJsonTools(t *testing.T) {
	txt := `[1,2,3`
	ok := json.Valid([]byte(txt))
	t.Log(ok)
}

//------------------------

type User struct {
	Id   int
	Name string
	Addr json.RawMessage
}

func TestJsonraw(t *testing.T) {
	txt := `{"id":1,"name":"kk","addr":{"street":"陕西省西安市","no":"10002"}}`
	var u User
	err := json.Unmarshal([]byte(txt), &u)
	t.Log(err, u)
}

//--------------------------
/*
Encoder
Decoder
*/

type Addr struct {
	Street string `json:"street"`
	No     string `json:"no"`
}

type MyUser struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
	Addr Addr   `json:"addr"`
}

func TestJsonCoder(t *testing.T) {

	//u := MyUser{1, "kk", Addr{
	//	Street: "重庆渝北区",
	//	No:     "10003",
	//}}
	//
	//file, _ := os.Create("./user.json")
	//defer file.Close()
	//encoder := json.NewEncoder(file)
	//err := encoder.Encode(u)
	//t.Log(err)

	file, _ := os.Open("user.json")
	defer file.Close()
	decoder := json.NewDecoder(file)
	var user User
	err := decoder.Decode(&user)
	t.Log(err, user)

}

type_query_test
package type_query_test

import (
	"fmt"
	"testing"
)

type User struct {
	Id   int
	Name string
}

// 定义接口Persistent
//  行为: Save 保存 User 切片,Load 加载User切片

type Persistent interface {
	Save([]User, string) error
	Load(string) ([]User, error)
}

type GobPersistent struct {
	GVersion string
}

// 定义了 Persistent 所有的接口,就叫GobPersistent 实现了 Persistent 接口

func (p GobPersistent) Save(users []User, path string) error {
	fmt.Println("gob persistent save")
	return nil
}

func (p GobPersistent) Load(path string) ([]User, error) {
	fmt.Println("gob persistent load")
	return nil, nil
}

type CsvPersistent struct {
	CVersion string
}

func (p CsvPersistent) Save(users []User, path string) error {
	fmt.Println("csv persistent save")
	return nil
}

func (p CsvPersistent) Load(path string) ([]User, error) {
	fmt.Println("csv persistent load")
	return nil, nil
}

func call(persistent Persistent) {
	fmt.Println("call:")
	persistent.Save(nil, "")
	persistent.Load("")
}

type JsonPersistent struct {
	Jversion string
}

func (p *JsonPersistent) Save(users []User, path string) error {
	fmt.Println("json persistent save")
	return nil
}

func (p *JsonPersistent) Load(path string) ([]User, error) {
	fmt.Println("json persistent load")
	return nil, nil
}

type ProtobufPersistent struct {
	Pversion string
}

func (p *ProtobufPersistent) Save(users []User, path string) error {
	fmt.Println("protobuf persistent save")
	return nil
}

func (p ProtobufPersistent) Load(path string) ([]User, error) {
	fmt.Println("protobuf persistent load")
	return nil, nil
}

type Other struct{}

func (p *Other) Save(users []User, path string) error {
	fmt.Println("other persistent save")
	return nil
}

func (p Other) Load(path string) ([]User, error) {
	fmt.Println("other persistent load")
	return nil, nil
}

func TestTypeQuery(t *testing.T) {
	var persistent Persistent = &ProtobufPersistent{"1.1.1"}

	if g, ok := persistent.(GobPersistent); ok {
		t.Log("g", g, ok)
	} else if c, ok := persistent.(CsvPersistent); ok {
		t.Log("c", c, ok)
	} else if j, ok := persistent.(*CsvPersistent); ok {
		t.Log("j", j, ok)
	} else if p, ok := persistent.(*ProtobufPersistent); ok {
		t.Log("p", p, ok)
	} else {
		t.Log("error")
	}

	/*
		switch 接口类型变量.(type) {
		case GobPersistent:
		case CsvPersistent:
		case *JsonPersistent:
		case *ProtobufPersistent:
		default:
		}

		switch p := 接口类型变量.(type) {
		case GobPersistent:
		case CsvPersistent:
		case *JsonPersistent:
		case *ProtobufPersistent:
		default:
		}
	*/
	switch persistent.(type) {
	case GobPersistent:
		fmt.Println("g")
	case CsvPersistent:
		fmt.Println("c")
	case *JsonPersistent:
		fmt.Println("j")
	case *ProtobufPersistent:
		fmt.Println("p")
	default:
		fmt.Println("err")
	}

	switch p := persistent.(type) {
	case GobPersistent:
		fmt.Println("g", p.GVersion)
	case CsvPersistent:
		fmt.Println("c", p.CVersion)
	case *JsonPersistent:
		fmt.Println("j", p.Jversion)
	case *ProtobufPersistent:
		fmt.Println("p", p.Pversion)
	default:
		fmt.Println("err")
	}

}

断言

type_assert_test
package type_assert_test

import (
	"fmt"
	"testing"
)

type User struct{}

type Persistent interface {
	Save([]User, string) error
	Load(string) ([]User, error)
}

type GobPersistent struct {
	GVersion string
}

func (p GobPersistent) Save(users []User, path string) error {
	fmt.Println("save")
	return nil
}

func (p GobPersistent) Load(path string) ([]User, error) {
	fmt.Println("load")
	return nil, nil
}

func (p GobPersistent) Test() {
	fmt.Println("test")
}

type CsvPersistent struct {
	CVersion string
}

func (p CsvPersistent) Save(users []User, path string) error {
	fmt.Println("save")
	return nil
}

func (p CsvPersistent) Load(path string) ([]User, error) {
	fmt.Println("load")
	return nil, nil
}

type Saver interface {
	Save([]User, string) error
}

func TestTypeAssert(t *testing.T) {
	var persistent Persistent = GobPersistent{"1.1.1.1"}
	// 断言 => 接口
	// 对应类型的变量, ok:= 接口类型变量.(类型)

	gobPersistent, ok := persistent.(GobPersistent)
	t.Logf("%T,%#v,%T,%#v\n", ok, ok, gobPersistent, gobPersistent)
	gobPersistent.Test()

	//user, ok := persistent.(User) // 没有实现接口类型
	//t.Log(user, ok)
	csvPersistent, ok := persistent.(CsvPersistent)
	t.Logf("%T, %#v, %T, %#v\n", ok, ok, csvPersistent, csvPersistent)

	var saver Saver = persistent
	// Persistent, GobPersistent, CsvPersistent

	p, ok := saver.(Persistent)
	t.Logf("%T,%#v,%T,%#v\n", ok, ok, p, p)
	p.Load("")

	//GobPersistent
	g, ok := saver.(GobPersistent)
	t.Logf("%T, %#v, %T, %#v\n", ok, ok, g, g)
	g.Test()
	t.Log(g.GVersion)

	//CsvPersistent
	c, ok := saver.(CsvPersistent)
	t.Logf("%T, %#v, %T, %#v\n", ok, ok, c, c)

}



=== RUN   TestTypeAssert
    type_assert_test.go:57: bool,true,type_assert_test.GobPersistent,type_assert_test.GobPersistent{GVersion:"1.1.1.1"}
test
    type_assert_test.go:63: bool, false, type_assert_test.CsvPersistent, type_assert_test.CsvPersistent{CVersion:""}
    type_assert_test.go:69: bool,true,type_assert_test.GobPersistent,type_assert_test.GobPersistent{GVersion:"1.1.1.1"}
load
    type_assert_test.go:74: bool, true, type_assert_test.GobPersistent, type_assert_test.GobPersistent{GVersion:"1.1.1.1"}
test
    type_assert_test.go:76: 1.1.1.1
    type_assert_test.go:80: bool, false, type_assert_test.CsvPersistent, type_assert_test.CsvPersistent{CVersion:""}
--- PASS: TestTypeAssert (0.00s)
PASS

反射

reflect_func_test
package reflect

import (
	"fmt"
	"reflect"
	"testing"
)

func printHi() {
	fmt.Println("hi")
}

func printHello(name string) string {
	fmt.Printf("hello: %s \n", name)
	return fmt.Sprintf("hello: %s", name)
}
func TestReflectFunc(t *testing.T) {
	fmt.Println("==========print Hi")
	value := reflect.ValueOf(printHi)
	t.Log(value.Type())

	params := make([]reflect.Value, 0)
	rts := value.Call(params)
	t.Log(rts)

	fmt.Println("============print Hello")
	value = reflect.ValueOf(printHello)
	t.Log(value.Type())
	params = make([]reflect.Value, 0)
	name := "kk"
	params = append(params, reflect.ValueOf(name))
	rts = value.Call(params)
	t.Log(rts[0].String())
}

reflect_method_test
package reflect

import (
	"reflect"
	"testing"
)

type User struct {
}

func (u User) TableName() string {
	return "aaa"
}

func TestReflectMethod(t *testing.T) {
	//value := reflect.ValueOf(new(User))
	value := reflect.ValueOf(&User{})

	methodValue := value.MethodByName("TableName")
	if !methodValue.IsValid() {
		t.Log(value.Elem().Type().Name())
		return
	}

	methodType := methodValue.Type()
	if 0 != methodType.NumIn() || 1 != methodType.NumOut() {
		t.Log(value.Elem().Type().Name())
		return
	}

	if outType := methodType.Out(0); outType.Kind() != reflect.String {
		t.Log(value.Elem().Type().Name())
		return
	}
	params := make([]reflect.Value, 0)
	rts := methodValue.Call(params)
	t.Log(rts)
	t.Log(rts[0].String())

}

=== RUN   TestReflectMethod
    reflect_method_test.go:37: [aaa]
    reflect_method_test.go:38: aaa
--- PASS: TestReflectMethod (0.00s)
PASS
reflect_type_test
package reflect

import (
	"reflect"
	"testing"
)

type UserT struct {
	Id   int    `kk:"yyy"`
	Name string `kk:"xxxx"`
}

func (u UserT) GetId() int {
	return u.Id
}

func (u *UserT) GetName() string {
	return u.Name
}

type Persistent interface {
	Save()
}

type DbPersistent struct {
}

func (p DbPersistent) Save() {

}

func TestReflectType(t *testing.T) {
	var u = new(UserT)
	typeValue := reflect.TypeOf(u)
	t.Logf("%T,%#v\n", typeValue, typeValue)
	t.Log(typeValue.Name())
	t.Log(typeValue.PkgPath())
	t.Log(typeValue.Kind())
	t.Log(typeValue.NumMethod())

	for i := 0; i < typeValue.NumMethod(); i++ {
		method := typeValue.Method(i)
		t.Log(i, method.Name)
	}

	m, ok := typeValue.MethodByName("GetName")
	t.Log(m)
	t.Log(ok)

	m, ok = typeValue.MethodByName("GetName1")
	t.Log(m)
	t.Log(ok)

	st := typeValue.Elem()
	t.Log(st.NumField())

	for i := 0; i < st.NumField(); i++ {
		field := st.Field(i)
		t.Log(i, field.Name, field.Type.Kind(), field.Tag.Get("kk"))
	}

}

练习

作业

posted @ 2023-01-15 20:49  元贞  阅读(18)  评论(0编辑  收藏  举报