Home  >  Article  >  Backend Development  >  Why Does Changing a Method Receiver from Pointer to Non-Pointer Lead to a Dead Loop When Using `fmt.Sprintf`?

Why Does Changing a Method Receiver from Pointer to Non-Pointer Lead to a Dead Loop When Using `fmt.Sprintf`?

DDD
DDDOriginal
2024-11-16 01:10:02151browse

Why Does Changing a Method Receiver from Pointer to Non-Pointer Lead to a Dead Loop When Using `fmt.Sprintf`?

Understanding the Difference Between t and *t

In this code snippet, we have a type TT with a String method that implements the fmt.Stringer interface:

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())
}

This code works because the fmt package invokes the String method to get the string representation of the TT value.

However, when the String method is modified to take a non-pointer receiver:

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

it causes a dead loop. Let's explain why:

Calling fmt.Sprintf("% v", t) passes a *TT (pointer to TT) value to the fmt package. Since the TT.String method has a pointer receiver, the fmt package will not find this method in the method set of the *TT type.

Changing the receiver to a non-pointer type means that the fmt package will find the String method in the method set of TT. However, this leads to infinite recursion because the method being called is the same one that is being used to format the value.

To avoid this issue, a new type can be created using the type keyword, effectively separating the receiver type from the value being passed to the fmt package:

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

This works because the new type created by the type keyword doesn't have any methods, so the fmt package won't try to invoke the String method on the new type.

The above is the detailed content of Why Does Changing a Method Receiver from Pointer to Non-Pointer Lead to a Dead Loop When Using `fmt.Sprintf`?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn