接口、反射(下)

接口

7. 接口嵌套
      
一个接口可以嵌套在另外的接口,如下所示:

 type ReadWrite interface {
               Read(b Buffer) bool
               Write(b Buffer) bool
} 
type Lock interface {
               Lock()
               Unlock() 
} 
type File interface {
               ReadWrite
               Lock 
               Close() 
} 

 

package main

import "fmt"

type Reader interface {
	Read()
}

type Writer interface {
	Write()
}

type ReadWriter interface {
	Reader
	Writer
}

type File struct {
}

func (f *File) Read() {
	fmt.Println("read data")
}

func (f *File) Write() {
	fmt.Println("write data")
}

func Test(rw ReadWriter) {
	rw.Read()
	rw.Write()
}

func main() {
	var f *File
	var b interface{}
	b = f
	//Test(&f)
	v, ok := b.(ReadWriter)
	fmt.Println(v, ok)
}

 8. 类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型
      可以采用以下方法进行转换:

var t int
var x interface{}
x = t
y = x.(int)   //转成int

 

var t int
var x interface{}
x = t
y, ok = x.(int)   //转成int,带检查

 练习,写一个函数判断传入参数的类型

 func classifier(items ...interface{}) {
          for i, x := range items { 
                  switch x.(type) {
                   case bool:       fmt.Printf(“param #%d is a bool\n”, i)
                   case float64:    fmt.Printf(“param #%d is a float64\n”, i)
                   case int, int64: fmt.Printf(“param #%d is an int\n”, i)
                   case nil: fmt.Printf(“param #%d is nil\n”, i)
                   case string: fmt.Printf(“param #%d is a string\n”, i)
                    default: fmt.Printf(“param #%d’s type is unknown\n”, i)
            }
}

类型断言,采用type switch方式

switch t := areaIntf.(type) {case *Square:        fmt.Printf(“Type Square %T with value %v\n”, t, t) 
case *Circle:       fmt.Printf(“Type Circle %T with value %v\n”, t, t) 
case float32:       fmt.Printf(“Type float32 with value %v\n”, t)case nil:        fmt.Println(“nil value: nothing to check?”) 
default:        fmt.Printf(“Unexpected type %T”, t)}

 

exp:

package main

import "fmt"

type Student struct {
	Name string
	Sex  string
}

func Test(a interface{}) {
	b, ok := a.(Student)
	if ok == false {
		fmt.Println("convert failed")
		return
	}
	//b += 3
	fmt.Println(b)
}

func just(items ...interface{}) {
	for index, v := range items {
		switch v.(type) {
		case bool:
			fmt.Printf("%d params is bool, value is %v\n", index, v)
		case int, int64, int32:
			fmt.Printf("%d params is int, value is %v\n", index, v)
		case float32, float64:
			fmt.Printf("%d params is float, value is %v\n", index, v)
		case string:
			fmt.Printf("%d params is string, value is %v\n", index, v)
		case Student:
			fmt.Printf("%d params student, value is %v\n", index, v)
		case *Student:
			fmt.Printf("%d params *student, value is %v\n", index, v)
		}
	}
}

func main() {
	var b Student = Student{
		Name: "stu01",
		Sex:  "female",
	}
	Test(b)
	just(28, 8.2, "this is a test", b, &b)
}

 11. 空接口,Interface{}
  空接口没有任何方法,所以所有类型都实现了空接口。

var a int
var b interface{}
b  = a

 

 12. 判断一个变量是否实现了指定接口

 type Stringer interface {
        String() string 
}
var v MyStruct
if sv, ok := v.(Stringer); ok {
       fmt.Printf(“v implements String(): %s\n”, sv.String()); 
} 

 反射

1、反射:可以在运行时动态获取变量的相关信息
     Import (“reflect”)
a. reflect.TypeOf,获取变量的类型,返回reflect.Type类型
b. reflect.ValueOf,获取变量的值,返回reflect.Value类型
c. reflect.Value.Kind,获取变量的类别,返回一个常量
d. reflect.Value.Interface(),转换成interface{}类型


2. reflect.Value.Kind()方法返回的常量
const (
        Invalid Kind = iota
        Bool
        Int
        Int8
        Int16
        Int32
        Int64
        Uint
        Uint8
        Uint16
        Uint32
        Uint64
        Uintptr
        Float32
        Float64
        Complex64
        Complex128
        Array
        Chan
        Func
        Interface
        Map
        Ptr
        Slice
        String
        Struct
        UnsafePointer
)
3. 练习:

package main

import (
	"fmt"
	"reflect"
)

func main() {

	var x float64 = 3.4
	fmt.Println("type:", reflect.TypeOf(x))
	v := reflect.ValueOf(x)
	fmt.Println("value:", v)
	fmt.Println("type:", v.Type())
	fmt.Println("kind:", v.Kind())
	fmt.Println("value:", v.Float())

	fmt.Println(v.Interface())
	fmt.Printf("value is %5.2e\n", v.Interface())
	y := v.Interface().(float64)
	fmt.Println(y)
}

4. 获取变量的值:

  • reflect.ValueOf(x).Float()
  • reflect.ValueOf(x).Int()
  • reflect.ValueOf(x).String()
  • reflect.ValueOf(x).Bool()

5. 通过反射的来改变变量的值
  reflect.Value.SetXX相关方法,比如:

  • reflect.Value.SetFloat(),设置浮点数
  • reflect.Value.SetInt(),设置整数
  • reflect.Value.SetString(),设置字符串
package main

import (
	"fmt"
	"reflect"
)

func main() {

	var a float64
	fv := reflect.ValueOf(&a)
	fv.Elem().SetFloat(3.3)
	fmt.Printf("%v\n", a)
}

 其中fv.Elem()用来获取指针指向的变量,相当于:
var a *int;  
*a = 100
9. 用反射操作结构体
a. reflect.Value.NumField()获取结构体中字段的个数
b. reflect.Value.Method(n).Call来调用结构体中的方法

10. 练习

package main

import (
	"fmt"
	“reflect"
)

type NotknownType struct {
	s1 string
	s2 string
	s3 string
}
func (n NotknownType) String() string {
	return n.s1 + "-" + n.s2 + "-" + n.s3
}
var secret interface{} = NotknownType{"Ada", "Go", "Oberon"}

func main() {
	value := reflect.ValueOf(secret) // <main.NotknownType Value>
	typ := reflect.TypeOf(secret)    // main.NotknownType
	fmt.Println(typ)

	knd := value.Kind() // struct
	fmt.Println(knd)
	
	for i := 0; i < value.NumField(); i++ {
		fmt.Printf("Field %d: %v\n", i, value.Field(i))
		//value.Field(i).SetString("C#")
	}
	
	results := value.Method(0).Call(nil)
	fmt.Println(results) // [Ada - Go - Oberon]
}

 10. 练习,通过反射操作结构体

package main

import (
	"fmt"
	“reflect"
)

type NotknownType struct {
	s1 string
	s2 string
	s3 string
}
func (n NotknownType) String() string {
	return n.s1 + "-" + n.s2 + "-" + n.s3
}
var secret interface{} = NotknownType{"Ada", "Go", "Oberon"}

func main() {
	value := reflect.ValueOf(secret) // <main.NotknownType Value>
	typ := reflect.TypeOf(secret)    // main.NotknownType
	fmt.Println(typ)

	knd := value.Kind() // struct
	fmt.Println(knd)
	
	for i := 0; i < value.NumField(); i++ {
		fmt.Printf("Field %d: %v\n", i, value.Field(i))
		//value.Field(i).SetString("C#")
	}
	
	results := value.Method(0).Call(nil)
	fmt.Println(results) // [Ada - Go - Oberon]
}

 10. 练习2,通过反射修改结构体

package main

import (
	"fmt"
	"reflect"
)

type T struct {
	A int
	B string
}

func main() {
	t := T{23, "skidoo"}
	s := reflect.ValueOf(&t).Elem()
	typeOfT := s.Type()
	for i := 0; i < s.NumField(); i++ {
		f := s.Field(i)
		fmt.Printf("%d: %s %s = %v\n", i,
			typeOfT.Field(i).Name, f.Type(), f.Interface())
	}
	s.Field(0).SetInt(77)
	s.Field(1).SetString("Sunset Strip")
	fmt.Println("t is now", t)
}

 exp:

package main

import (
	"encoding/json"
	"fmt"
	"reflect"
)

type Student struct {
	Name  string `json:"student_name"`
	Age   int
	Score float32
	Sex   string
}

func (s Student) Print() {
	fmt.Println("---start----")
	fmt.Println(s)
	fmt.Println("---end----")
}

func (s Student) Set(name string, age int, score float32, sex string) {

	s.Name = name
	s.Age = age
	s.Score = score
	s.Sex = sex
}

func TestStruct(a interface{}) {
	tye := reflect.TypeOf(a)
	val := reflect.ValueOf(a)
	kd := val.Kind()
	if kd != reflect.Ptr && val.Elem().Kind() == reflect.Struct {
		fmt.Println("expect struct")
		return
	}

	num := val.Elem().NumField()
	val.Elem().Field(0).SetString("stu1000")
	for i := 0; i < num; i++ {
		fmt.Printf("%d %v\n", i, val.Elem().Field(i).Kind())
	}

	fmt.Printf("struct has %d fields\n", num)

	tag := tye.Elem().Field(0).Tag.Get("json")
	fmt.Printf("tag=%s\n", tag)

	numOfMethod := val.Elem().NumMethod()
	fmt.Printf("struct has %d methods\n", numOfMethod)
	var params []reflect.Value
	val.Elem().Method(0).Call(params)
}

func main() {
	var a Student = Student{
		Name:  "stu01",
		Age:   18,
		Score: 92.8,
	}

	result, _ := json.Marshal(a)
	fmt.Println("json result:", string(result))

	TestStruct(&a)
	fmt.Println(a)
}

 

posted @ 2020-06-26 13:06  Dylan123  阅读(154)  评论(0)    收藏  举报