在 Go 中,将接收者变量命名为“self”是误导还是好的做法?

2024-01-05

我看过相当多的关于 Go 的博客和视频,据我记得,没有一个作者在编写方法时使用“self”或“this”作为接收者变量。然而,似乎有很多关于堆栈溢出的问题可以做到这一点,这让我思考这是否会误导将变量命名为“self”?

阅读规格方法集 https://golang.org/ref/spec#Method_sets无论如何都没有提供任何证据(以我的解释)。

我似乎记得在某个地方发现它并不是真正的自我指针,任何人都可以列出证据或提供推理,以及如果将其视为“自我”可能会出现任何问题/陷阱?

一个简单的例子:

type MyStruct struct {
    Name string
} 

哪种方法更合适,或者两者兼而有之?

func (m *MyStruct) MyMethod() error {
    // do something useful
}

or

func (self *MyStruct) MyMethod() error {
    // do something useful
}

除了别人说的(特别是PeterSO and dskinner-在他对彼得的回答的评论中),请注意几件重要的事情:

您可以像调用简单函数一样调用方法

在Go中,你可以调用any方法函数不是作为接收器上的方法,而是作为常规函数 - 只需用它定义为方法的类型的名称来限定其名称即可明确地向它传递一个接收者参数(从方法中获取一个简单的函数称为 用一个方法表达式 https://golang.org/ref/spec#Method_expressions).

展示:

package main

import "fmt"

type Foo int

func (f Foo) Bar() {
    fmt.Printf("My receiver is %v\n", f)
}

func main() {
    a := Foo(46)
    a.Bar()
    b := Foo(51)
    Foo.Bar(b)
}

(游乐场链接。 http://play.golang.org/p/hGDELp3OBA)

运行时,该程序打印:

My receiver is 46
My receiver is 51

如你看到的,self在这里失去了它的神圣意义,因为你刚刚调用了一个方法人为地为其构建上下文,这与经常引用的“调用对象的方法是将消息传递给该对象”的概念无关。

回顾一下,在 Go 中,方法只是一个在语义上绑定到特定类型的函数,它接收一个额外的参数(它的接收者),无论它是如何调用的。与许多其他主流语言相反,Go 并没有隐藏这一事实。

接收器不一定是mutable在其类型定义的方法内

正如我的示例所示,我定义了一个方法,Bar(),在非指针接收器上,如果您尝试向接收器分配一个值,该值将成功但不会影响调用者,因为接收器(与 Go 中的所有内容一样)已按值传递(因此整数已刚刚被复制)。

为了能够改变方法中接收者的值,您必须在适当类型的指针上定义它,例如

func (f *Foo) Bar() {
    // here you can mutate the value via *f, like
    *f = 73
}

再次,您可以看到使用self意思是“我”,“我的内部”在这里变得毫无意义:在我的示例中,该方法仅接收一个它知道的类型的值。您可以看到这与许多面向对象语言形成鲜明对比,在许多面向对象语言中,对象是通常通过引用传递的黑匣子。在 Go 中,您几乎可以在任何东西上定义方法(包括其他方法 http://play.golang.org/p/eeT3WXFHH3,这是由net/http顺便说一下,标准包)这削弱了“方法是针对对象的”概念。

不同的方法集可能在不同的时间适用于相同的值

在 Go 中,方法是围绕特定类型对功能进行分组的便捷方法,并且不同的方法集可能适用于程序流的不同点中的相同值。结合他们提供的接口和鸭子类型,这个概念确实蓬勃发展。这个想法是,在 Go 中,有一种定义“支持”类型的习惯用法,这些类型对其他类型的值执行某些操作。

一个很好的例子是标准套餐sort http://golang.org/pkg/sort/:例如,它提供了类型IntSlice它允许您对整数切片(类型的值)进行排序[]int。为此,您可以将切片类型转换为sort.IntSlice结果得到的值有一整套用于对切片进行排序的方法,同时你的价值的内在表现并没有改变- 因为sort.IntSlice is 定义为type IntSlice []int http://golang.org/pkg/sort/#IntSlice。在每个方法中IntSlice类型,很难将它们的接收者值的含义与self——仅仅因为该类型的存在只是为了为另一种类型提供一组方法;从哲学意义上来说,这种实用类型没有“自我”的概念;-)

结论

所以我想说,让事情在你的头脑中保持简单,不要试图用它不具备的语义“超载”Go 所采用的清晰简单的方法。明确地说明它提供的。

还有一点注意。我个人对 Go 习语的看法是,Go 最重要的特性是它的实用性(而不是理想主义等),所以如果你看到一些“感觉”不自然的概念,请尝试解决why它就是这样设计的,大多数时候你会发现为什么这个概念会在你的大脑中“点击”并变得自然。 (我必须承认,要理解 Go 中的方法来解决这个特殊问题,需要对C将会有很大帮助。)

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

在 Go 中,将接收者变量命名为“self”是误导还是好的做法? 的相关文章

  • 使用Golang登录私有站点并提取信息

    我尝试使用 golang 登录网站的私人区域并提取一些信息 但我似乎不太正确 我设法获取登录页面以获取 csrf 令牌 然后将 csrf 令牌与登录信息一起发布到登录页面 然后我就可以正常登录了 如果我在此时停止 我可以看到我被重定向的页面
  • log4go的异常行为

    我找到了log4go http code google com p log4go w list包有时会丢失日志 以下是一个简单的代码片段 我移动了log4go目录 因此以下导入就可以了 package main import log4go
  • Go (golang),Windows 上的文件 uid

    是否可以在 Windows 上获取文件的 UID 所有者 我尝试使用FileInfo Sys 但它只适用于Linux 我真的很困惑这个问题 不知道如何获取 UID 第一个问题是 Windows 本机支持文件 目录所有权的文件系统没有 所有者
  • 无法将 go tool pprof 与现有服务器一起使用

    我有一个现有的 http 服务器 我想对其进行分析 我已经包括了 net http pprof 到我的导入 并且我已经运行了 http 服务器 router createRouter server http Server Addr 8080
  • 在 Windows 上安装 gokogiri 时找不到错误 libxml2

    我正在尝试安装gokogiri https github com moovweb gokogiri在 Windows 8 机器上按照 github 页面中的说明进行操作 安装 sudo apt get install libxml2 dev
  • 关于堆栈分配,Go 中什么被视为“小”对象?

    代码 func MaxSmallSize a make int64 8191 b make int64 8192 a b 然后运行go build gcflags m 2 gt 1检查内存分配详细信息 结果 mem go 10 can in
  • Lua:冒号符号、“自我”和函数定义与调用

    我对定义 调用 Lua 函数时使用的冒号表示法感到非常困惑 我以为我已经明白了 直到我看到这段代码 function string PatternSafe str return str gsub pattern escape replace
  • 将 nil 字符串指针设置为空字符串

    如何将类型中字符串指针的引用值设置为空字符串 考虑这个例子 package main import fmt type Test struct value string func main t Test nil if t value nil
  • 如何根据其他 JSON 值获取 JSON 值

    我在 Go 中有一个来自 XML resp body 的结构 pdp sellableUnits attributes id 22555278 type size value 03 5 type sizeJ struct PDP struc
  • 为什么net.DialTimeout一半的时候会超时?

    这是我的测试代码 我设置了6s超时 但是程序只执行了3s 为什么 package main import net import time import fmt func main fmt Println time Now conn err
  • 如何使用 Go 的 flag 包打印位置参数的用法?

    鉴于这个简单的 Go 程序只需要一个命令行参数 我该如何改进它以便flag Usage 给出有用的输出 package main import flag fmt os func main flag Parse if len flag Arg
  • golang:无法从内存不足崩溃中恢复

    在某些情况下 调用append 会触发内存不足恐慌 并且append 本身似乎不会返回nil 我怎样才能避免这种恐慌情况并向我的用户显示 资源暂时不可用 此致 你不能 如果运行时无法为追加分配内存 则可能无法恢复或向用户传达 资源暂时不可用
  • Golang:我可以投射到 chan 接口吗{}

    我正在尝试为订阅编写一个通用包装器 例如 type Subscriber interface Subscribe addr string chan interface 假设有一个我想使用的库 其中有一个 subscribe 方法 但它使用c
  • golang - 省略 json 属性进行序列化的优雅方法

    我有一个用户结构 其中包含密码等敏感字段 type User struct UID string json uid binding required Password string json password binding require
  • sync.WaitGroup 的示例正确吗?

    这个例子的用法是sync WaitGroup正确的 它给出了预期的结果 但我不确定wg Add 4 和位置wg Done 一次添加四个 goroutine 是否有意义wg Add http play golang org p ecvYHii
  • 如何在 Go 中解组可以是数组或字符串的字段?

    我正在尝试解组该文件 babel email protected cdn cgi l email protection licenses MIT repository https github com babel babel tree ma
  • 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 我只是好奇 因为该文件存在并且已正确打包 但
  • 是否可以从 JS 显式调用导出的 Go WebAssembly 函数?

    是否可以调用 Go WebAssembly 函数 除了main 在 JavaScript 中 让我先展示一下我做了什么 我的Go函数定义如下 package main import fmt func main fmt Println it
  • 接口实现中的非接口方法

    我有一个定义方法的接口 我有一个结构实施这个界面 在其中 我实现了该接口中的方法 并且还定义了其他方法 例如 package main import fmt type Animal interface MakeNoise type Dog

随机推荐

  • 递归删除数组键前缀

    我有一个以下格式的数组 每个子数组都以父级的键作为前缀 input array seo text gt array seo text title gt seo text description gt seo text button gt a
  • 一键上传文件

    如何在需要发送文件的 html 中制作一个按钮 允许您选择文件 然后将其发送到我想要的页面上 而不使用按钮来选择文件并使用按钮将其发送到另一个页面 感谢您
  • python3.6 - TypeError:write() 参数必须是 str,而不是 bytes - 但不涉及文件

    以下代码返回错误 我不明白为什么 在Python 3 6上运行 import subprocess import sys import os def execute shell cmd cmd process subprocess Pope
  • Qt 上的“GLib-ERROR **:无法创建管道主循环唤醒:打开的文件太多”

    我正在 Ubuntu 上工作 当我运行程序大约 1 小时后 我收到此错误 GLib ERROR 无法创建管道主循环唤醒 打开的文件太多程序意外完成 当我使用 gdb 运行时 它不会崩溃 我不明白为什么 以及此错误的原因是什么 非常感谢 打开
  • 后台模式下的 iOS 区域监控

    我在我的应用程序中使用区域监控 但遇到了一个问题 但找不到任何答案 区域监控在后台模式下如何工作 根据位置感知 PG 的说法 每次用户的当前位置 跨越边界区域 系统 生成适当的区域事件 为您的应用程序 如果你的 应用程序已经在运行 这些 活
  • 寻找一个 Perl 模块来在共享 RAM 中存储哈希结构

    我想将数据结构持久存储在 RAM 中 并可以从预分叉中访问它 Perl 中的 Web 服务器进程 理想情况下 我希望它的行为类似于 memcached 但不需要单独的守护进程 有任何想法吗 Use 缓存 FastMmap http sear
  • 定义中的预处理器指令? [复制]

    这个问题在这里已经有答案了 可能的重复 C 预处理器 在 define 中使用 if https stackoverflow com questions 2831934 c preprocessor using if inside defi
  • 检测零分和交叉中获胜的比赛

    我需要知道在圈和十字游戏中检测获胜动作的最佳方法 源代码并不重要 我只需要一个示例或可以开始的东西 我唯一能想到的就是使用循环并测试玩家所做的每个动作的每个方向 以搜索例如连续五个 有没有更快更有效的方法呢 真正简单的解决方案是从最后一步开
  • Haskell 中的多核编程 - Control.Parallel

    我正在尝试学习如何使用Control Parallel模块 但我认为我没有理解正确 我正在尝试运行以下代码 fibs hs import Control Parallel fib Int gt Int fib 0 0 fib 1 1 fib
  • 如何使用 Java 8 中的流将列表中的对象按属性分组到其他列表中?

    我想对包含以下内容的对象列表进行分组time属性分为 5 分钟间隔 最好使用流和收集器 我在 StackOverflow 上找到的唯一可能的解决方案是计算我需要多少个间隔 子列表 将每个对象添加到每个列表中 并过滤掉不适合相应时间范围的对象
  • php中如何检查文件路径是否为图像?

    我有一个表存储 images documents pdf 等的文件路径 我的查询是 Select File Paths from Uploads 现在我如何使用 PHP 检查文件路径是否是图像 如果是图像我必须查看它或下载它 老好获取图像大
  • 有没有一种干净的方法来阻止 windows.h 创建近和远宏?

    在 WinDef h 的深处有一段来自分段内存时代的遗迹 define far define near 如果您尝试使用近或远作为变量名称 这显然会导致问题 有什么干净的解决方法吗 其他然后重命名我的变量 您可以安全地取消定义它们 这与其他人
  • 将用户控件添加到 wpf 窗口

    我创建了一个用户控件 但是当我将其添加到窗口中的 XAML 时 Intellisense 不会拾取它 并且我不知道如何将其添加到窗口 您需要在窗口标签内添加引用 就像是 xmlns controls clr namespace YourCu
  • 在 C# 中支持 VB.NET 的导入命名空间功能

    我习惯VB NET 我正在学习的游戏源代码是用C 编写的 我觉得很烦人 我必须添加using System Diagnostics到源代码以便输入Debug WriteLine 我在项目属性下进行了检查 但找不到允许我将命名空间添加到导入的
  • Spring框架是否支持多部分请求中的流模式

    我在中找不到任何指示Spring文档 http static springsource org spring docs 1 2 x reference mvc html它支持在处理多部分请求的 MultipartHttpServletReq
  • 如何强制 Internet Explorer 使用元标记中给出的编码?

    我正在尝试准备一个包含英语和阿拉伯语混合内容的演示 html 页面 基本上它包含一个小桌子 左边是英语短语 右边是阿拉伯语翻译 因为我不懂阿拉伯语 所以我从 中取出了阿拉伯字母的前三个字符统一码参考 http www unicode org
  • 如何在 Visual Studio 2013 调试会话期间编辑日期时间变量

    如果我放置断点并导致代码执行在我希望测试 DateTime 变量值的行暂停 则 Visual Studio 2013 调试器将以 10 1 2017 12 的形式显示 DateTime 变量的值 00 00 AM 当我悬停它甚至允许我开始编
  • 如何从分离的视图控制器中呈现视图控制器?

    我试图以模态方式呈现一个视图控制器并获得著名的Presenting view controllers on detached view controllers is discouraged错误 我进行了研究 一致的解决方案似乎是由家长进行演
  • sk paymentqueue canmake payment内存泄漏检查

    I run Instrument去检查Leaks在我的应用程序中 又有 1 条新泄漏 SKPaymentQueue canMakePayments 每次启动时甚至没有调用付款代码 根据这个日期 SKPaymentQueue s CanMak
  • 在 Go 中,将接收者变量命名为“self”是误导还是好的做法?

    我看过相当多的关于 Go 的博客和视频 据我记得 没有一个作者在编写方法时使用 self 或 this 作为接收者变量 然而 似乎有很多关于堆栈溢出的问题可以做到这一点 这让我思考这是否会误导将变量命名为 self 阅读规格方法集 http