Go - Simplifying Repetitive Error Handling

发布时间 2023-09-29 09:56:06作者: ZhangZhihuiAAA

Problem: You want to reduce the number of lines of repetitive error - handling code.


Solution: Use helper functions to reduce the number of lines of repetitive error - handling code.

 

One of the most frequent complaints about Go’s error handling, especially from newcomers, is that it’s tedious to do repetitive checks. Let’s take, for example, this piece of code that opens a JSON file to read and unmarshal to a struct:

func   unmarshal ()   ( person   Person )   { 
      r ,   err   :=   http . Get ( "https://swapi.dev/api/people/1" ) 
      if   err   !=   nil   { 
          //  handle  error 
      } 
      defer   r . Body . Close () 

      data ,   err   :=   io . ReadAll ( r . Body ) 
      if   err   !=   nil   { 
          //  handle  error 
      } 

      err   =   json . Unmarshal ( data ,   & person ) 
      if   err   !=   nil   { 
          //  handle  error 
      } 
      return   person 
}

You can see three sets of error handling: one when you call http.Get to get the API response into an http.Response , then when you call io.ReadAll to get the JSON text from the http.Response , and finally to unmarshal the JSON text into the Person struct. Each of these calls is a potential point of failure, so you need to handle errors that result from those failures.
However, these error - handling routines are similar to each other and, in fact, repetitive. How can you resolve this? There are several ways, but the most straightforward is using helper functions:

func   helperUnmarshal ()   ( person   Person )   { 
      r ,   err   :=   http . Get ( "https://swapi.dev/api/people/1" ) 
      check ( err ,   "Calling  SW  people  API" ) 
      defer   r . Body . Close () 

      data ,   err   :=   io . ReadAll ( r . Body ) 
      check ( err ,   "Read  JSON  from  response" ) 

      err   =   json . Unmarshal ( data ,   & person ) 
      check ( err ,   "Unmarshalling" ) 

      return   person 
} 

func   check ( err   error ,   msg   string )   { 
      if   err   !=   nil   { 
          log . Println ( "Error  encountered:" ,   msg ) 
          //  do  common  error - handling  stuff 
      } 
}

The helper function here is the check function that takes in an error and a string. Besides logging the string, you can also put all the common error - handling stuff that you want to do into the function. Instead of a string, you can also take in a function as a parameter and execute the function if an error is encountered.