在本文中,我将介绍一些登录go的经验法则以及 您可能没有听说过的函数可以使您的调试生活变得更轻松。
规则1 –在适当的地方使用错误,而不是字符串
Go具有内置的错误类型,它使开发人员可以轻松地将错误与“正常”字符串区分开,并以更简洁的方式检查是否没有错误。 错误类型是一个接口,仅需要相关类型定义一个“ Error() ”函数即可将自身打印为字符串。
type error interface {
Error() string
}
切勿在错误更合适的地方使用普通字符串! 字符串向您的函数用户暗示“一切照旧”正在进行。 错误清楚表明出了点问题。
例如,假设我们正在构建REST API。 我们可能需要一个带有响应编写器,一条消息以及一个可用于在错误的API调用上返回错误代码的代码的函数。 这是我们的第一次尝试:
func respondWithError (w http.ResponseWriter, code int , msg string ) {
payload := map [ string ] string { "error" : msg}
response, _ := json.Marshal(payload)
w.Header().Set( "Content-Type" , "application/json" )
w.WriteHeader(code)
w.Write(response)
}
这将完美地工作。 事实上,在一个错误类型工作的字符串的任何地方可以用来代替。 但是,如果我们对编写其他开发人员可以更快地理解并做出贡献的代码感兴趣,则应使用Error类型:
func respondWithError (w http.ResponseWriter, code int , msg error) {
payload := map [ string ] string { "error" : msg.Error()}
response, _ := json.Marshal(payload)
w.Header().Set( "Content-Type" , "application/json" )
w.WriteHeader(code)
w.Write(response)
}
规则2 –换行错误
通常,我们只是将错误沿链条传递,这很方便。 例如,让我们看一下将小时和分钟格式化为时间消息的此函数:
func formatTimeWithMessage (hours, minutes int ) ( string , error) {
formatted, err := formatTime(hours, minutes)
if err != nil {
return "" , err
}
return "It is " + formatted + " o'clock" , nil
}
这里的问题是formatTime函数可以在应用程序或库中的许多其他位置调用。 如果我们要做的只是传递原始错误,那么很难说出错误在哪里被调用。 相反,让我们执行以下操作:
func formatTimeWithMessage(hours, minutes int) (string, error) {
formatted, err := formatTime(hours, minutes)
if err != nil {
return "" , fmt.Errorf( "formatTimeWithMessage: %v" , err)
}
return "It is " + formatted + " o'clock" , nil
}
另外,如果您使用的是Go 1.13或更高版本,则可以查看更明确的“ Unwrap() ”方法以查找错误链: https : //blog.golang.org/go1.13-errors#TOC_3.1。
fmt.Errorf()
fmt.Errorf()类似于fmt.Printf(),而是返回一个串的错误。 您过去可能已经这样做:
err := errors.New( "Bad thing happened! " + oldErr.Error())
使用fmt.Errorf()可以更简洁地完成此操作:
err := fmt.Errorf( "Bad thing happened! %v" , oldError)
当所涉及的格式更复杂并且包含更多变量时,可读性上的差异会变得更加明显。
格式化结构
打印结构可能非常难看且不可读。 例如,以下代码:
func main () {
make := "Toyota"
myCar := Car{year: 1996 , make : & make }
fmt.Println(myCar)
}
将打印如下内容:
{ 1996 0x40c138 }
我们可能想要获取指针中的值,并且我们可能想要查看该结构的键。 因此,我们可以在结构上实现默认的String()方法。 如果这样做,那么Go编译器将在打印时使用该方法。
func (c Car) String () string {
return fmt.Sprintf( "{make:%s, year:%d}" , *c. make , c.year)
}
func main () {
make := "Toyota"
myCar := Car{year: 1996 , make : & make }
fmt.Println(myCar)
}
它将打印如下内容:
{ make :Toyota, year: 1996 }
fmt.Println()
过去,我经常在记录日志时执行以下操作:
fmt.Printf( "%s beat %s in the game\n" , playerOne, playerTwo)
事实证明,仅使用fmt.Println()函数添加间距的功能要容易得多:
fmt.Printf(playerOne, "beat" , playerTwo, "in the game" )
谢谢阅读!
- Twitter上的车道: @wagslane
- Dev.to上的车道: wagslane
- 下载Qvault: https ://qvault.io
- 为我们的Github加上星号: https : //github.com/q-vault/qvault
From: https://hackernoon.com/logging-for-gophers-idiomatic-log-strategies-in-go-golang-ocr3tz3