...interface{} 函数参数中的“取消引用”元素

我有一个工作正常的记录器,但在内存分配方面会产生相当多的开销。下面的Debug()函数不是故意打印的,因为logOutputLevel不够高。


var logOutputLevel = 2

func Debug(s string, args ...interface{}) {

    if logOutputLevel > 1 { return }

    fmt.Printf(s, args...)

}

在向它传递值时,该方法仍然会产生相当多的分配。将指针传递给它时,它不会产生大量分配。请参阅以下基准:


func BenchmarkLog(b *testing.B) {

    x := "abc"

    for n := 0; n < b.N; n++ {

        Debug("test %s", x)

    }

}


func BenchmarkLogRef(b *testing.B) {

    x := "abc"

    for n := 0; n < b.N; n++ {

        Debug("test %s", &x)

    }

}

生产:


BenchmarkLog-8          50000000            43.1 ns/op        16 B/op          1 allocs/op

BenchmarkLogRef-8       500000000            3.17 ns/op        0 B/op          0 allocs/op

现在一切都很好,我正在尝试重新设计该Debug()方法以仅接受一个字符串和无限指针参数。稍后,fmt.Printf()如果日志级别足够高,我想“取消引用”所有参数并将它们传递给。


我怎样才能做到这一点?“仅指针”是否有特定的语言习语?我假设这...*interface{}意味着指向 an 的指针interface{}(而不是任何值都应该是指针)。


长风秋雁
浏览 115回答 1
1回答

波斯汪

阻止分配的唯一方法是首先不进行分配。这通常是通过在评估之前将调试语句放在条件块中来完成的:if logOutputLevel > 1 {     Debug("test: %s", x) }这是大多数日志记录包处理它的方式。您可以使用构建标签有条件地编译Debug函数,并完全忽略参数。语言规范不能保证不分配,但如果当前性能可以接受,编译器将来可能会进行优化。Debug使用两个单独的文件,您可以在编译时在实现之间切换:调试.go// +build debugpackage mainimport "log"func Debug(fmt string, args ...interface{}) {    log.Printf(fmt, args...)}发布.go// +build !debugpackage mainfunc Debug(_ string, _ ...interface{}) {}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go