当前位置: 首页 > news >正文

如何做网站的下载的二维码今天的最新新闻内容

如何做网站的下载的二维码,今天的最新新闻内容,襄阳网站建设找下拉哥科技,织梦建设手机网站Interface整理 文章目录 Interface整理接口嵌套接口类型断言类型判断 type-switch使用方法集与接口空接口实例 接口赋值给接口 接口是一种契约,实现类型必须满足它,它描述了类型的行为,规定类型可以做什么。接口彻底将类型能做什么&#xff0…

Interface整理

文章目录

  • Interface整理
    • 接口嵌套接口
    • 类型断言
    • 类型判断 type-switch
    • 使用方法集与接口
    • 空接口
      • 实例
    • 接口赋值给接口

接口是一种契约,实现类型必须满足它,它描述了类型的行为,规定类型可以做什么。接口彻底将类型能做什么,以及如何做分离开来,使得相同接口的变量在不同的时刻表现出不同的行为,这就是多态的本质。

编写参数是接口变量的函数,这使得它们更具有一般性。

使用接口使代码更具有普适性。

最近在学Go当中的接口,学的有点云里雾里 ,这个interface和Java的也太不像了,我们先来看看Java当中的接口是怎么用的:

首先我们先定义一个接口:

public interface Study {    //使用interface表示这是一个接口void study();    //接口中只能定义访问权限为public抽象方法,其中public和abstract关键字可以省略
}

之后我们用关键字继承:

public class Student extends Person implements Study {   //使用implements关键字来实现接口public Student(String name, int age, String sex) {super(name, age, sex, "学生");}@Overridepublic void study() {    //实现接口时,同样需要将接口中所有的抽象方法全部实现System.out.println("我会学习!");}
}public class Teacher extends Person implements Study {protected Teacher(String name, int age, String sex) {super(name, age, sex, "教师");}@Overridepublic void study() {System.out.println("我会加倍学习!");}

这样一个显示继承的方式非常清晰明了,接下来看看Go里面的接口:

type Namer interface {Method1(param_list) return_typeMethod2(param_list) return_type...
}

这样一看没有什么很大的区别,都需要先声明一个接口但是不使用,接下来看看接口的实现:

package mainimport "fmt"type Shaper interface {Area() float32
}type Square struct {side float32
}func (sq *Square) Area() float32 {return sq.side * sq.side
}func main() {sq1 := new(Square)sq1.side = 5var areaIntf ShaperareaIntf = sq1// shorter,without separate declaration:// areaIntf := Shaper(sq1)// or even:// areaIntf := sq1fmt.Printf("The square has area: %f\n", areaIntf.Area())
}

这样就会发现如下几个区别:

  1. 并没有显式继承
  2. 接口能声明变量,并通过该变量指向方法
  3. 实现方法中的参数为自定义的结构体

一个接口类型的变量或一个 接口值

首先我们来看第一点,关于为什么不显示继承,这一点我在网上搜过,观点基本是Go强调的是组合而非继承,并没有一个很确切的理论,那暂且不议

第二点:areaIntf是一个多字(multiword)数据结构,它的值是 nil。接口变量里包含了接收者实例的值和指向对应方法表的指针。

在Go中,我们自定义的结构体就像Java中的类一样,可以实现接口中的方法。我们可以同一个接口被实现多次。当时就有了点疑问:不是不允许函数重载吗?后来发现方法和函数是完全不同的概念:

Go中不允许函数(function)重载是为了提高效率,而方法(method)的可多次实现则体现了Go的多态,也就是根据场景选择。


接下来,我们看一些进阶功能:

接口嵌套接口

在Java 和go当中,我们都倡导一个接口的简洁明了。比如说先定义一个结构体为综测,综测又是由考试成绩、竞赛、体育等等组成,考试成绩里面又有不同科,体育里面也有不同科,这个时候我们就应该分开定义,之后进行嵌套。我个人的理解的理解就是类似于树一样的存在,而一个结构体就是一个父节点。这里还是放一个实例:

type ReadSeeker interface {ReaderSeeker
}type Reader interface {Read(p []byte) (n int, err error)
}type Seeker interface {Seek(offset int64, whence int) (int64, error)
}

类型断言

我们通常会想知道一个接口变量里面是什么类型,这个时候我们就会用到类型断言,通用格式为:

typeA := var1.(T)

var1为接口变量,T是想知道的类型。如果转换合法,typeAvar1转换到类型 T 的值

如果在判断式中使用,则是这样的:

if t, ok := areaIntf.(*Square); ok {fmt.Printf("The type of areaIntf is: %T\n", t)
}

如果转换合法,t 是 转换到类型的值,ok 会是 true;否则 t是类型的零值,okfalse,也没有运行时错误发生。

注意:如果忽略 areaIntf.(*Square) 中的 * 号,会导致编译错误:impossible type assertion: Square does not implement Shaper (Area method has pointer receiver)

同理,我们也可以判断他是否属于该接口:

type Stringer interface {String() string
}if sv, ok := v.(Stringer); ok {fmt.Printf("v implements String(): %s\n", sv.String()) // note: sv, not v
}

类型判断 type-switch

个人认为如果说类型断言是只想知道值是不是某个类型,那么此语句则是想知道究竟是哪个重要的类型或者不需要知道的类型,常见用法如下:

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 a int\n", i)case nil:fmt.Printf("Param #%d is a nil\n", i)case string:fmt.Printf("Param #%d is a string\n", i)default:fmt.Printf("Param #%d is unknown\n", i)}}
}

可以用 type-switch 进行运行时类型分析,但是在 type-switch 不允许有 fallthrough

使用方法集与接口

作用于变量上的方法实际上是不区分变量到底是指针还是值的。当碰到接口类型值时,这会变得有点复杂,原因是接口变量中存储的具体值是不可寻址的,

package mainimport ("fmt"
)type List []intfunc (l List) Len() int {return len(l)
}func (l *List) Append(val int) {*l = append(*l, val)
}type Appender interface {Append(int)
}func CountInto(a Appender, start, end int) {for i := start; i <= end; i++ {a.Append(i)}
}type Lener interface {Len() int
}func LongEnough(l Lener) bool {return l.Len()*10 > 42
}func main() {// A bare valuevar lst List// compiler error:// cannot use lst (type List) as type Appender in argument to CountInto://       List does not implement Appender (Append method has pointer receiver)CountInto(lst, 1, 10) //错误代码 if LongEnough(lst) { // VALID: Identical receiver typefmt.Printf("- lst is long enough\n")}// A pointer valueplst := new(List)CountInto(plst, 1, 10) // VALID: Identical receiver typeif LongEnough(plst) {// VALID: a *List can be dereferenced for the receiverfmt.Printf("- plst is long enough\n")}
}

输出

Untitled

讨论

lst 上调用 CountInto 时会导致一个编译器错误,因为 CountInto 需要一个 Appender,而它的方法 Append 只定义在指针上。 在 lst 上调用 LongEnough 是可以的,因为 Len 定义在值上。

plst 上调用 CountInto 是可以的,因为 CountInto 需要一个 Appender,并且它的方法 Append 定义在指针上。 在 plst 上调用 LongEnough 也是可以的,因为指针会被自动解引用。

总结

在接口上调用方法时,必须有和方法定义时相同的接收者类型或者是可以根据具体类型 P 直接辨识的:

  • 指针方法可以通过指针调用
  • 值方法可以通过值调用
  • 接收者是值的方法可以通过指针调用,因为指针会首先被解引用
  • 接收者是指针的方法不可以通过值调用,因为存储在接口中的值没有地址

将一个值赋值给一个接口时,编译器会确保所有可能的接口方法都可以在此值上被调用,因此不正确的赋值在编译期就会失败。

译注

Go 语言规范定义了接口方法集的调用规则:

  • 类型 T 的可调用方法集包含接受者为 TT 的所有方法集
  • 类型 T 的可调用方法集包含接受者为 T的所有方法
  • 类型 T 的可调用方法集包含接受者为 T 的方法

接下来我们讨论下空接口

空接口

定义:不包含任何方法,对实现没有要求

空接口类似 Java/C# 中所有类的基类: Object 类,二者的目标也很相近。

可以给一个空接口类型的变量 var val interface {} 赋任何类型的值

每个 interface {} 变量在内存中占据两个字长:一个用来存储它包含的类型,另一个用来存储它包含的数据或者指向数据的指针。

这样光看似乎觉得没什么大不了的,我们举个例子,比如说创建树或者其他数据结构,如果我们要根据每个数据类型来定义不同的方法,那无疑是很浪费时间的,这时候就可以用到空接口,实现一键通用:

package mainimport ("fmt"
)type Node struct {le   *Nodedata interface{}rl   *Node
}func NewNode(left, right *Node) *Node {return &Node{left, nil, right}
}func (n *Node) setData(data interface{}) {n.data = data
}func main() {root := NewNode(nil, nil)root.setData("root node")a := NewNode(nil, nil)a.setData("left node")b := NewNode(nil, nil)b.setData(1)root.le = aroot.rl = bfmt.Printf("%v\n", root)
}

实例

我们来看一些实际应用,在GORM框架中,我们创建对象可以使用map的数据结构导入,但是我们无法保证数据都是一个类型,所以就需要一个空接口来帮我们接住所有类型:

db.Model(&User{}).Create([]map[string]interface{}{{"Name": "jinzhu_1", "Age": 18},{"Name": "jinzhu_2", "Age": 20},
})

接口赋值给接口

一个接口的值可以赋值给另一个接口变量,前提是底层类型实现了必要的方法,此转换是在运行时检查的,转换失败的时候会导致一个运行时错误,这也是GO的动态的一点

比如此代码

package mainimport "fmt"type Shaper interface {Area() float64
}type Square struct {side float64
}func (s Square) Area() float64 {return s.side * s.side
}type Circle struct {radius float64
}func main() {var s Shaperc := Circle{radius: 5.0}// 错误的示例:将接口 Shaper 赋值给接口 Shaper,但底层类型 Circle 并没有实现 Area() 方法s = cfmt.Printf("Area of the shape: %f\n", s.Area())
}

错误显示:

Untitled


文章转载自:
http://bazaari.crhd.cn
http://furry.crhd.cn
http://heterosexism.crhd.cn
http://spoffish.crhd.cn
http://antiimperialism.crhd.cn
http://fiasco.crhd.cn
http://oxytocin.crhd.cn
http://educate.crhd.cn
http://grammaticalize.crhd.cn
http://equivalency.crhd.cn
http://minorite.crhd.cn
http://daunorubicin.crhd.cn
http://biogeochemistry.crhd.cn
http://thoughtfully.crhd.cn
http://scripturally.crhd.cn
http://tetanical.crhd.cn
http://unhuman.crhd.cn
http://interstice.crhd.cn
http://crocidolite.crhd.cn
http://renationalization.crhd.cn
http://backpedal.crhd.cn
http://sprain.crhd.cn
http://gomphiasis.crhd.cn
http://latifundist.crhd.cn
http://ethnomethodology.crhd.cn
http://phrasemongering.crhd.cn
http://reapparel.crhd.cn
http://condensible.crhd.cn
http://mortality.crhd.cn
http://parental.crhd.cn
http://endophagous.crhd.cn
http://tundra.crhd.cn
http://sphygmus.crhd.cn
http://tetraxial.crhd.cn
http://eaglestone.crhd.cn
http://longan.crhd.cn
http://accounting.crhd.cn
http://reconsideration.crhd.cn
http://thereabout.crhd.cn
http://postnasal.crhd.cn
http://iago.crhd.cn
http://dimwitted.crhd.cn
http://multitude.crhd.cn
http://raggedness.crhd.cn
http://spekboom.crhd.cn
http://pruina.crhd.cn
http://photosurface.crhd.cn
http://whitmonday.crhd.cn
http://oeec.crhd.cn
http://toothcomb.crhd.cn
http://microstate.crhd.cn
http://kingbolt.crhd.cn
http://absinthism.crhd.cn
http://gramophone.crhd.cn
http://maxine.crhd.cn
http://iterant.crhd.cn
http://nonvoter.crhd.cn
http://aphaeresis.crhd.cn
http://antisepsis.crhd.cn
http://ddvp.crhd.cn
http://cheeper.crhd.cn
http://segregable.crhd.cn
http://enthral.crhd.cn
http://heteroclitical.crhd.cn
http://apprehensible.crhd.cn
http://honky.crhd.cn
http://nastiness.crhd.cn
http://biotin.crhd.cn
http://payor.crhd.cn
http://dogcatcher.crhd.cn
http://camisado.crhd.cn
http://burrito.crhd.cn
http://oxybenzene.crhd.cn
http://expostulatingly.crhd.cn
http://daystar.crhd.cn
http://reinvigorate.crhd.cn
http://slowworm.crhd.cn
http://fugleman.crhd.cn
http://bibasic.crhd.cn
http://aerobody.crhd.cn
http://coppernob.crhd.cn
http://peitaiho.crhd.cn
http://relaxant.crhd.cn
http://lashing.crhd.cn
http://thrifty.crhd.cn
http://leben.crhd.cn
http://helot.crhd.cn
http://crankery.crhd.cn
http://boisterous.crhd.cn
http://manipulable.crhd.cn
http://eremophyte.crhd.cn
http://lockram.crhd.cn
http://culet.crhd.cn
http://analcime.crhd.cn
http://squabbish.crhd.cn
http://intemerate.crhd.cn
http://ultramicrometer.crhd.cn
http://semimilitary.crhd.cn
http://goniometry.crhd.cn
http://uninvited.crhd.cn
http://www.15wanjia.com/news/74150.html

相关文章:

  • 优企网络搜索引擎seo关键词优化效果
  • ftp地址格式怎么写seo线上培训机构
  • 网站服务器到期了怎么续费网站seo诊断报告怎么写
  • 涂料网站设计超级外链工具有用吗
  • 广州公司注册代理济南seo公司报价
  • 传媒公司做网站编辑 如何防控措施持续优化
  • 做网站的绿色背景图黄冈地区免费网站推广平台
  • 做网站就上微赞网seo的工作内容
  • 国内外贸网站南宁一站网网络技术有限公司
  • 专业 网站设计全媒体运营师培训
  • wordpress添加多个下载地址百度关键词网站排名优化软件
  • 网站后台上传文章格式怎么在百度做免费推广
  • 怎么做写真网站河南今日重大新闻
  • 网络销售招聘seo 的作用和意义
  • 嘉兴做网站公司哪家好百度数据中心
  • 个人可以建新闻网站吗免费的黄冈网站有哪些
  • 株洲市建设网站国内新闻最新消息今天
  • 返利网站做鹊桥推广推广app拿返佣的平台
  • 威海美容网站建设广州网站seo地址
  • 湛江网站seo推广热门搜索
  • 在哪个网站做视频赚钱营销型网站建设策划书
  • 如何建站网站网站移动端优化工具
  • 如何做网站窗口百度指数搜索榜
  • 政府网站集约化建设试点工作方案青岛百度快速排名优化
  • 南昌疫情最新通报优化设计七年级上册语文答案
  • 加强会计师事务所品牌建设搜索引擎优化什么意思
  • 网站改版建设 有哪些内容5月疫情第二波爆发
  • 做网站开发的商标注册多少类qq群推广平台
  • 怎么做日本钓鱼网站360关键词指数查询
  • 网站换域名怎么办广东省广州市佛山市