ffyns
ffyns

Reputation: 479

Managing errors in golang

I'm coming from Ruby and looking at Go at the moment. I start writing a little bit of code to check TLS support for a given host.

var tls_versions = map[uint16]string{
  tls.VersionSSL30:  "SSLv3",
  tls.VersionTLS10:  "TLSv1.0",
  tls.VersionTLS11:  "TLSv1.1",
  tls.VersionTLS12:  "TLSv1.2",
}

var refused_re = regexp.MustCompile(": connection refused")
var nodns_re = regexp.MustCompile(": no such host")
var versionnotsupported_re = regexp.MustCompile(": protocol version not supported")

func checkversion(host string) (map[string]bool, error) { // {{
  ret := map[string]bool{}

  for version := tls.VersionSSL30; version <= tls.VersionTLS12; version++ {
    conn, err := tls.Dial("tcp", host+":443", &tls.Config{
       MinVersion: uint16(version),
    })

    if err != nil && 
        (refused_re.MatchString(err.Error()) == true || nodns_re.MatchString(err.Error()) == true) { 
      log.Println(err)
      return ret, err
    }

    if err != nil && versionnotsupported_re.MatchString(err.Error()) == true  {
      ret[tls_versions[uint16(version)]] = false
      log.Println("Not supported: "+host+"  "+tls_versions[uint16(version)])
    }
    ret[tls_versions[uint16(version)]] = true

    if conn != nil {
      conn.Close()
    }
  }
  return ret, nil
} 

Coming from Ruby I found the error management in this code pretty ugly as I'm one typo/change away from not getting the right reason for the error. I tried to play with reflect but couldn't get it to do what I wanted. I was wondering if I was missing something obvious or if it was the go way? Or is it specific to the crypto/tls library to avoid recovering from any issue?

Thanks for your help.

Upvotes: 1

Views: 872

Answers (1)

icza
icza

Reputation: 417402

There is possibility for good error management in Go.

See this answer by Dave C for a nice summary and good examples.

Unfortunately in case of the tls package, you're out of luck. The errors you try to detect are generated by fmt.Errorf() calls (which delegate to errors.New()) so they are not special in any way and they are not pre-declared so you can't do significantly better than your current solution to distinguish them. Probably the developers were lazy to provide more sophisticated or more easily traceable errors or simply they thought it is not important and left out for simplicity; so they currently serve more like informational for the developer.

Further reading (quoted from Dave C's answer):

Upvotes: 3

Related Questions