5

If I have a type in go like this:

type myType ...

func (m myType) String() string { ... }

how can I print (using the various fmt functions) this type using the default representation (that is, instead of having String() called)? What I'd like to do is something like this:

func (m myType) String() string {
    // some arbitrary property
    if myType.isValid() {
        // format properly
    } else {
        // will recurse infinitely; would like default
        // representation instead
        return fmt.Sprintf("invalid myType: %v", m)
    }
}

3 Answers 3

6

fmt.Stringer is the default format, which is called when you use %v. If you want the Go syntax, use %#v.

Alternatively, you can bypass the reflection in fmt altogether, and format your output as you see fit.

func (m myType) String() string {
    return fmt.Sprintf("{Field: %s}", m.Value)
}

If the underlying type of myType is a number, string or other simple type, then convert to the underlying type when printing:

func (m mType) String() string {
    return fmt.Sprint(int(m))
}
Sign up to request clarification or add additional context in comments.

Comments

5

Use %#v instead of %v

That will not invoke String(). - but it will invoke GoString() if you implement it.

2 Comments

This was covered in Effective Go. OP should convert the value to the underlying type and then use %v format. See my answer.
@Ainar-G Your answer is trivial for a type alias, but doesn't become straight forward for e.g. type myType struct { a myOtherType}. There also doesn't seem to be anything in Effective Go that indicates %#v is not what the OP wants.
2

Using %#v format is not the correct answer if you want to get your underlying type's String to work or your type is a type alias.

As is explained in Effective Go, just convert it back to the type it represents:

type Foo int

func (f Foo) String() string {
    if f == 0 {
        return "foo"
    }
    return fmt.Sprintf("%v", int(f)) // N.B.
}

func main() {
    fmt.Println(Foo(0))
    fmt.Println(Foo(42))
}

Playground.

EDIT: As others have pointed out in the comments, if your type is a struct, using %#v format seems like the only way besides converting it to an anonymous struct type with same fields.

2 Comments

This only really helps though if myType is a type alias. More frequently it's a struct itself.
Is there any way to do this that doesn't involve explicit conversion? My use case is that I have a struct, and it'd be a pain to create an anonymous version of it just for printing and then convert between the two.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.