接口在结构体中没有导出字段或方法。

huangapple go评论94阅读模式
英文:

Interface has no field or method for an exported field in a struct

问题

我有以下结构的代码:

// $GOPATH/experiments/interfaceexport/printer/printer.go
package printer

import "fmt"

type ResourcePrinter interface {
    PrintSomething()
}

type JSONPrinter struct {
    IsGeneric bool
}

func (printer *JSONPrinter) PrintSomething() {
    fmt.Println("JSON")
}

// $GOPATH/experiments/interfaceexporter/printerretriever/printerretriever.go
package printer

import "experiments/interfaceexporter/printer"

func GetPrinter() printer.ResourcePrinter {
    return &printer.JSONPrinter{IsGeneric: true}
}


// $GOPATH/experiments/interfaceexport/main.go
import "experiments/intefaceexport/printerretriever"

func main() {
    printer := printerretriever.GetPrinter()

    printer.PrintSomething() // "JSON"
    // interfaceexport/main.go:13: printer.IsGeneric undefined (type printer.ResourcePrinter has no field or method IsGeneric)
    if printer.IsGeneric {
        printer.PrintSomething()
    }
}

当我运行 go run main.go 时,我得到以下错误:

interfaceexport/main.go:13: printer.IsGeneric undefined (type printer.ResourcePrinter has no field or method IsGeneric)

为什么我会得到上述错误,即使 IsGeneric 是公开的?

英文:

I have code that has following structure:

// $GOPATH/experiments/interfaceexport/printer/printer.go
package printer

import "fmt"

type ResourcePrinter interface {
	PrintSomething()
}

type JSONPrinter struct {
	IsGeneric bool
}

func (printer *JSONPrinter) PrintSomething() {
	fmt.Println("JSON")
}

// $GOPATH/experiments/interfaceexporter/printerretriever/printerretriever.go
package printer

import "experiments/interfaceexporter/printer"

func GetPrinter() printer.ResourcePrinter {
  return &printer.JSONPrinter{IsGeneric: true}
}


// $GOPATH/experiments/interfaceexport/main.go
import "experiments/intefaceexport/printerretriever"

func main() {
  printer := printerretriever.GetPrinter()

  printer.PrintSomething() // "JSON"
  // interfaceexport/main.go:13: printer.IsGeneric undefined (type printer.ResourcePrinter has no field or method IsGeneric)
  if printer.IsGeneric {
    printer.PrintSomething()
  }
}

When I do go run main.go I get following error:

interfaceexport/main.go:13: printer.IsGeneric undefined (type printer.ResourcePrinter has no field or method IsGeneric)

Why do I get above error even though IsGeneric is exported?

答案1

得分: 12

printer.ResourcePrinter是一个接口,而不是实际的实例JSONPrinter,后者可以访问IsGeneric属性。

你需要在接口中添加一个IsGeneric()方法(并在JSONPrinter中实现它),以便能够按照你的需求使用该接口。

参考“golang如何访问接口字段”:你还可以通过类型断言提取接口变量中保存的动态值:

dynamic_value := printer.(JSONPrinter)

然后,dynamic_value将能够访问IsGeneric属性。

更多信息请参见“如何访问接口的属性”。


> 即使编译器知道printer.ResourcePrinter是一个接口,它仍然说IsGeneric也可能是一个字段。

接口的动态值可以有字段(参见“从接口获取所有字段”)。

当应用于接口时,无字段部分可以指代一个嵌入类型,未限定类型的名称充当字段名。

type ReadWriter interface {
	Read(b Buffer) bool
	Write(b Buffer) bool
}

type File interface {
	ReadWriter  // 等同于添加ReadWriter的方法
	Locker      // 等同于添加Locker的方法
	Close()
}

当使用指针指向接口时(当接口本身包含某种指针时),你也会看到这种类型的错误消息:“Go:interface{}的含义是什么?”和“在Golang中将结构体指针转换为接口指针”。

参见issue 10700

> 当使用一个新的、不熟悉的包时,程序员有时会错误地使用指向接口类型的指针,而不是直接使用接口类型。

英文:

printer.ResourcePrinter is an interface, not the actual instance JSONPrinter, which does have access to IsGeneric

You would need to add a method IsGeneric() to your interface (and implement it in JSONPrinter) in order to be able to use that interface as you want.

See "golang how to access interface fields": you could also extract the dynamic value held by the interface variable through a type assertion:

dynamic_value := printer.(JSONPrinter)

Then dynamic_value would have access to the IsGeneric attribute.

See more at "How to access attribute of interface".


> Even though compiler knows that printer.ResourcePrinter is an interface, it says that IsGeneric could also be a field.

The dynamic value of the interface can have field (see "Get all fields from an interface")

The no field part, when applied to an interface, can refer to an embedded type, the unqualified type’s name acts as the field name.

type ReadWriter interface {
	Read(b Buffer) bool
	Write(b Buffer) bool
}

type File interface {
	ReadWriter  // same as adding the methods of ReadWriter
	Locker      // same as adding the methods of Locker
	Close()
}

You also see that kind of error message when using a pointer to an interface (when the interface itself includes a pointer of sorts: "Go: What's the meaning of interface{}?" and "Cast a struct pointer to interface pointer in Golang")

See issue 10700

> When using a new, unfamiliar package, programmers occasionally make the error of using a pointer to an interface type instead of the interface type directly.

答案2

得分: 0

简单来说,你的接口没有IsGeneric方法:

type ResourcePrinter interface {
    PrintSomething()
}
英文:

Simple, your interface has no method IsGeneric:

type ResourcePrinter interface {
    PrintSomething()
}

huangapple
  • 本文由 发表于 2017年5月20日 14:08:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/44082536.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定