- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有一个只有一个方法的简单结构:
type Person struct {
name string
}
func (p Person) SetName(name string) {
p.name = name
}
以下输出:
dave := Person{}
dave.SetName("Dave")
fmt.Println(dave.name)
将是空的,因为方法接收器接受一个值(或更准确地创建您传递的值的副本),因此它不会修改您的基础值。
如果我将方法更改为:
func (p *Person) SetName(name string) {
p.name = name
}
输出将是“Dave”。
现在我不明白的是我不应该在指针上调用方法吗?所以在初始化我的对象时我应该这样做:
dave := &Person{}
而不是这个:
dave := Person{}
我还尝试使用 go 的 reflect 包来找出以下值:
&Person
并发现它是 *Person,这很好。与打印指向 int 的指针的值相比,当我打印值时虽然没有获得内存位置:
a := 4
fmt.Println(&a)
我一直在阅读文档,就此提出问题,但我了解得越多,我就越想知道我是否遗漏了一些简单的东西,因为很多人认为这一切并不令人困惑。
最佳答案
您混淆了在指针接收器上调用方法与保持指向值的指针。也就是说,在指针接收器上定义的调用 SetName
与存储指针到内存中的指针之间没有内在连接,该内存包含 Person< 类型的值
与直接存储 Person
。
当你有声明时
var pers Person
然后调用
pers.SetName("foo")
编译器取其占用的内存块地址变量 pers
— 就像您通过应用程序手动执行此操作一样&
运算符到 pers
,并将该地址传递给 SetName
函数,所以调用最终会像
(&pers).SetName("foo")
或者,换句话说,SetName
的接收者将是&pers
——即pers
的地址。
现在没有什么能阻止你获取 pers
的地址并将其存储在别处:
var ptr *Person = &pers
(你通常不会写这样的 Java 风格的卡顿代码,但是我这样做是为了更加清晰),现在你可以打电话了SetName
就在 ptr
值上:
ptr.SetName("bar")
现在编译器将直接使用存储在变量ptr
中的值将其作为方法的接收者传递。
这个“谜题”的最后一点是当你使用Go 提供的特殊语法——应用地址获取运算符 &
直接转换为文字——编译器会做这样的事情:
var __pers Person = Person{
// The contents of your literal
}
var dave = &__pers
...并使 __pers
变量无法通过名称访问(因为它自然没有名字)。
如你所见,这与获取指针没有区别手动保存到 Person
值的内存中。
您可能想咨询this FAQ entry获得更多的了解该方法如何设置类型 T
和 *T
相关,以及为什么后者总是包括前者但不包括前者。另请阅读 this .
更新: 解释 fmt.Println
格式和输出方式的差异*int
和 *Person
类型的值。
int
值的内存位置的地址。&{}
。此行为已记录在案:fmt.Print
和 fmt.Println
对它们的参数使用所谓的默认格式规则被传递,这些规则取决于参数的类型。
让我们首先查阅关于fmt.Println
的文档(运行 go doc fmt.Println
):
func Println(a ...interface{}) (n int, err error)
Println
formats using the default formats for its operands and writes to standard output. Spaces are always added between operands and a newline is appended. It returns the number of bytes written and any write error encountered.
(强调我的。)
现在让我们转向fmt
包本身的文档(运行 go doc fmt
):
<…>
Printing
The verbs:
General:
%v
the value in a default formatwhen printing structs, the plus flag (
%+v
) adds field names.<…>
The default format for
%v
is:bool: %t
int, int8 etc.: %d
uint, uint8 etc.: %d, %#x if printed with %#v
float32, complex64, etc: %g
string: %s
chan: %p
pointer: %pFor compound objects, the elements are printed using these rules, recursively, laid out like this:
struct: {field0 field1 ...}
array, slice: [elem0 elem1 ...]
maps: map[key1:value1 key2:value2]
pointer to above: &{}, &[], &map[]
A *Person
是一个指向结构类型的指针,所以它呈现为
&{name}
其中name
是name字段的内容;说,如果它被分配字符串“Dave”,输出将是 &{dave}
。
关于Go struct 方法允许类型混合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49251583/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!