当前位置: 首页 > 面试题库 >

t和* t之间的差异

冯渝
2023-03-14
问题内容

package main

import "fmt"

type TT struct {
    a int
    b float32
    c string
}

func (t *TT) String() string {
    return fmt.Sprintf("%+v", *t)
}

func main() {
    tt := &TT{3, 4, "5"}
    fmt.Printf(tt.String())
}

该代码可以很好地工作。但是,如果String按如下所示更改方法,则会导致死循环。区别在于将*t替换为t。为什么?

func (t *TT) String() string {
    return fmt.Sprintf("%+v", t)
}

问题答案:

因为fmt程序包检查要打印的值是否具有String() string方法(或换句话说:是否实现fmt.Stringer接口),如果是,则将调用它以获取string值的表示形式。

fmt软件包doc中对此进行了说明:

[…]如果操作数实现String()字符串方法,则将调用该方法将对象转换为字符串,然后根据动词的要求对其进行格式化(如果有)。

这里:

return fmt.Sprintf("%+v", *t)

您正在将*t类型的值传递TTfmt包。如果该TT.String()方法具有指针接收器,则该类型的方法集TT
不包含String()方法,因此fmt程序包将不会调用它(仅*TT包含它的方法集)。

如果更改接收到非指针类型,那么该类型的方法集TT 将包括
String()方法,所以fmt包将调用,但这是我们目前正处在的方法,所以这是一个无休止的“间接递归”。

预防/保护

如果由于某种原因您确实需要使用与传递给fmt包的值的类型相同的接收器类型,避免这种情况/避免这种情况发生的一种简单而通用的方法是type使用关键字创建一个新类型,并使用type
传递的值的转换:

func (t TT) String() string {
    type TT2 TT
    return fmt.Sprintf("%+v", TT2(t))
}

在Go Playground上尝试一下。

但是为什么这样做呢?因为type关键字创建了一个新类型,并且该新类型将具有 零个 方法(它不会“继承”基础类型的方法)。

这会产生一些运行时开销吗?编号。引用自规范:类型声明:

特定规则适用于数字类型之间或字符串类型之间的(非恒定)转换。这些转换可能会更改的表示形式x并产生运行时成本。
所有其他转换只会更改类型,而不会更改的表示形式x



 类似资料:
  • 问题内容: 在我编写的测试案例中,字符串比较似乎在SQL Server / .NET CLR之间的工作方式不同。 此C#代码: 将输出: 此SQL Server代码: 将输出: 为什么会有所不同? 问题答案: 这在此处记录。 Windows归类(例如)使用Unicode类型的归类规则。SQL排序规则没有。 这导致在两者之间对连字符的区别对待。

  • 我一直在学习如何使用java编程,但我还没有明确解释的和方法的区别。第二个只是将LinkedList对象中的所有元素作为数组返回,对吗?但是,第一个呢? 编辑: 我的意思是,我从甲骨文中阅读了文档,它说: 返回一个数组,其中包含此列表中所有元素的正确顺序(从第一个元素到最后一个元素);返回数组的运行时类型是指定数组的运行时类型。如果列表适合指定的数组,则返回该数组。否则,将使用指定数组的运行时类型

  • 当扩展在其他板条箱中定义的特性时,似乎有两种默认实现新特性的方法。 性状的原始定义是 为了扩展该特征的功能,我们定义了一个特征, 现在,由于我们希望该功能在默认情况下可用,我们可以实现以下功能 我所观察到的是,当与trait对象混合时,这两种实现都是必需的。 我理解

  • 问题内容: 可能有人解释一下这两个符号之间的细微差别:和。 看起来这两者之间的唯一区别是它返回nil指针或不返回任何指针,但仍为Struct的所有字段分配内存。 问题答案: 这两种形式的和是完全等效的:两个分配零T和一个指针返回到该分配的内存。唯一的区别是,对于像; 这样的内置类型不起作用。你只能做。 该表格并 没有 分配它只是返回一个零指针T.你仅仅是一个混淆的惯用的变种。

  • \t

    描述 (Description) 字符\t匹配制表符。 例子 (Example) 以下示例显示了字符匹配的用法。 package com.wenjiangs; import java.util.regex.Matcher; import java.util.regex.Pattern; public class CharactersDemo { private static final St

  • 问题内容: 很快就有两个相等运算符:double equals( )和Triple equals( ),两者之间有什么区别? 问题答案: 简而言之: 操作员检查其实例值是否相等, 操作员检查引用是否指向同一实例, 长答案: 类是引用类型,可能有多个常量和变量在幕后引用类的同一单个实例。类引用保留在运行时堆栈(RTS)中,其实例保留在内存的堆区域中。当您控制平等时, 这意味着它们的实例是否彼此相等。