duandai0373 2014-10-22 09:15
浏览 27
已采纳

来自流的字符串,用于多种对象类型

I'm used to Java, and setting first steps in google go. I have a tree of objects with child objects etc... This tree is recursively dumped to an io.Writer. Output might be huge, so I don't want to create a string for each object, and concatenate the result in memory..

For debugging purposes, i want to fmt.Printf parts of this tree. Thus, I want to create a generic String() function on each object in which calls the ToStream function, returning the result as a string. In Java, this is easy: create the method on the base class. How do I do this in GO, without creating a custom String method for each kind of object.

See the code for what I want, specifically the line marked ERROR

package main

import (
"io"
"fmt"
"bytes"
)

//Base is an interface for bulk output
type Base interface {
    ToStream(io.Writer)
}

//Impl1 has interface Base
type Impl1 struct{
    stuff int
}

func (Impl1) ToStream(w io.Writer) {
    fmt.Fprintf(w, "A lot of stuff")
}

//Impl2 has interface Base
type Impl2 struct{
    otherstuff int
}

func (Impl2) ToStream(w io.Writer) {
    fmt.Fprintf(w, "A lot of other stuff")
}

//I want to convert any base to a sting for debug output
//This should happen by the ToStream method

func (v Base) String() string {//ERROR here: Invalid receiver type Base (Base is an interface type)
//func (v Impl1) String() string {//This works, but requires re-implementation for every struct Impl1,Impl2,...
    var buffer bytes.Buffer
    v.ToStream(&buffer)
    return string(buffer.Bytes())
}

func main(){
    aBase:= new(Impl1)
    fmt.Printf("%s
",aBase)
}
  • 写回答

3条回答 默认 最新

  • duanjun7801 2014-10-22 19:53
    关注

    You can wrap around a Base to add the necessary String() function. Here is one approach:

    type StreamerToStringer struct {
        Base
    }
    
    func (s StreamerToStringer) String() string {
        var buffer bytes.Buffer
        s.Base.ToStream(&buffer)
        return string(buffer.Bytes())
    }
    

    With this, you can augment any Base instance so it has a String() method.

    func main() {
        aBase1 := StreamerToStringer{new(Impl1)}
        aBase2 := StreamerToStringer{new(Impl2)}
        fmt.Printf("%s
    ", aBase1)
        fmt.Printf("%s
    ", aBase2)
    
        // These wrapped values still support ToStream().
        var buffer bytes.Buffer
        aBase1.ToStream(&buffer)
        fmt.Println(buffer.Bytes())
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改