Go 在不重新分配新切片的情况下将项附加到可变函数包装器

Go 在不重新分配新切片的情况下将项附加到可变函数包装器,go,variadic-functions,Go,Variadic Functions,好的,我需要一个fmt.Printf()的小包装,以便于调试: 1/“调用fmt.Fprintln时参数太多”: 2/“接口类型中不允许使用名称列表”: 3/工作正常,但感觉不对劲: func Debug (a ... interface{}) { if debug { sl := make ([]interface{}, len(a) + 2) sl[0] = prefix sl[1] = sep for i, v :=

好的,我需要一个fmt.Printf()的小包装,以便于调试:

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

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

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...)
    }
}

有没有办法避免分配额外内存?

没有办法避免分配额外内存

最短、最有效的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}...)
我会写:

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
函数分配相对重要


您考虑过使用吗?

我只需要打印两张:

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...))
    }
}

任何一种方法都比构建新切片更简单。

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

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

有关工作示例,请参见。对于一行程序,您也可以使用
append

func调试(一个…接口{}){
如果调试{
Fprintln(out,append([]接口{}{prefix,sep},a..}…)
}
}

len(aa)最初应该是0。好的,谢谢,我来看看日志包,似乎很有趣。回答你的问题:这并不重要,真的。这更是一个普遍的问题。谢谢你们两位的append()不过,func并不知道这一点,并且想知道如何向slices@Atom添加元素,这是为什么?它正在向len(a)+2发展,因为
aa:=make([]接口{},2+len(a))
len(aa)=2+len(a)和
cap(aa)=2+len a
。对于,
aa:+make([]接口{},0,2+len a))
len=0
cap(aa)=2+len(a)
。append从
len(aa)
开始追加。这似乎是最好的方式,不分配也不复制。
func Debug(a ...interface{}) {
    if debug {
        fmt.Fprint(out, prefix, sep, fmt.Sprintln(a...))
    }
}
func Debug(a ...interface{}) {
    if debug {
            a = append(a, 0)
            copy(a[1:], a[0:])
            a[0] = prefix + sep
            fmt.Fprintln(out, a...)
    }
}