我很好奇,为什么要开不隐式转换[]T到[]interface{}时候会隐式转换T到interface{}.对于这种转换,我有什么不平凡的东西吗?
例:
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 实践,调用者(又名消费者)应该从其依赖项(又名生产者)定义他们想要使用的接口。
\n但是,如果生产者有一个接受自定义类型的函数,那么最好让它接受一个接口,对吗?这样消费者就可以传递一些符合生产者接口的值,而无需知道确切的类型。因为生产者函数的输入值使生产者成为该输入值的“消费者”。
\n好吧,很公平。
\n问题是,消费者如何定义一个接口,其中包含一个函数,其参数是生产者中定义的接口?
\n假设我有一个名为chefstruct 的包Chef。它有一个方法Cut(fruit) error,并且fruit是我的包中定义的接口chef。
现在假设我在调用代码中,并且导入了 package chef。我想给它一个水果来切,但就我而言,我实现了一个名为 的特定水果Apple。当然,我会尝试为自己构建这个界面:
type myRequirements interface {\n Cut(Apple) error\n}\nRun Code Online (Sandbox Code Playgroud)\nfruit因为我有接口的具体实现称为Apple,所以我想表明我的接口仅适用于苹果。
但是,如果我尝试Chef{}针对我的接口使用,Go 将抛出编译错误,因为我的接口想要Cut(Apple)并且Chef{}想要Cut(Fruit)。尽管苹果实现了这一点fruit。
看来,避免这种情况的唯一方法是创建chef.Fruit一个公共接口,并在我自己的接口中使用它。
type myRequirements interface {\n Cut(chef.Fruit) error\n}\nRun Code Online (Sandbox Code Playgroud)\n但这完全破坏了我chef在接口下插入不同实现(而不是 )的能力,因为现在我与chef.
所以Chef有一个内部接口 …
如何不在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类型的所有方法来实现接口.但是Kingdom和Phylum方法对于这两种类型相同.是否有可能只Family实现Tiger类型的方法:
func (t Tiger) Family() string {return "Felidae"}
Run Code Online (Sandbox Code Playgroud)
而不是为每种类型重复所有三种方法?
请不要混淆方法中的简单字符串返回,在实际情况下,我需要不同的方法实现,而不仅仅是预定义的值.使用这种愚蠢的风格,我想避免玷污你的大脑.所以跳过方法根本不是.谢谢
我有一片,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) 我是新手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方法有指针接收器)
我知道编译器在第一个场景中代表我们做了一些指针转换和解引用.为什么不在第二种情况下做同样的事情?
我试图用以下代码理解接口嵌入.
我有以下内容:
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。主要的实现是用 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 没有类型层次结构的概念:没有类,也没有类型继承。也没有方法的动态分派 …
我最近开始研究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,但在第一个障碍上就遇到了困难。
在我的测试代码中,我对一个不存在的域执行基本的 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,所以我做了一些谷歌搜索,看看是否有更好的方法来找出引发了什么样的错误,我发现了以下答案:
包“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 中包含的 …
如果我有以下接口和结构:
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().我的目的是让任何继承的结构Shape都New()自动拥有一个方法.我怎样才能做到这一点?
go ×10
go-interface ×10
inheritance ×2
constructor ×1
dry ×1
go-reflect ×1
interface ×1
oop ×1
pointers ×1
reflection ×1
struct ×1