golang的接口快把我给整疯了。

小洛北 2019-12-18 10:03:34
有点编程基础的我自学了一段时间go语言了,一直止步在接口这一块,知道接口的基本用法,在本包里可以灵活使用接口,但是外包使用另外一个包的接口时我真的就懵圈了,根本不知道哪个结构体实现了哪个接口,还有两个不是同包接口和结构体之间的赋值这一块真的快整疯我了,天天上语数英课啥也不听,就自己一个人自学go,学了这么多天感觉也没领悟接口这一块,这个隐式实现真的太难了,根本不知道谁实现了谁?谁可以赋值给谁?现在最经典的io包下边的writer接口和reader接口我都没搞明白,看讲师讲的都太浅,就只讲本包使用本包的接口和赋值,外包的就不讲,一个外包(http包)接口类型和结构体之间的赋值一下子我就懵圈了,自学真的太难了,我都快撑不住了,这几天一直专注接口这一块的学习,但是没太大的进展,都说go的接口是go最妙的特性,但我为啥觉得go的接口并没有那么神,特别是这个隐式声明,真的搞不懂谁实现了谁?大佬们可否给小弟指点迷津?小弟真的洗耳恭听,感激不尽。
...全文
642 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
wuxingren888 2019-12-23
  • 打赏
  • 举报
回复
引用 5 楼 CSDN首席执行官的回复:
[quote=引用 1 楼 qybao的回复:]接口是一种“规范”,也就是接口的实现类都要遵循这个“规范”,假如这个“规范”体现在接口的方法上,那么所有的接口实现类都要实现该接口方法(遵循“规范”,和接口一致,即接口有什么动作,实现类也有什么动作)。那么好了,如果有一个类,它封装的方法恰好和接口定义的方法一致,也就是说它无形中遵循了接口的“规范”,所以它隐形的成了接口的实现类

打个比方,某工厂的一批零件有个生产指标,比如直径为10cm(可以理解为有个接口方法),那么在这个工厂里生产的零件都符合这个指标,也就是都符合这个接口,因为在该工厂生产的,所以显示地遵循了标准(也就是显示实现接口)。那么好了,另一家工厂也生产一种零件,刚好直径也是10cm(可以理解为有个方法和接口方法一样)。假如我么第一家工厂生产的零件坏了,我们要找一个零件代替,我们发现另一家工厂的零件刚好也是10cm(也有同样的接口方法),也符合第一家工厂的生产指标,所以也可以拿来代替使用。你会发现,另一家工厂没有特意去遵循第一个工厂的指标(没有显示implement),但事实上却隐式的遵循的指标,也就是说另一家工厂的零件,隐式地实现了第一家工厂的接口,所以它也和第一家工厂生产的零件一样,能应用在相同的场合。
谢谢大佬,我自己定义的接口和结构体之间的使用我还是能搞明白的,(接口的规则我懂了)但是标准库里边的我就有点搞不懂了,比如 Readall( io reader) Readall方法接收一个实现了io reader接口的参数,但是下边的例子file怎么就变成就实现io reader接口的参数了?os. Open后返回的应该是os. Open类型的变量,我怎么知道和确定file实现了io reader接口?讲真的,我是真的看不出来file这个变量能跟io reader接口有半毛钱关系,大佬拜托您指点。 func main() { file, _ := os.Open("test") b, _ := ioutil.ReadAll(file) fmt.Println(string(b)) }[/quote] 虽然没学过golang 但是标准库是人家写的,返回什么人家决定的。这个是需要记的。reader接口也只是file结构体的方法集合,提前写好的一些方法,也可以用自己的结构体来继承这些方法。在rust中管这些叫trait
小洛北 2019-12-23
  • 打赏
  • 举报
回复
引用 43 楼 wuxingren888的回复:
[quote=引用 5 楼 CSDN首席执行官的回复:][quote=引用 1 楼 qybao的回复:]接口是一种“规范”,也就是接口的实现类都要遵循这个“规范”,假如这个“规范”体现在接口的方法上,那么所有的接口实现类都要实现该接口方法(遵循“规范”,和接口一致,即接口有什么动作,实现类也有什么动作)。那么好了,如果有一个类,它封装的方法恰好和接口定义的方法一致,也就是说它无形中遵循了接口的“规范”,所以它隐形的成了接口的实现类

打个比方,某工厂的一批零件有个生产指标,比如直径为10cm(可以理解为有个接口方法),那么在这个工厂里生产的零件都符合这个指标,也就是都符合这个接口,因为在该工厂生产的,所以显示地遵循了标准(也就是显示实现接口)。那么好了,另一家工厂也生产一种零件,刚好直径也是10cm(可以理解为有个方法和接口方法一样)。假如我么第一家工厂生产的零件坏了,我们要找一个零件代替,我们发现另一家工厂的零件刚好也是10cm(也有同样的接口方法),也符合第一家工厂的生产指标,所以也可以拿来代替使用。你会发现,另一家工厂没有特意去遵循第一个工厂的指标(没有显示implement),但事实上却隐式的遵循的指标,也就是说另一家工厂的零件,隐式地实现了第一家工厂的接口,所以它也和第一家工厂生产的零件一样,能应用在相同的场合。
谢谢大佬,我自己定义的接口和结构体之间的使用我还是能搞明白的,(接口的规则我懂了)但是标准库里边的我就有点搞不懂了,比如 Readall( io reader) Readall方法接收一个实现了io reader接口的参数,但是下边的例子file怎么就变成就实现io reader接口的参数了?os. Open后返回的应该是os. Open类型的变量,我怎么知道和确定file实现了io reader接口?讲真的,我是真的看不出来file这个变量能跟io reader接口有半毛钱关系,大佬拜托您指点。 func main() { file, _ := os.Open("test") b, _ := ioutil.ReadAll(file) fmt.Println(string(b)) }[/quote] 虽然没学过golang 但是标准库是人家写的,返回什么人家决定的。这个是需要记的。reader接口也只是file结构体的方法集合,提前写好的一些方法,也可以用自己的结构体来继承这些方法。在rust中管这些叫trait[/quote] 好的 , 多谢大佬指教
小洛北 2019-12-23
  • 打赏
  • 举报
回复
引用 43 楼 wuxingren888的回复:
[quote=引用 5 楼 CSDN首席执行官的回复:][quote=引用 1 楼 qybao的回复:]接口是一种“规范”,也就是接口的实现类都要遵循这个“规范”,假如这个“规范”体现在接口的方法上,那么所有的接口实现类都要实现该接口方法(遵循“规范”,和接口一致,即接口有什么动作,实现类也有什么动作)。那么好了,如果有一个类,它封装的方法恰好和接口定义的方法一致,也就是说它无形中遵循了接口的“规范”,所以它隐形的成了接口的实现类

打个比方,某工厂的一批零件有个生产指标,比如直径为10cm(可以理解为有个接口方法),那么在这个工厂里生产的零件都符合这个指标,也就是都符合这个接口,因为在该工厂生产的,所以显示地遵循了标准(也就是显示实现接口)。那么好了,另一家工厂也生产一种零件,刚好直径也是10cm(可以理解为有个方法和接口方法一样)。假如我么第一家工厂生产的零件坏了,我们要找一个零件代替,我们发现另一家工厂的零件刚好也是10cm(也有同样的接口方法),也符合第一家工厂的生产指标,所以也可以拿来代替使用。你会发现,另一家工厂没有特意去遵循第一个工厂的指标(没有显示implement),但事实上却隐式的遵循的指标,也就是说另一家工厂的零件,隐式地实现了第一家工厂的接口,所以它也和第一家工厂生产的零件一样,能应用在相同的场合。
谢谢大佬,我自己定义的接口和结构体之间的使用我还是能搞明白的,(接口的规则我懂了)但是标准库里边的我就有点搞不懂了,比如 Readall( io reader) Readall方法接收一个实现了io reader接口的参数,但是下边的例子file怎么就变成就实现io reader接口的参数了?os. Open后返回的应该是os. Open类型的变量,我怎么知道和确定file实现了io reader接口?讲真的,我是真的看不出来file这个变量能跟io reader接口有半毛钱关系,大佬拜托您指点。 func main() { file, _ := os.Open("test") b, _ := ioutil.ReadAll(file) fmt.Println(string(b)) }[/quote] 虽然没学过golang 但是标准库是人家写的,返回什么人家决定的。这个是需要记的。reader接口也只是file结构体的方法集合,提前写好的一些方法,也可以用自己的结构体来继承这些方法。在rust中管这些叫trait[/quote] 好的 , 多谢大佬指教
程序员不鸣 2019-12-22
  • 打赏
  • 举报
回复
别想那么复杂,本来go设计时就是想避免开发者在一堆接口实现关系中懵逼。go里的接口只是一种规范而已
小洛北 2019-12-22
  • 打赏
  • 举报
回复
引用 41 楼 與蘤舊縐的回复:
文档全英文,遍地都是坑,英语得学好,坑还得自个儿填,天天面向github编程
是啊,现在我也在尝试学习使用github,感觉这个很有用。
「已注销」 2019-12-22
  • 打赏
  • 举报
回复
文档全英文,遍地都是坑,英语得学好,坑还得自个儿填,天天面向github编程
小洛北 2019-12-22
  • 打赏
  • 举报
回复
引用 39 楼 與蘤舊縐的回复:
人工置顶 文档它不香的吗 顺便吐槽一句,某些作者同志更新框架都不同步更新文档的说
文档感觉看的不是太明白。
「已注销」 2019-12-22
  • 打赏
  • 举报
回复
人工置顶 文档它不香的吗 顺便吐槽一句,某些作者同志更新框架都不同步更新文档的说
小洛北 2019-12-22
  • 打赏
  • 举报
回复
引用 34 楼 ARong.的回复:
别想那么复杂,本来go设计时就是想避免开发者在一堆接口实现关系中懵逼。go里的接口只是一种规范而已
go中接口这个隐式实现,有些对象实现了哪个接口根本不知道,所以也不敢乱赋值,这一块有点晕,比如Writer接口,根本不知道有多少对象实现了这个接口,所以也不敢传参数。
小洛北 2019-12-22
  • 打赏
  • 举报
回复
go中接口这个隐式实现,有些对象实现了哪个接口根本不知道,所以也不敢乱赋值,这一块有点晕,比如Writer接口,根本不知道有多少对象实现了这个接口,所以也不敢传参数。
小洛北 2019-12-22
  • 打赏
  • 举报
回复
引用 34 楼 ARong.的回复:
别想那么复杂,本来go设计时就是想避免开发者在一堆接口实现关系中懵逼。go里的接口只是一种规范而已
主要我怕接口没搞明明白白之后学新的包容易懵逼比如net包
luj_1768 2019-12-21
  • 打赏
  • 举报
回复
http接口需要特别处理么?区别就是http属于不稳定连接,需要错误处理代码。
小洛北 2019-12-21
  • 打赏
  • 举报
回复
引用 28 楼 luj_1768的回复:
http接口需要特别处理么?区别就是http属于不稳定连接,需要错误处理代码。
http包还不了解,没深入学习,基础打好了再学http包
  • 打赏
  • 举报
回复
厉害大佬就是牛呢
小洛北 2019-12-20
  • 打赏
  • 举报
回复
引用 25 楼 ying1234的回复:
db操作也是基本啊,别外的github里多找找开源的吧。
好的,非常感谢大佬的指教。
ying1234 2019-12-20
  • 打赏
  • 举报
回复
db操作也是基本啊,别外的github里多找找开源的吧。
ying1234 2019-12-20
  • 打赏
  • 举报
回复
引用 16 楼 CSDN首席执行官 的回复:
[quote=引用 15 楼 ying1234的回复:]网上有破解版的,我装的是JetBrains GoLand 2019.2.3 ,百度搜一下好多破解,有老版本的先卸载,有效期到2089年,足够用了。

好的,多谢了,前辈,你可以跟我说一下你们工作中经常用的的几个包和接口吗?我想重点先看这几个。[/quote]你看看go官方中文文档吧,常用的包无非就是fmt,net/http,net,sync,io,os,encoding/xml,encoding/json,time,encoding,zip,strings,reflect等等,象map,struct,slice,array之些数据结构,还有重点就是go 多协程chan之类
小洛北 2019-12-19
  • 打赏
  • 举报
回复
引用 12 楼 ying1234的回复:
你要给一个接口变量赋值,就必须实现接口定义的所有方法,空接口因为没有定义任何方法,所以可以认为任何东西都实现了空接口,任何都可以给空接口赋值。你把sort.Sort官方文档的例子看一下,变会明白了。

package sort_test
import (
"fmt"
"sort"
)
// A Change is a record of source code changes, recording user, language, and delta size.
type Change struct {
user string
language string
lines int
}
type lessFunc func(p1, p2 *Change) bool
// multiSorter implements the Sort interface, sorting the changes within.
type multiSorter struct {
changes []Change
less []lessFunc
}
// Sort sorts the argument slice according to the less functions passed to OrderedBy.
func (ms *multiSorter) Sort(changes []Change) {
ms.changes = changes
sort.Sort(ms)
}
// OrderedBy returns a Sorter that sorts using the less functions, in order.
// Call its Sort method to sort the data.
func OrderedBy(less ...lessFunc) *multiSorter {
return &multiSorter{
less: less,
}
}
// Len is part of sort.Interface.
func (ms *multiSorter) Len() int {
return len(ms.changes)
}
// Swap is part of sort.Interface.
func (ms *multiSorter) Swap(i, j int) {
ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
}
// Less is part of sort.Interface. It is implemented by looping along the
// less functions until it finds a comparison that is either Less or
// !Less. Note that it can call the less functions twice per call. We
// could change the functions to return -1, 0, 1 and reduce the
// number of calls for greater efficiency: an exercise for the reader.
func (ms *multiSorter) Less(i, j int) bool {
p, q := &ms.changes[i], &ms.changes[j]
// Try all but the last comparison.
var k int
for k = 0; k < len(ms.less)-1; k++ {
less := ms.less[k]
switch {
case less(p, q):
// p < q, so we have a decision.
return true
case less(q, p):
// p > q, so we have a decision.
return false
}
// p == q; try the next comparison.
}
// All comparisons to here said "equal", so just return whatever
// the final comparison reports.
return ms.less[k](p, q)
}
var changes = []Change{
{"gri", "Go", 100},
{"ken", "C", 150},
{"glenda", "Go", 200},
{"rsc", "Go", 200},
{"r", "Go", 100},
{"ken", "Go", 200},
{"dmr", "C", 100},
{"r", "C", 150},
{"gri", "Smalltalk", 80},
}
// ExampleMultiKeys demonstrates a technique for sorting a struct type using different
// sets of multiple fields in the comparison. We chain together "Less" functions, each of
// which compares a single field.
func Example_sortMultiKeys() {
// Closures that order the Change structure.
user := func(c1, c2 *Change) bool {
return c1.user < c2.user
}
language := func(c1, c2 *Change) bool {
return c1.language < c2.language
}
increasingLines := func(c1, c2 *Change) bool {
return c1.lines < c2.lines
}
decreasingLines := func(c1, c2 *Change) bool {
return c1.lines > c2.lines // Note: > orders downwards.
}
// Simple use: Sort by user.
OrderedBy(user).Sort(changes)
fmt.Println("By user:", changes)
// More examples.
OrderedBy(user, increasingLines).Sort(changes)
fmt.Println("By user,<lines:", changes)
OrderedBy(user, decreasingLines).Sort(changes)
fmt.Println("By user,>lines:", changes)
OrderedBy(language, increasingLines).Sort(changes)
fmt.Println("By language,<lines:", changes)
OrderedBy(language, increasingLines, user).Sort(changes)
fmt.Println("By language,<lines,user:", changes)
// Output:
// By user: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken Go 200} {ken C 150} {r Go 100} {r C 150} {rsc Go 200}]
// By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
// By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
// By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
// By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
}


其中 sort.Sort(data Interface),Sort方法接收的是一个接口类型,定义有Sort包里
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}

你看到了吧,代码里传的 sort.Sort(ms),这个ms就必须实现Len() int,Less(i,j int)bool,Swap(i,j int)这3个方法,ms才能传进去不报错,你删除一个方法试试,马上报错。

go 里的接口实现是非注入性的,(不需要在实现接口的类里指明继承哪个接口)相比java,.net里的接口,耦合性小,找的话,你开发工具用JetBrains GoLand,,结构体multiSorter左边有上I+向上红色箭头的,你点击一下,该结构体实现所有的接口都会列出来,你可以查看任何一个接口的定义,当然,只有multiSorter实现在接口才会有这个红色箭头出现。
好的,多谢大佬,另外想问一下,goland好破解吗?
小洛北 2019-12-19
  • 打赏
  • 举报
回复
引用 22 楼 與蘤舊縐的回复:
大家都是单干的,互帮互助吧
嗯嗯,单干太难了,希望有朝一日今天的努力不会白费。
ying1234 2019-12-19
  • 打赏
  • 举报
回复
开发工具不要用vscode,我没发现vscode里可以快速查找接口的,而且vscode里代码量一大,连代码提示弹出来都很慢,怎么设配置都没有用,不是一般的难用。
加载更多回复(19)

2,190

社区成员

发帖
与我相关
我的任务
社区描述
go语言学习与交流版
社区管理员
  • go语言社区
  • Freeman Z
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧