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"))
}
}