将项附加到可变参数函数包装器而不重新分配新切片

时间:2011-12-22 14:42:07

标签: go variadic-functions

好的我需要一个fmt.Printf()的小包装来调试方便性:

1 /“调用fmt.Fprintln的参数太多了”:

func Debug (a ... interface{}) {
    if debug {
        fmt.Fprintln(out, prefix, sep, a...)
    }
}

2 /“接口类型中不允许使用名称列表”:

func Debug (a ... interface{}) {
    if debug {
        fmt.Fprintln(out, []interface{prefix, sep, a...}...)
    }
}

3 /工作,但感觉不对:

func Debug (a ... interface{}) {
    if debug {
        sl := make ([]interface{}, len(a) + 2)
        sl[0] = prefix
        sl[1] = sep
        for i, v := range a {
            sl[2+i] = v
        }

        fmt.Fprintln(out, sl...)
    }
}

任何避免分配额外内存的想法?

5 个答案:

答案 0 :(得分:4)

我会做两次打印:

func Debug(a ...interface{}) {
    if debug {
        fmt.Fprint(out, prefix, sep)
        fmt.Fprintln(out, a...)
    }
}

如果你认为你需要拨打一次Fprint电话,你可以这样做,

func Debug(a ...interface{}) {
    if debug {
        fmt.Fprint(out, prefix, sep, fmt.Sprintln(a...))
    }
}

建立新切片似乎更简单。

答案 1 :(得分:3)

我会写:

func Debug(a ...interface{}) {
    if debug {
        aa := make([]interface{}, 0, 2+len(a))
        aa = append(append(aa, prefix, sep), a...)
        fmt.Fprintln(out, aa...)
    }
}

分配仅在调试模式下进行,那么为什么Debug函数分配的数量很重要?

Go fmt套餐因其一般性而价格昂贵;它使用反射,它分配,它做I / O.为什么Debug函数分配相对重要?

您是否考虑过使用Go log package

答案 2 :(得分:2)

可变参数可用作切片,因此无需分配新参数:

func Debug(a ...interface{}) {
    if debug {
            a = append(a, 0)
            copy(a[1:], a[0:])
            a[0] = prefix + sep
            fmt.Fprintln(out, a...)
    }
}

有关工作示例,请参阅http://play.golang.org/p/xXEO58BJoA

答案 3 :(得分:1)

无法避免分配额外的内存。

最短且最有效的Go代码似乎是:

func Debug (a ...interface{}) {
    if debug {
        b := make([]interface{}, 0, 2+len(a))
        b = append(b, prefix, sep)
        b = append(b, a...)
        fmt.Fprintln(out, b...)
    }
}

次要注意:在您的第二个示例中,您错过了{}:

fmt.Fprintln(out, []interface{}{prefix, sep}...)

答案 4 :(得分:1)

您还可以将append用于单线:

func Debug (a ... interface{}) {
    if debug {
        fmt.Fprintln(out, append([]interface{}{prefix, sep}, a...}...)
    }
}