标签: go-interface

在go中键入转换接口切片

我很好奇,为什么要开不隐式转换[]T[]interface{}时候会隐式转换Tinterface{}.对于这种转换,我有什么不平凡的东西吗?

例:

func foo([]interface{}) { /* do something */ }

func main() {
    var a []string = []string{"hello", "world"}
    foo(a)
}
Run Code Online (Sandbox Code Playgroud)

go build 抱怨

不能在函数参数中使用(type [] string)作为type [] interface {}

如果我尝试明确地做,同样的事情:b := []interface{}(a)抱怨

无法将(type [] string)转换为type [] interface {}

所以每次我需要进行这种转换(这看起来很多),我一直在做这样的事情:

b = make([]interface{}, len(a), len(a))
for i := range a {
    b[i] = a[i]
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来执行此操作,或标准库函数来帮助进行这些转换?每次我想调用一个可以获取例如整数或字符串列表的函数时,编写4行额外代码似乎有点愚蠢.

go go-interface go-reflect

171
推荐指数
6
解决办法
7万
查看次数

在 Golang 中,消费者如何为接受接口的函数定义接口?

如果我正确理解 Go 实践,调用者(又名消费者)应该从其依赖项(又名生产者)定义他们想要使用的接口。

\n

但是,如果生产者有一个接受自定义类型的函数,那么最好让它接受一个接口,对吗?这样消费者就可以传递一些符合生产者接口的值,而无需知道确切的类型。因为生产者函数的输入值使生产者成为该输入值的“消费者”。

\n

好吧,很公平。

\n

问题是,消费者如何定义一个接口,其中包含一个函数,其参数是生产者中定义的接口?

\n

试图让问题更清楚

\n

假设我有一个名为chefstruct 的包Chef。它有一个方法Cut(fruit) error,并且fruit是我的包中定义的接口chef

\n

现在假设我在调用代码中,并且导入了 package chef。我想给它一个水果来切,但就我而言,我实现了一个名为 的特定水果Apple。当然,我会尝试为自己构建这个界面:

\n
type myRequirements interface {\n  Cut(Apple) error\n}\n
Run Code Online (Sandbox Code Playgroud)\n

fruit因为我有接口的具体实现称为Apple,所以我想表明我的接口仅适用于苹果。

\n

但是,如果我尝试Chef{}针对我的接口使用,Go 将抛出编译错误,因为我的接口想要Cut(Apple)并且Chef{}想要Cut(Fruit)。尽管苹果实现了这一点fruit

\n

看来,避免这种情况的唯一方法是创建chef.Fruit一个公共接口,并在我自己的接口中使用它。

\n
type myRequirements interface {\n  Cut(chef.Fruit) error\n}\n
Run Code Online (Sandbox Code Playgroud)\n

但这完全破坏了我chef在接口下插入不同实现(而不是 )的能力,因为现在我与chef.

\n

所以Chef有一个内部接口 …

go go-interface

10
推荐指数
1
解决办法
2616
查看次数

如何在Golang中保留代码DRY

编辑++:

如何不在Go中重复我的代码?

type Animal interface {
    Kingdom() string
    Phylum() string
    Family() string
}

type Wolf struct {}
type Tiger struct {}

func (w Wolf) Kingdom() string {return "Animalia"}
func (w Wolf) Phylum() string {return "Chordata"}
func (w Wolf) Family() string {return "Canidae"}
Run Code Online (Sandbox Code Playgroud)

我为Wolf类型实现了三种方法,我需要实现Tiger类型的所有方法来实现接口.但是KingdomPhylum方法对于这两种类型相同.是否有可能只Family实现Tiger类型的方法:

func (t Tiger) Family() string {return "Felidae"}
Run Code Online (Sandbox Code Playgroud)

而不是为每种类型重复所有三种方法?

放弃

请不要混淆方法中的简单字符串返回,在实际情况下,我需要不同的方法实现,而不仅仅是预定义的值.使用这种愚蠢的风格,我想避免玷污你的大脑.所以跳过方法根本不是.谢谢

interface dry go go-interface

9
推荐指数
1
解决办法
1310
查看次数

在Go中,如何检查(任何)指针类型的值?

我有一片,interface{}我需要检查这个片是否包含指针字段值.

澄清示例:

var str *string
s := "foo"
str = &s
var parms = []interface{}{"a",1233,"b",str}
index := getPointerIndex(parms)
fmt.Println(index) // should print 3
Run Code Online (Sandbox Code Playgroud)

reflection pointers go go-interface

8
推荐指数
1
解决办法
4809
查看次数

接口和指针接收器

我是新手gopher,并试图让我的头围绕指针接收器和接口.

type Foo interface {
    foo()
}
type Bar struct {}
func (b *Bar) foo() {}
Run Code Online (Sandbox Code Playgroud)

基于以上定义..

--- Allowed ---------
b := Bar{}
b.foo()

--- Not allowed ----- 

var foo Foo = Bar{}
Run Code Online (Sandbox Code Playgroud)

获取编译器错误:不能在赋值时使用Bar literal(类型Bar)作为类型Foo:Bar不实现Foo(foo方法有指针接收器)

我知道编译器在第一个场景中代表我们做了一些指针转换和解引用.为什么不在第二种情况下做同样的事情?

go go-interface

6
推荐指数
2
解决办法
2430
查看次数

了解界面内部界面(嵌入式界面)

我试图用以下代码理解接口嵌入.

我有以下内容:

type MyprojectV1alpha1Interface interface {
    RESTClient() rest.Interface
    SamplesGetter
}

// SamplesGetter has a method to return a SampleInterface.
// A group's client should implement this interface.
type SamplesGetter interface {
    Samples(namespace string) SampleInterface
}

// SampleInterface has methods to work with Sample resources.
type SampleInterface interface {
    Create(*v1alpha1.Sample) (*v1alpha1.Sample, error)
    Update(*v1alpha1.Sample) (*v1alpha1.Sample, error)
    Delete(name string, options *v1.DeleteOptions) error
    DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
    Get(name string, options v1.GetOptions) (*v1alpha1.Sample, error)
    List(opts v1.ListOptions) (*v1alpha1.SampleList, error)
    Watch(opts v1.ListOptions) (watch.Interface, error)
    Patch(name string, …
Run Code Online (Sandbox Code Playgroud)

go go-interface

6
推荐指数
1
解决办法
971
查看次数

在没有语言支持类型层次结构的情况下对相关事物的层次结构进行建模

我是 Go 的新手,我想做的第一件事就是将我的小标记页面生成库移植到 Go。主要的实现是用 Ruby 实现的,它的设计非常“经典的面向对象”(至少我从业余程序员的角度理解 OO)。它模拟了我如何看待标记文档类型之间的关系:

                                      Page
                                   /        \
                          HTML Page          Wiki Page
                         /         \
              HTML 5 Page           XHTML Page
Run Code Online (Sandbox Code Playgroud)

对于一个小项目,我可能会做这样的事情(翻译成我现在想要的 Go):

p := dsts.NewHtml5Page()
p.Title = "A Great Title"
p.AddStyle("default.css")
p.AddScript("site_wide.js")
p.Add("<p>A paragraph</p>")
fmt.Println(p) // Output a valid HTML 5 page corresponding to the above
Run Code Online (Sandbox Code Playgroud)

对于较大的项目,比如一个名为“Egg Sample”的网站,我将现有的一种页面类型子类化,创建更深层次的层次结构:

                                 HTML 5 Page
                                      |
                               Egg Sample Page
                             /        |        \
               ES Store Page    ES Blog Page     ES Forum Page
Run Code Online (Sandbox Code Playgroud)

这非常适合经典的面向对象设计:子类可以免费获得很多,并且它们只关注与父类不同的少数部分。例如,EggSamplePage 可以添加一些在所有 Egg Sample 页面中通用的菜单和页脚。

然而,Go 没有类型层次结构的概念:没有类,也没有类型继承。也没有方法的动态分派 …

oop inheritance go go-interface

5
推荐指数
2
解决办法
563
查看次数

如何在go中实现类似的界面?

我最近开始研究Go并面临下一期.我想实现Comparable接口.我有下一个代码:

type Comparable interface {
    compare(Comparable) int
}
type T struct {
    value int
}
func (item T) compare(other T) int {
    if item.value < other.value {
        return -1
    } else if item.value == other.value {
        return 0
    }
    return 1
}
func doComparison(c1, c2 Comparable) {
    fmt.Println(c1.compare(c2))
}
func main() {
    doComparison(T{1}, T{2})
}
Run Code Online (Sandbox Code Playgroud)

所以我收到了错误

cannot use T literal (type T) as type Comparable in argument to doComparison:
    T does not implement Comparable (wrong type for compare method)
        have …
Run Code Online (Sandbox Code Playgroud)

go go-interface

5
推荐指数
1
解决办法
1723
查看次数

我如何找出 go 中的错误是什么类型?

我不确定如何确切地表达这个问题,而且我看到其他人提出了类似的问题,但没有真正给出答案(这告诉我我问了错误的问题,但我不知道如何解决这个问题)。

我正在尝试学习一些基本的 Go,但在第一个障碍上就遇到了困难。

在我的测试代码中,我对一个不存在的域执行基本的 http GET 操作,以触发 DNS 警告。我发现 err.error() 返回一个字符串,因此为了断言它是否是 DNS 错误,我使用了字符串比较:

resp, err := http.Get(link)
if err != nil {
    if strings.Contains(err.Error(), "no such host") == true {
        return "no such host"
    }
}
Run Code Online (Sandbox Code Playgroud)

这显然是很hacky,所以我做了一些谷歌搜索,看看是否有更好的方法来找出引发了什么样的错误,我发现了以下答案:

如何检查特定的 golang net/http 错误代码?

包“errors”具有 As 功能,用于解包特定的错误类型,包“net”具有 *DNSError 类型。所以:

var dnsErr *net.DNSError
if errors.As(err, &dnsErr) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

这段代码有效,但我完全不知道这个结论是如何得出的。以下是我试图理解这一点的方法,我想知道我哪里出错了。我(模糊地)理解 .Is() 和 .As() 正在做什么,但我不明白的是如何计算出什么错误“类型”来提供这些函数而无需猜测或先验知识。

我查看了 client.get() 文档,其中写着:

任何返回的错误都将是 *url.Error 类型。

更多的谷歌搜索,我发现我需要将错误转换为该类型才能使用它:

urlErr := err.(*url.Error)
Run Code Online (Sandbox Code Playgroud)

*url.Error 包含:

&url.Error{Op:"Get", URL:"http://doesnotexistkjdfhgsdfsdf.com", Err:(*net.OpError)(0xc00021a2d0)}
Run Code Online (Sandbox Code Playgroud)

所以我然后查看 url.Error 中包含的 …

error-handling go go-interface

5
推荐指数
1
解决办法
6860
查看次数

接口中的构造方法?(在Golang)

如果我有以下接口和结构:

package shape

type Shape interface {
    Area()
}

type Rectangle struct {
}

func (this *Rectangle) Area() {}

func New() Shape {
    return &Rectangle{}
}
Run Code Online (Sandbox Code Playgroud)

那么如何将该New()方法(作为构造函数)添加到界面中Shape

用例是如果我有另一个结构 Square

type Square struct {
    Rectangle
}
Run Code Online (Sandbox Code Playgroud)

然后Square将有一个方法Area().但它不会New().我的目的是让任何继承的结构ShapeNew()自动拥有一个方法.我怎样才能做到这一点?

inheritance constructor struct go go-interface

4
推荐指数
1
解决办法
5024
查看次数