2016-09-27 36 views
1

Golang noob問題:爲什麼我不是使用"%+v"標誌爲String()實現方法中的結構?struct String()實現導致堆棧溢出與Sprintf「+」標誌

我有一個結構,我想實現漂亮打印的String()方法。我喜歡給出的答案here,但我不喜歡輸入,所以我試圖修改它以返回一個字符串,其格式標記爲"%+v"。從fmt DOC:

%V的默認格式值打印時結構,加標誌 (%+ V)將字段名

這工作得很好,如果我簡單地叫它fmt.Printf("%+v", color),但如果我嘗試把+國旗在String()執行,我得到一個堆棧溢出(我第一次有機會問一個「堆棧溢出」的問題上stackoverflow.com;))

我敢肯定,我」沒有理解這裏的指針引用,或者有s遞歸。我懷疑這個noob找到了我的第一個Golang錯誤,那麼有人能解釋一下嗎?

看到去這裏https://play.golang.org/p/13_qI8Iwwa

回答

6

發揮示範見Package fmt Docs:在使用動詞%T%p,特殊格式 考慮適用於實現某些接口的操作數印刷

除外。 在應用的順序:

  • 如果操作數實現方法String() string,該方法將被調用,以將對象轉換爲一個字符串,然後,這將是 格式化爲所要求的動詞(如果有的話)。
  • 爲了避免遞歸在諸如

    type X string 
    func (x X) String() string { return Sprintf("<%s>", x) } 
    

    轉換值重複之前:

    func (x X) String() string { return Sprintf("<%s>", string(x)) } 
    

    無限遞歸也可以通過自引用數據 結構觸發,如作爲包含其自身作爲元素的切片,如果該類型具有String方法,則爲 。然而,這樣的病態很少見,並且該包不能防止它們發生。


    內幕:

    func (c Color) String() string { 
        // THIS CAUSES STACK OVERFLOW 
        return fmt.Sprint(c) 
    } 
    

    的調用

    fmt.Sprint(c) 
    

    fmt.Println(c)再次呼籲func (c Color) String() string遞歸導致溢出:試試The Go Playground


    此外這工作正常:https://play.golang.org/p/NYLtrxUeiA

    +1

    Thanks @amd。你最初的答案指出了明顯的遞歸......但是使用新字符串('string(x)')失去了結構引用,所以仍然沒有辦法使用「+」標誌......但是,你的解決方案在你的操場使用String()方法中的「#」標誌使用Go的「語法表示」,爲我提供了標籤,並避免了遞歸。謝謝! – Merl