2017-10-12 70 views
0

我想記錄一個函數的返回值。我能想出的「最聰明」的東西是將我的實際函數體封裝在一個閉包中。Golang日誌函數返回參數

func foo(a int, b int) (int, error) { 
    c, err := func (a int, b int) (int, error) { 
     //... 
     return c, err 
    }(a, b) 

    fmt.Printf("%v %v %v %v", a, b, c, err) 

    return c, err 
} 

有沒有辦法用較少的樣板來實現這一點?

+2

這只是在調試過程中,還是您希望這是您的生產代碼的功能? – Flimzy

+0

這兩個,我目前正在開發一個kubernetes集羣,並沒有得到一個調試器運行在那裏和生產它很酷,因爲你可以得到基於日誌的指標非常簡單 – 21st

+1

,並感謝刪除我的問候✌️ – 21st

回答

2

也許我誤解你的問題,但怎麼樣:

package main 

import (
    "log" 
) 

func foo(a, b int) (c int, err error) { 
    defer func() {log.Printf("%v %v %v %v", a, b, c, err)}() 
    c = a + b 
    return c, nil 
} 


func main() { 
    foo(1, 3) 
} 
+0

https://play.golang.org/p/i2ngKIp-aI – Keeto

+0

這就是錯誤。 c是4 – Keeto

+0

我的壞...閱讀... –

0

試試這個:https://play.golang.org/p/VrPgH1VUwP

基本上,你只是有一些函數,返回相同的簽名的函數來包裝他們,但包括日誌記錄:

type fooFunc func(int, int) (int, error) 

func fooLogger(f fooFunc) fooFunc { 
    return func(a, b int) (int ,error){ 
     c, err := f(a, b) 
     log.Printf("%s => a: %v, b: %v, return => c: %v, err: %v\n", fnName(f), a, b, c, err); 
     return c, err 
    } 
} 

func foo(a, b int) (int, error){ 
    c := a + b 
    return c, nil 
} 


func main() { 
    loggedFoo := fooLogger(foo) 

    //prints something like this 
    //2009/11/10 23:00:00 main.foo => a: 2, b: 2, return => c: 4, err: <nil> 
    c, err := loggedFoo(2, 2) 
    fmt.Println("from foo:", c, err) 
} 
+0

很酷的想法,我不喜歡,你總得寫了一個「記錄儀」爲每個函數簽名雖然 – 21st

0

有兩種模式,我會考慮:

  1. 由於@Keeto建議,您可以使用 '推遲' 聲明:

    func foo(a, b int) (c int, e error) { 
        defer log.Printf("%v %v %v %v\n", a, b, c, err) 
        // ... the function body 
    } 
    
  2. 一個記錄存根功能:

    func foo(a, b int) (int, error) { 
        c, err := realFoo(a, b) 
        log.Printf("%v %v %v %v\n", a, b, c, err) 
    } 
    
    func realFoo(a, b int) (int, error) { 
        // ... the function body 
    } 
    

的封蓋也適用,因爲你在你的問題中提到,但在我看來,這是選項中最不可讀的。

你選擇哪一個主要取決於偏好。在三個選項中性能應該大致相同 - 但是如果性能很關鍵,那麼在真正的應用程序負載下確保基準確定。