为什么接口不实现带有指针引用的方法,而仍然可以直接访问?

2024-03-28

我确实理解接口没有按照 Go 规范和 FAQ 实现带有指针引用的方法,因为 T 和 *T 有不同的方法集(https://golang.org/doc/faq#guarantee_satisfies_interface https://golang.org/doc/faq#guarantee_satisfies_interface).

所以,这是行不通的:

package main

import (
    "fmt"
)

type user struct {
    name string
}

type modifier interface {
    modify()
}

func (u *user) modify() {
    u.name = "My name"
}

func interfaceModify(m modifier) {
    m.modify()
}

func main() {
    u := user{"Default Name"}

    interfaceModify(u)
    fmt.Println(u.name)
}

并返回:

./main.go:26: 不能在接口修改参数中使用 u (类型 user)作为类型修饰符:用户没有实现修饰符(修改方法有指针接收器)

这解释为:

[...]方法调用没有有用的方法来获取指针。

即使编译器可以将值的地址传递给方法,如果方法修改了值,则调用者中的更改也会丢失。

然而,更换interfaceModify(u)直接调用,例如u.modify()确实有效:编译器获取地址u,并将按照 Println() 确认修改其 name 属性。

因此,我们能够在这种精确的情况下执行该操作,但不能在界面中执行该操作。我对这种差异的唯一解释是interfaceModify(m modifier),我们将有一个直接副本u to m,并且没有办法m调用时匹配对应的地址modify()。 并且,所以,宣布u := &user{"Default Name"}因此会复制指针(所以地址)u to m,这就是为什么m.modify()是可能的。 我对么?


我想你已经明白了。u.modify()有效,因为 go 将其视为简写(&u).modify(). interfaceModify(&u)也会起作用。这是一个游乐场,其中包含更多按引用传递与按值传递的示例。

https://play.golang.org/p/HCMtcFAhLe https://play.golang.org/p/HCMtcFAhLe

package main

import (
    "fmt"
)

type user struct {
    name string
}

type userPointer struct {
    user
}

func (up *userPointer) modify() {
    up.name = "My name"
}

type modifier interface {
    modify()
}

func (u user) modify() {
    u.name = "My name"
}

func interfaceModify(m modifier) {
    m.modify()

}

func main() {
    u := user{"Default Name"}
    u.modify()
    fmt.Println(u.name)
    interfaceModify(u)
    fmt.Println(u.name)

    up := userPointer{user{"Default Name"}}
    interfaceModify(&up)
    fmt.Println(up.name)
    // short hand version
    up.name = "Default Name"
    up.modify()
    fmt.Println(up.name)
    // long hand version https://golang.org/ref/spec#Calls
    up.name = "Default Name"
    (&up).modify()
    fmt.Println(up.name)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么接口不实现带有指针引用的方法,而仍然可以直接访问? 的相关文章

  • 如何展平嵌套 JSON

    尝试将嵌套的 json 响应从 2 层深度压平到 1 层 这是我在 Go Playground 上的工作代码 http play golang org p kHAYuZUTko http play golang org p kHAYuZUT
  • c.JSON gin.H{()} 输出空对象

    我刚刚开始学习 GO lang 结合 Gin 框架 我决定编写一些简单的 api 来获取有关酒精饮料的数据 我当前的问题是 api get 方法http localhost 8080 alcohol drinks 返回空数据对象 My co
  • 为什么我无法导入“内置”pkg?

    cat test go package main import builtin func main return go run test go can t find import builtin 我只是好奇 因为该文件存在并且已正确打包 但
  • 将 Base64 字符串转换为 JPG

    我正在得到图像为 base64 字符串 dataurl 下面是我的函数 它将dataurl进入图像 现在 如果图像是 png 则 png 库将创建图像 而 jpg 库将引发错误 反之亦然 问题是当我上传 png 时效果很好 但是当我上传 j
  • 如何将 interface{} 转换回其原始结构?

    我需要一种方法将结构 接口动态转换回其原始对象 我可以在里面添加方法 函数 基本上我需要这样的东西 MyStruct gt Interface gt MyStruct 在最终转换时 除了结构内部的内容之外 我对原始结构一无所知 所以我不能这
  • 如何获取变量的内存大小?

    有谁知道如何获取变量的内存大小 int string struct等 并打印它 是否可以 var i int 1 I want to get something like this fmt Println Size of i is i Al
  • 接口实现中的非接口方法

    我有一个定义方法的接口 我有一个结构实施这个界面 在其中 我实现了该接口中的方法 并且还定义了其他方法 例如 package main import fmt type Animal interface MakeNoise type Dog
  • 如何用 Go 将多个字符串解析为模板?

    有没有像这样的简单方法template ParseFiles base html home html 但是对于字符串来说 如何从一组字符串构建模板 我有一个基本模板和一个页面模板列表 全部为字符串 我想在基本模板之上构建它们 我想出了如何合
  • Go1编译器如何工作?

    我在一个学校项目中接触 Go 大约一个月了 我注意到 src pkg go 文件夹中的 go ast go token go parser 等包 但是 gc 编译器基于位于 src cmd gc 中的 C 文件 我的问题是关于 Go1 中用
  • 如何更改“go build”的库路径

    我正在尝试与 goncurses 一起工作 在 Centos 6 上 ncurses 库很旧 5 7 想要 5 9 所以我从源代码构建了 ncurses 并将其安装到 usr lib usr include 等中 如何告诉 go get 针
  • Golang 中的“相互”包导入

    是否可以在 Golang 中执行 相互 包导入之类的操作 举例来说 我有两个包 A 和 B 分别具有 AFunc 和 BFunc BFunc2 函数 package A import B func AFunc do stuff but al
  • 为什么我不能执行 fmt.Sprintf("%d.%d.%d.%d", a...)?

    我正在学习 Go 但我一直坚持 Go 之旅 exercise stringer go https tour golang org methods 7 https tour golang org methods 7 这是一些代码 type I
  • 通过 API Gateway 使用表单数据将图像发布到 Lambda 函数会导致文件无效

    I ve a 用 Go 编写的 Lambda 函数 https github com mhausenblas imgn blob master functions app uploadimg main go应该允许图像文件上传 通过 HTM
  • 带 cookie 身份验证的 Gorilla websocket

    这是我的设置 我正在构建一个带有用户登录的服务 使用 Negroni 和 Gorilla 登录后 用户会获得一个会话 cookie 服务器使用该会话 cookie 来授权受保护的端点 受保护的端点之一允许用户 客户端与服务器打开 Webso
  • golang:使用 gin 路由器服务 net.Conn

    我有一个处理传入 TCP 连接的函数 func Handle conn net Conn error 另外 我有一个初始化的 gin 路由器 带有已实现的句柄 router gin New router GET router POST Th
  • 使用 MongoDB Atlas 时 mongo-go-driver 因服务器选择超时而失败

    去版本 1 12 5 我有这个使用 node js mongo 驱动程序的代码 const MongoClient require mongodb MongoClient const uri process env MONGO HOST d
  • Go 中的切片分块

    我有一个切片 其中包含约 210 万条日志字符串 我想创建一个切片切片 其中字符串尽可能均匀分布 这是我到目前为止所拥有的 logs is a slice with 2 1 million strings in it var divided
  • Ajax 将文件上传到内容类型为 Multipart 的 GoLang 服务器

    我正在尝试使用多部分表单将音频文件上传到 Golang 服务器 然而 Go 返回错误 multipart NextPart bufio buffer full 我相信这表明我的 Javascript 请求中存在不属于多部分格式的内容 这是我
  • 使用 google.protobuf.Timestamp 在 Go 中解析带有时区偏移的日期时间戳

    我正在创建一个将使用 GRPC 和 protobuf 的 Go 应用程序 我的 RPC 服务应获取包含类型的消息google protobuf Timestamp 解析它并最终将其保存在数据库中或对其执行更多操作 我对什么被认为是该类型的有
  • 无需时间即可生成随机字符串?

    我知道如何使用 Runes 和播种 rand Init 在 go 中生成随机字符串time UnixNano 我的问题是 是否可以 使用 stdlib 在不使用当前时间戳 安全 的情况下播种 rand 此外 我问 因为仅仅依靠时间来为敏感操

随机推荐