Go-day06
今日内容概要:
1.interface接口
2.反射
一、接口
接口定义
1.Interface类型可以定义一组方法,当时不需要实现,并且interface不能包含任何变量
2.接口定义
type example interface{
Method1(参数列表) 返回值列表
Method2(参数列表) 返回值列表
…
}
/*
例子:
*/
type Student interface{
call()
say() string
}
3.interface类型默认是一个指针
type example interface{
Method1(参数列表) 返回值列表
Method2(参数列表) 返回值列表
…
}
var a example
a.Method1()
/*
没有实现method方法会panic
*/
4.接口的实现
1. Golang中的接口,不需要显示的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,golang中没有implement类似的关键字
2. 如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口。
3. 如果一个变量只含有了1个interface的方部分方法,那么这个变量没有实现这个接口。
package main
//定义了一个车的接口,满足run,getname,didi就实现了该方法.
import "fmt" type Carter interface {
Run()
GetName() string
Didi()
} type BMW struct {
name string
} func (p *BMW) Run(){
fmt.Println("this bmw is running")
} func(p *BMW) GetName() string{
return p.name
} func (p *BMW) Didi() {
fmt.Println("this bmw is didi")
} func main() {
var car Carter
isBmw := new(BMW)
isBmw.name = "liangliang"
car = isBmw //将结构体赋值给接口,之后都通过接口调用
car.Run()
res := car.GetName()
fmt.Println(res) }
多态
一种事物的多种形态,都可以按照统一的接口进行操作
接口嵌套
一个接口可以嵌套在另外的接口上
package main
import "fmt"
type Writer interface {
Write()
}
type Reader interface {
Read()
}
type WrintReader interface {
//此接口类似于继承,只有都实现write和read方法才行
Writer
Reader
}
type file struct {
}
func (p *file) Read(){
fmt.Println("is read")
}
func(p *file) Write(){
fmt.Println("is write")
}
func Test(rw WrintReader){
rw.Read()
rw.Write()
}
func main() {
var f file //声明了一个结构体
Test(&f)
}
/*
is read
is write
*/
类型断言
类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型可以采用以下方法进行转换
//第一种
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,带检查
package main
import "fmt"
type Student struct {
name string
age int
}
func Test(a interface{}){
v,ok := a.(Student) ; if ok{ //接口断言判断
//v += 3
fmt.Println(v)
}else{
fmt.Println("convert error")
}
//b := a.(int) //接口断言
//b += 3
//fmt.Println(b)
}
func main() {
var b Student
Test(b)
}
/*
{ 0}
*/
练习:写一个函数判断传入参数的类型
package main
import "fmt"
type Student struct {
name string
age int
}
func just(a ...interface{}){ //一个interface接口的切片
for index,v := range a{
switch v.(type) {
case int,int32,int64:
fmt.Printf("this index is %d,this value is %v,this type is int\n",index,v)
case string:
fmt.Printf("this index is %d,this type is %v,this type is string\n",index,v)
case float32,float64:
fmt.Printf("this index is %d,this type is %v,this type is float\n",index,v)
case bool:
fmt.Printf("this index is %d,this type is %v,this type is bool\n",index,v)
case Student:
fmt.Printf("this index is %d,this type is %v,this type is student\n",index,v)
case *Student:
fmt.Printf("this index is %d,this type is %v,this type is *student\n",index,v)
}
}
}
func main() {
var stu = Student{name:"ake",age:18}
just("hello",9.9,200,true,stu,&stu)
}
/*
this index is 0,this type is hello,this type is string
this index is 1,this type is 9.9,this type is float
this index is 2,this value is 200,this type is int
this index is 3,this type is true,this type is bool
this index is 4,this type is {ake 18},this type is student
this index is 5,this type is &{ake 18},this type is *student
*/
类型断言 采用type-switch
switch t := areaIntf.(type) //areaIntf是结构体
{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)
}
空接口 interface{}
空接口没有任何方法,所有类型都实现了空接口
package main
import "fmt"
func main() {
var a int
var b interface{}
b = a
fmt.Println(b)
}
判断变量是否实现了指定接口
package main
import "fmt" type Stringer interface {
String() string
} func main() {
var m interface{}
if v,ok := m.(Stringer); ok {
fmt.Printf("v implements String(): %s\n", v.String());
}
}
变量slice和接口slice之前的赋值操作. 不能够直接赋值,需要通过for_range赋值
错误示例:
var a []int
var b []interface{}
b = a //错误示例
反射
1.反射:可以在运行时动态获取变量的相关信息
import reflect
2.
a.reflect.TypeOf,获取变量类型,返回reflect.Type类型
b.reflect.ValueOf,获取变量值,返回reflect.Value类型
c.reflect.Value.Kind,获取变量类别,返回一个常量
d.reflect.Value.Interface(),转换成interface{}类型

3.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
)
package main import (
"fmt"
"reflect"
) func main() {
var x float64 = 2.3
fmt.Println(reflect.TypeOf(x))
v := reflect.ValueOf(x)
fmt.Println(v)
fmt.Println(v.Kind())
fmt.Println(v.Type())
fmt.Println(v.Float()) //取值
//通过反射value,可以转换为接口,可以转换成值类
fmt.Println(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(),设置字符串
容易出问题的case
package main import (
"fmt"
"reflect"
) func main() {
var x float64 = 2.2
//fv := reflect.ValueOf(x) 传入的a为值类型,修改不生效,panic: reflect: reflect.Value.SetFloat using unaddressable value
fv := reflect.ValueOf(&x) //传入为内存地址,修改的时候需要Elem()
fv.Elem().SetFloat(3.3)
fmt.Printf("%v\n",x) }
反射例子:
package main import (
"reflect"
"fmt"
) type Student struct{
Name string
Age int
Sex int
}
func(s *Student) Set(name string,age,sex int){
s.Name = name
s.Age = age
s.Sex = sex
}
func(s *Student) Getname(name string){
s.Name = name
} func TestStruct_value(){
var s *Student = &Student{}
v := reflect.ValueOf(s) //reflect.Value类型
setinfo := v.MethodByName("Set") //通过reflect反射结构体Set方法
var par []reflect.Value
name := "dragon"
age := 18
sex := 1
par = append(par,reflect.ValueOf(name))
par = append(par,reflect.ValueOf(age))
par = append(par,reflect.ValueOf(sex))
setinfo.Call(par)
fmt.Printf("%v\n",s)
} func main() {
TestStruct_value()
} /*
&{dragon 18 1}
*/
用反射操作结构体
a. reflect.Value.NumField()获取结构体中字段的个数
b. reflect.Value.Method(n).Call来调用结构体中的方法
c. reflect.Value.MethodByName(方法名字) 获取结构体方法 可以直接.Call执行该方法
练习:
通过反射操作结构体
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]
} /*
Ada-Go-Oberon
main.NotknownType
struct
Field 0: Ada
Field 1: Go
Field 2: Oberon
[Ada-Go-Oberon] */
通过反射修改结构体
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)
} /*
0: A int = 23
1: B string = skidoo
t is now {77 Sunset Strip}
*/
interface实现一个可以接收任意参数的链表:
package main
import "fmt"
type LinkNode struct {
data interface{}
next *LinkNode //定义一个链表节点的结构体
}
type Link struct { //定义一个链表结构体
head *LinkNode
tail *LinkNode
}
func (p *Link) InsertChain(data interface{}){
node := &LinkNode{
data : data,
next:nil,
}
if p.tail == nil && p.head == nil{
p.tail = node
p.head = node
return
}
node.next = p.head //最好画图理解容易
p.head = node
}
func (p *Link) TailChain(data interface{}){
node := &LinkNode{
data : data,
next:nil,
}
if p.tail == nil && p.head == nil{
p.tail = node
p.head = node
return
}
p.tail.next = node
p.tail = node
}
func (p *Link) Trans(){
//从头到尾遍历
q := p.head
for q != nil{
fmt.Println(q.data)
q = q.next
}
}
func main() {
var link Link
for i:=0 ; i < 10 ; i++ {
//link.InsertChain(i)
link.TailChain(i)
}
link.Trans()
}
通过interface实现sort排序
package main import (
"fmt"
"math/rand"
"sort"
) type Student struct {
name string
age int
id int
} //想使用sort必须实现三种方法,Len,Less,Swap
type StudentArry []Student func (p StudentArry) Len() int{
return len(p)
} func (p StudentArry) Less(i , j int ) bool{
return p[i].name < p[j].name
} func(p StudentArry) Swap(i,j int){
p[i], p[j] = p[j] , p[i]
} func main() {
var stus StudentArry
for i :=0 ; i < 10 ; i++ {
stu := Student{
name:fmt.Sprintf("stu%d",rand.Intn(100)),
age : rand.Intn(100),
id : rand.Intn(100),
}
stus = append(stus,stu)
} for _,v := range stus{
fmt.Println(v.name,v.age,v.id)
} sort.Sort(stus) fmt.Println("--------------") for _,v := range stus{
fmt.Println(v.name,v.age,v.id)
} } /*
stu81 87 47
stu59 81 18
stu25 40 56
stu0 94 11
stu62 89 28
stu74 11 45
stu37 6 95
stu66 28 58
stu47 47 87
stu88 90 15
--------------
stu0 94 11
stu25 40 56
stu37 6 95
stu47 47 87
stu59 81 18
stu62 89 28
stu66 28 58
stu74 11 45
stu81 87 47
stu88 90 15 */
Go-day06的更多相关文章
- day06 Request Response
rw 读写模板的设置 day05 Request Response 1. HttpServletResponse 简介 1.1 Response 的 OutputStream 输出中文的问题 1.2 ...
- python day06笔记总结
2019.4.3 S21 day06笔记总结 一.昨日内容补充 1.列表独有功能: 1.revers 反转 例:v1 = [1,2,4,88,2] v1.revers() print(v1) 2.so ...
- Python基础(正则、序列化、常用模块和面向对象)-day06
写在前面 上课第六天,打卡: 天地不仁,以万物为刍狗: 一.正则 - 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法: - 在线正则工具:http://tool ...
- Day06 DOM4J&schema介绍&xPath
day06总结 今日内容 XML解析之JAXP( SAX ) DOM4J Schema 三.XML解析器介绍 操作XML文档概述 1 如何操作XML文档 XML文档也是数据的一种,对数据的 ...
- python开发学习-day06(模块拾忆、面向对象)
s12-20160130-day06 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...
- 2017-2018-1 JAVA实验站 冲刺 day06
2017-2018-1 JAVA实验站 冲刺 day06 各个成员今日完成的任务 小组成员 今日工作 完成进度 张韵琪 进行工作总结.博客.小组成员头像 100% 齐力锋 找背按钮声音 100% 张浩 ...
- C++Primer笔记-----day06
================================================================day06=============================== ...
- day06 - Python - 面向对象
本节内容: 引子 面向对象 v.s. 面向过程 面向对象编程介绍 面向对象的特性: 封装 继承 多态 类.方法 1.引子 假设你现在是一家游戏公司的开发人员,现 ...
- 记录我的 python 学习历程-Day06 is id == / 代码块 / 集合 / 深浅拷贝
一.is == id 用法 在Python中,id是内存地址, 你只要创建一个数据(对象)那么就会在内存中开辟一个空间,将这个数据临时加载到内存中,这个空间有一个唯一标识,就好比是身份证号,标识这个空 ...
- day06——小数据池、深浅拷贝、集合
day06 小数据池 小数据池--缓存机制(驻留机制),只是一种规格,不会实际的开辟一个空间 == 判断两边内容是否相等 ***** # a = 10 # b = 10 # print(a == b) ...
随机推荐
- 配置 BizTalk Server
使用“基本配置”或“自定义配置”配置 BizTalk Server. 基本配置与自定义配置 如果配置使用域组,则进行“自定义配置”. 如果配置使用自定义组名称而不是默认组名称,则进行“自定 ...
- bzoj4152-[AMPPZ2014]The_Captain
Description 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. Input 第一行包含一个正整数n(2 ...
- 从身份证号码中获取性别、出生日期、籍贯,并更新mongodb
有这样的需求,人员信息是存在mongodb中,需要存放人员的身份证.性别.出生日期.籍贯等信息.通过脚本导入这些信息,但是只导入了身份证号码,其他信息空缺.现在需要补全其他信息. 其实身份证信息就包含 ...
- kubernetes ceph-rbd挂载步骤 类型storageClass
由于kubelet本身并不支持rbd的命令,所以需要添加一个kube系统插件: 下载插件 quay.io/external_storage/rbd-provisioner 下载地址: https:// ...
- Spring MVC启动过程(1):ContextLoaderListener初始化
此文来自https://my.oschina.net/pkpk1234/blog/61971 (写的特别好)故引来借鉴 Spring MVC启动过程 以Tomcat为例,想在Web容器中使用Spirn ...
- BZOJ2212 [POI2011] Tree Rotations 【treap】
题目分析: 写的无旋treap应该跑不过,但bzoj判断的总时限.把相关实现改成线段树合并就可以了. 代码: #include<bits/stdc++.h> using namespace ...
- 洛谷P2045 K方格取数(算竞进阶习题)
费用流 又是一道网络流的模型,对于这种费用与经过次数有关的边,我们经常把边拆成多条,比如这个题,第一次费用是x,第二次是0,我们就可以先把点拆成入点和出点,入点和出点又连两条边,第一条容量为1,费用为 ...
- 基于 __new__ 方法的单例模式
单例模式定义 首次实例化创建实例化对象 之后的每次实例化都用最初的实例化对象 即单实例模式 __new__ 的原理 __new__ 方法可以在 __init__ 方法执行 这样可以在初始化之前进行一系 ...
- MT【300】余弦的三倍角公式
2017清华大学THUSSAT附加学科测试数学(二测)$\cos^5\dfrac{\pi}{9}+\cos^5\dfrac{5\pi}{9}+\cos^5\dfrac{7\pi}{9}$ 的值为___ ...
- 「CF838B」 Diverging Directions
B. Diverging Directions 题意 给出一个n个点2n-2条边的有向图.n-1条指向远离根方向的边形成一棵树,还有n-1条从非根节点指向根节点的边. q次操作,1修改第x条边权值为y ...