来自流的字符串去多个对象类型

时间:2014-10-22 09:15:54

标签: go

我已经习惯了Java,并在google go中设置了第一步。我有一个带有子对象等的对象树...这个树被递归地转储到一个io.Writer。输出可能很大,所以我不想为每个对象创建一个字符串,并将结果连接到内存中。

出于调试目的,我想fmt.Printf这个树的一部分。因此,我想在每个调用ToStream函数的对象上创建一个通用的String()函数,并将结果作为字符串返回。在Java中,这很容易:在基类上创建方法。如何在GO中执行此操作,而无需为每种对象创建自定义String方法。

查看我想要的代码,特别是标记为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\n",aBase)
}

3 个答案:

答案 0 :(得分:3)

似乎Java思维阻止了你: - )

虽然Java只有方法,但 具有函数。当然,你不能在接口上有方法,但你可以使用Base做一个简单的函数并做一些事情:

func Base2String(b Base) string {
    var buffer bytes.Buffer
    b.ToStream(&buffer)
    return string(buffer.Bytes())
}

现在,如果您将Base重命名为Go-ish(请记住Go中没有类型层次结构),您可以使用一些不错的代码。

答案 1 :(得分:1)

您可以环绕Base以添加必要的String()函数。这是一种方法:

type StreamerToStringer struct {
    Base
}

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

有了这个,您可以扩充任何Base实例,使其具有String()方法。

func main() {
    aBase1 := StreamerToStringer{new(Impl1)}
    aBase2 := StreamerToStringer{new(Impl2)}
    fmt.Printf("%s\n", aBase1)
    fmt.Printf("%s\n", aBase2)

    // These wrapped values still support ToStream().
    var buffer bytes.Buffer
    aBase1.ToStream(&buffer)
    fmt.Println(buffer.Bytes())
}

答案 2 :(得分:0)

首先打电话更容易:

fmt.Printf("%+v\n", yourProject)

查看打印的信息是否足以开始:fmt package提及

  

打印结构时,加号标志(%+ v)添加字段名称

如果这还不够,那么你必须使用反射,就像我在“Golang - How to print struct variables in console?”中提到的那样。

或者您可以查看项目davecgh/go-spew(在“Go-spew: A Journey into Dumping Go Data Structures”中提及)

  

Go-spew为Go数据结构实现了一个非常漂亮的打印机,以帮助调试

spew.Dump(myVar1, myVar2, ...)
spew.Fdump(someWriter, myVar1, myVar2, ...)
str := spew.Sdump(myVar1, myVar2, ...)

那将打印出如下内容:

(main.Foo) {
 unexportedField: (*main.Bar)(0xf84002e210)({
  flag: (main.Flag) flagTwo,
  data: (uintptr) <nil>
 }),
 ExportedField: (map[interface {}]interface {}) {
  (string) "one": (bool) true
 }
}
([]uint8) {
 00000000  11 12 13 14 15 16 17 18  19 1a 1b 1c 1d 1e 1f 20  |............... |
 00000010  21 22 23 24 25 26 27 28  29 2a 2b 2c 2d 2e 2f 30  |!"#$%&'()*+,-./0|
 00000020  31 32                                             |12|
}