X 没有实现 Y(...方法有一个指针接收器)

2024-02-24

已经有几个关于此的问答“X 没有实现 Y(...方法有一个指针接收器)”的事情,但对我来说,他们似乎在谈论不同的事情,并不适用于我的具体情况。

因此,我没有将问题变得非常具体,而是将其变得广泛和抽象 - 似乎有几种不同的情况可能会导致此错误发生,有人可以总结一下吗?

即如何避免该问题,如果发生,可能性有哪些?谢谢。


当您尝试分配或传递(或转换)一个concrete类型为接口类型;并且类型本身并没有实现接口,只是一个指向类型的指针.

Short summary: An assignment https://golang.org/ref/spec#Assignments to a variable of interface type is valid if the value being assigned implements the interface it is assigned to. It implements it if its method set https://golang.org/ref/spec#Method_sets is a superset of the interface. The method set of pointer types includes methods with both pointer and non-pointer receiver. The method set of non-pointer types only includes methods with non-pointer receiver.

让我们看一个例子:

type Stringer interface {
    String() string
}

type MyType struct {
    value string
}

func (m *MyType) String() string { return m.value }

The Stringer接口类型只有一种方法:String()。存储在接口值中的任何值Stringer一定有这个方法。我们还创建了一个MyType,我们创建了一个方法MyType.String() with pointer接收者。这意味着String()方法是在方法集 https://golang.org/ref/spec#Method_sets of the *MyType类型,但不属于MyType.

当我们尝试分配一个值MyType到一个类型的变量Stringer,我们得到有问题的错误:

m := MyType{value: "something"}

var s Stringer
s = m // cannot use m (type MyType) as type Stringer in assignment:
      //   MyType does not implement Stringer (String method has pointer receiver)

但是如果我们尝试分配一个 type 的值,一切都可以*MyType to Stringer:

s = &m
fmt.Println(s)

我们得到了预期的结果(尝试一下去游乐场 https://play.golang.org/p/TSaT30PRD0):

something

因此,获得此编译时错误的要求:

  • 值为非指针被分配(或传递或转换)的具体类型
  • 被分配(或传递或转换)的接口类型
  • 具体类型具有接口所需的方法,但带有一个指针接收器

解决该问题的可能性:

  • 必须使用指向该值的指针,其方法集将包括带有指针接收者的方法
  • 或者必须将接收器类型更改为非指针,因此非指针具体类型的方法集也将包含该方法(从而满足接口)。这可能可行,也可能不可行,就像该方法必须修改值一样,非指针接收器不是一个选项。

结构和嵌入

使用时结构和嵌入 https://golang.org/ref/spec#Struct_types,通常不是“您”实现接口(提供方法实现),而是您嵌入到您的struct。就像这个例子一样:

type MyType2 struct {
    MyType
}

m := MyType{value: "something"}
m2 := MyType2{MyType: m}

var s Stringer
s = m2 // Compile-time error again

再次,编译时错误,因为方法集MyType2不包含String()嵌入方法MyType,只有方法集*MyType2,所以以下工作(在去游乐场 https://play.golang.org/p/3MuyevNpL8):

var s Stringer
s = &m2

如果我们嵌入,我们也可以让它工作*MyType并且只使用一个非指针 MyType2(尝试一下去游乐场 https://play.golang.org/p/BMG5EctMVa):

type MyType2 struct {
    *MyType
}

m := MyType{value: "something"}
m2 := MyType2{MyType: &m}

var s Stringer
s = m2

另外,无论我们嵌入什么(要么MyType or *MyType),如果我们使用指针*MyType2,它总是有效的(尝试一下去游乐场 https://play.golang.org/p/3MuyevNpL8):

type MyType2 struct {
    *MyType
}

m := MyType{value: "something"}
m2 := MyType2{MyType: &m}

var s Stringer
s = &m2

规范中的相关部分(来自部分结构类型 https://golang.org/ref/spec#Struct_types):

给定一个结构体类型S和一个名为T,提升的方法包含在结构体的方法集中,如下所示:

  • If S包含匿名字段T,方法集S and *S两者都包括带有接收器的升级方法T。方法集为*S还包括带有接收器的升级方法*T.
  • If S包含匿名字段*T,方法集S and *S两者都包括带有接收器的升级方法T or *T.

换句话说:如果我们嵌入一个非指针类型,非指针嵌入器的方法集只能获取具有非指针接收器的方法(来自嵌入类型)。

如果我们嵌入指针类型,非指针嵌入器的方法集将获取具有指针和非指针接收器的方法(来自嵌入类型)。

如果我们使用指向嵌入器的指针值,则无论嵌入类型是否是指针,指向嵌入器的指针的方法集始终都会获取具有指针和非指针接收器的方法(来自嵌入类型)。

Note:

有一个非常相似的情况,即当您有一个包装值的接口值时MyType,然后你尝试类型断言 https://golang.org/ref/spec#Type_assertions另一个接口值,Stringer。在这种情况下,由于上述原因,断言将不成立,但我们会得到略有不同的运行时错误:

m := MyType{value: "something"}

var i interface{} = m
fmt.Println(i.(Stringer))

运行时恐慌(尝试一下去游乐场 https://play.golang.org/p/Mos344EWbH):

panic: interface conversion: main.MyType is not main.Stringer:
    missing method String

尝试转换而不是类型断言,我们得到了我们正在讨论的编译时错误:

m := MyType{value: "something"}

fmt.Println(Stringer(m))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

X 没有实现 Y(...方法有一个指针接收器) 的相关文章

  • 模板中的 bson.ObjectId

    我有一个具有 bson ObjectId 类型的结构 例如如下所示 type Test struct Id bson ObjectId Name string Foo string 我想在 html 模板中呈现它 Name Food a h
  • 指向特征矩阵的指针数组

    我在代码中使用 Eigen 的 MatrixXd 矩阵 在某个时刻我需要一个 3D 矩阵 由于 Eigen 没有三维矩阵类型 因为它仅针对线性代数进行了优化 因此我创建了一个 MatrixXd 类型的指针数组 Eigen MatrixXd
  • Java:SortedMap、TreeMap、可比较?如何使用?

    我有一个对象列表 需要根据其中一个字段的属性进行排序 我听说 SortedMap 和 Comparator 是实现此目的的最佳方法 我是否要与正在排序的类实现 Comparable 还是创建一个新类 如何实例化 SortedMap 并传入
  • 如何使用 javascript 更改文件扩展名

    有谁知道在 Javascript 中更改文件扩展名的简单方法吗 例如 我有一个带有 first docx 的变量 但我需要将其更改为 first html 这将改变字符串包含文件名 let file first docx file file
  • 如何在静态方法中获取会话变量的值?

    我正在使用带有 jQ uery 的 ASP NET 页面方法 如何在 C 中的静态方法中获取会话变量的值 protected void Page Load object sender EventArgs e Session UserName
  • GOMAXPROCS 默认值是多少?

    不设置同名环境变量时是否保证GOMAXPROCS设置为1 此代码显示的值 package main import runtime fmt func getGOMAXPROCS int return runtime GOMAXPROCS 0
  • 如何在 Linux 中编写文本模式 GUI? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 当我编写脚本 程序时 我经常想弹出一个简单的文本 gui 来提示输入 我该怎么做 例如 来自 Shel
  • 有队列实现吗?

    任何人都可以建议使用 Go 容器来实现简单快速的 FIF 队列 Go 有 3 种不同的容器 heap list and vector 哪一种更适合实现队列 事实上 如果您想要的是一个基本且易于使用的 fifo 队列 slice 可以满足您所
  • 使用接口或函数对象进行回调? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在面向对象中 通常使用接口来实现回调 粗略示例 class Message class IMsgProcessor public virtual
  • 如何在golang中解析JSON而不需要解组两次

    我有一个 Web 套接字连接 它在 JSON 对象中发送不同类型的消息 并且我想将内容解组到一些已知的结构中 为此 我认为我应该执行以下操作 步骤 1 将 JSON 解组为通用映射 字符串 接口 步骤 2 找到我要找的钥匙 步骤 3 尝试将
  • “go.tools”的权限被拒绝错误

    当我尝试安装 go 工具时 我的权限被拒绝 usr local go pkg tool linux amd64 cover 我可以接受 因为它是 usr local 目录及需求root使用权 但我的第一个疑问是为什么当我设置时它试图安装在这
  • Golang中按长度分割字符串

    有谁知道如何在 Golang 中按长度分割字符串 例如 每 3 个字符分割 helloworld 那么理想情况下它应该返回一个 hel low orl d 数组 或者 一个可能的解决方案是在每 3 个字符后附加一个换行符 所有的想法都非常感
  • 为什么 json.Unmarshal 返回映射而不是预期的结构?

    看看这个游乐场 http play golang org p dWku6SPqj5 http play golang org p dWku6SPqj5 基本上 我正在工作的图书馆收到了interface 作为参数 然后需要json Unma
  • x86 上未对齐的指针

    有人可以提供一个示例 将指针从一种类型转换为另一种类型由于未对齐而失败吗 在评论中这个答案 https stackoverflow com questions 544928 reading integer size bytes from a
  • 我可以从命令行调用除 main(String[]) 之外的 java 方法吗?

    我可以调用 java 方法吗 main String 从命令行 如果没有 main 函数 则可以添加一个 main 函数 如果有 则可以在顶部添加一系列 if then 块 public static void main String ar
  • 为什么这个二维指针表示法有效,而另一个则无效[重复]

    这个问题在这里已经有答案了 这里我编写了一段代码来打印 3x3 矩阵的对角线值之和 这里我必须将矩阵传递给函数 矩阵被传递给指针数组 代码可以工作 但问题是我必须编写参数的方式如下 int mat 3 以下导致程序崩溃 int mat 3
  • '回应?'与“定义?”

    如果我想检查是否定义了给定名称的方法 使用哪个更好 respond to or defined 从效率的角度来看 可以有理由使用defined 因为defined 是一个内置关键字 而respond to 是一种方法 因此前者可能更快 但另
  • 在 Gorilla Mux 中嵌套子路由器

    我一直在使用gorilla mux https github com gorilla mux满足我的路由需求 但我注意到一个问题 当我嵌套多个子路由器时它不起作用 这是示例 func main r mux NewRouter StrictS
  • RSA OAEP、Golang 加密、Java 解密 -BadPaddingException:解密错误

    我正在尝试解密使用 RSA OAEP 在 Golang 中加密的字符串 但出现 BadPaddingException 解密错误 很难弄清楚我错过了什么 这是Golang加密方法 func encryptString rootPEM io
  • 结构体指针的动态数组

    我必须使用以下代码块来完成学校作业 严格不进行任何修改 typedef struct char firstName char lastName int id float mark pStudentRecord pStudentRecord

随机推荐

  • Swift:如何从 UIImage 数组中提取图像文件名

    如果我有一个像这样的 UIImage 数组 newImageArray UIImage named Red png UIImage named Green png UIImage named Blue png UIImage named Y
  • 如何使用 DotNetZip 从 zip 中提取 XML 文件

    我使用的是最新版本的 DotNetZip 并且有一个包含 5 个 XML 的 zip 文件 我想打开 zip 读取 XML 文件并使用 XML 的值设置一个字符串 我怎样才能做到这一点 Code thats my old way of do
  • 使用 Selenium 的模态对话框窗口

    因此 我尝试使用 Selenium 导航到 IE9 中的页面 该页面在加载页面时显示存在证书错误 使用 AutoIT 我可以让它在浏览器中单击 然后按 TAB 两次 然后按 Enter 键 没有问题 然而 当它继续时 它会抛出 模态对话框存
  • 如何避免未使用的 setState 函数? React useState 可以在没有 setter 的情况下创建吗?

    我目前正在减少 删除 React 站点上的 npm 警告 大量警告是由 setState 函数 未使用 引起的 如下所示 const state setState useState some state 以下哪项是消除这些警告的更好方法 或
  • 基本高性能数据真实性

    我不是母语人士 术语可能不正确 对此感到抱歉 我正在 AVR 微控制器之间通过无线电传输数据供个人使用 并希望客户能够证明传输数据的真实性 因为它来自授权客户之一 这意味着我不需要不可否认性并且能够预先定义共享密钥 我对不同的方法进行了一些
  • Xcode 8:以 NSException 类型的未捕获异常终止

    我是新手 我遇到了这个错误 我到处查找 但找不到解决方案 任何帮助将非常感激 0 CoreFoundation 0x00000001102bb34b exceptionPreprocess 171 1 libobjc A dylib 0x0
  • 为什么 UINavigationBar 会窃取触摸事件?

    我有一个自定义 UIButton 其中 UILabel 添加为子视图 仅当我触摸顶部边界下方约 15 个点时 按钮才会执行给定的选择器 当我点击该区域上方时 什么也没有发生 我发现这并不是由错误创建按钮和标签引起的 因为在我将按钮向下移动约
  • EditText TextChangeListener问题

    我有一个用于搜索目的的编辑文本 我已经添加了 searchET addTextChangedListener new TextWatcher Override public void onTextChanged CharSequence s
  • 如何使用 bash 命令创建 CPU 峰值

    我想在 Linux 机器上创建接近 100 的负载 它是四核系统 我希望所有核心都全速运行 理想情况下 CPU 负载将持续指定的时间 然后停止 我希望 bash 有一些技巧 我在想某种无限循环 I use stress http linux
  • Java Swing 中的图形绘制仅绘制点

    我目前正在开发一个程序 其中随着时间的推移而演变的某些数值变量在每次迭代中显示它们的值 这已经足够好了 但现在我想绘制一个图表来显示它们随时间的演变 因此 我研究了在 Swing 中绘制图表的代码示例 我的最终代码如下所示 public c
  • 处理ControlCAsInput 问题。这是一个错误吗?

    刚刚遇到了下面描述的问题 如果 Console TreatControlCAsInput true 则必须在 ReadLine 上按 enter 两次 我在下面写了一些演示代码 我对这段代码演示了 NET 4 框架中的错误的猜测是正确的吗
  • 打开 XML SDK 2.0 以按名称访问 Excel 2010 工作表

    我有一个 Excel 2010 电子表格 其中有 3 个工作表 分别名为 Sheet1 Sheet2 和 Sheet3 我正在尝试按名称获取对工作表的引用 我正在使用代码 using SpreadsheetDocument myWorkbo
  • 将 JSON 编码的 PHP 数组解析为 JavaScript JSON.parse() 时的 PHP 或 JavaScript 问题

    我目前正在为我的工作场所制作一个 Web 应用程序 它一次性从 SQL 表中下载大约 40 000 行数据 将数据放入嵌套的 PHP 数组中 然后尝试回显 JSON 编码的数组 其中 JavaScript 变量应该捕获内容 如果我尝试将数据
  • 在repz cmpsb之后,汇编指令'seta'和'setb'做什么?

    我无法理解以下装配线的作用 0x401810 repz cmps BYTE PTR ds rsi BYTE PTR es rdi 0x401812 seta dl 0x401815 setb al 我明白调试后 第一条指令比较寄存器中的字节
  • 为什么 Visual Studio 找不到我的 DLL? [复制]

    这个问题在这里已经有答案了 在 Visual Studio 2010 中 在VC Directories gt Executable Directories 我已经指定了路径glew32d dll 但是 当我运行可执行文件时 它仍然抱怨 另
  • NodeJS Redis 客户端返回错误值

    我正在使用 NodeJS Redis 客户端 Redis节点 https github com mranney node redis并调用 SISMEMBER Redis 命令 但是 当我调用该命令时 无论该值是否是该集合的成员 它总是返回
  • Spring Boot REST API 的指标收集

    我正在尝试收集我的 Spring Boot 2 1 0 RELEASE 应用程序的指标 具体来说我想知道 调用各个 REST 端点的次数 每个端点处理请求所花费的时间 我的请求被处理 出错的平均速率 执行器 actuator metrics
  • 测量缠绕的绳子

    我正在尝试创建一个控件 它基本上允许我在彼此下面绘制不同的字符串 但是 字符串的宽度不能大于控件的宽度 为了解决这个问题 我正在考虑将 RectangleF 对象传递给 Graphics DrawString 方法 这将包装比传递的矩形宽度
  • array_walk_recursive 与数组?

    我有一个菜单数组 它是一个多维数组 我想对每个项目做一些事情 所以我尝试了 array walk recursive 这是菜单 menu array array name gt a url gt b array name gt c url
  • X 没有实现 Y(...方法有一个指针接收器)

    已经有几个关于此的问答 X 没有实现 Y 方法有一个指针接收器 的事情 但对我来说 他们似乎在谈论不同的事情 并不适用于我的具体情况 因此 我没有将问题变得非常具体 而是将其变得广泛和抽象 似乎有几种不同的情况可能会导致此错误发生 有人可以