2014-09-24 166 views
3

如果我有這樣的旅途中類型:打印圍棋類型忽略「字符串()字符串」方法

type myType ... 

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

我怎麼能打印(使用各種fmt功能)這類使用默認的表示(那就是,而不是叫String())?我想要做的是這樣的:

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

使用%#v而不是%v

這不會調用字符串()。 - 但它會調用GoString(),如果你實現它。

+0

這是Effective Go中的內容。 OP應該將該值轉換爲基礎類型,然後使用'%v'格式。看到我的答案。 – 2014-09-24 14:52:01

+1

@ Ainar-G對於類型別名,您的答案很簡單,但對於例如'輸入myType struct {myOtherType}'。 Effective Go中似乎也沒有任何內容表明%#v不是OP想要的。 – nos 2014-09-24 15:09:24

+0

你是對的,編輯我的答案。 – 2014-09-24 15:18:11

6

fmt.Stringer默認格式,當您使用%v時會調用該格式。如果您需要Go語法,請使用%#v

或者,您可以完全繞過fmt中的反射,並按照您認爲合適的方式格式化輸出。

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

如果基礎類型的myType的是一個數字,字符串或其它簡單的類型,然後在打印時轉換爲基本類型:

func (m mType) String() string { 
    return fmt.Sprint(int(m)) 
} 
2

使用%#v格式不正確的答案,如果你想讓您的基礎類型的String工作或您的類型是一個類型別名。

正如在Effective Go解釋,只是將其轉換回它所代表的類型:

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

編輯:正如其他人在評論中所指出的那樣,如果你的類型是一個結構,使用%#v格式好像除了將其轉換爲匿名結構類型與同一領域的唯一途徑。

+0

只有'myType'是一個類型別名,這才真正有幫助。更頻繁的是它本身就是一個結構。 – JimB 2014-09-24 14:59:02

+0

有沒有辦法做到這一點,不涉及顯式轉換?我的用例是我有一個結構,創建它的匿名版本只是爲了打印,然後在兩者之間進行轉換會很痛苦。 – joshlf 2014-09-24 15:01:52

+0

@JimB,synful你是對的。我會編輯我的答案。 – 2014-09-24 15:13:33