proposal: Go 2: prevent variable aliasing/shadowing (original) (raw)

This is a follow up to the original proposal: #9818

The following code will alias the logw variable and introduce a bug in all the code that falls in the default label.

func OpenLogFile(lo LogOptions) (io.WriteCloser, error) {
    var logw io.WriteCloser
    switch lo.LogPath {
    case "stderr":
        logw = os.Stderr
    default:
        logw, err := openLogFileInternal(lo)
        if err != nil {
            return logw, err
        }
    }
    log.SetOutput(logw)
    return logw, nil
}

logw is declared outside the switch case (and correctly initialized to nil), but then another logw is created together with err in the default case. This will result in logw being always set to nil if the code goes through the default case.

This is a mistake that both newbie and seasonal go developers do. In my opinion, aliasing in general should be avoided in all cases, since compatibility is relevant in this first phase, maybe the := syntax could be made a bit smarter and reuse an already existing variable (at least for multiple declarations, like the one in the sample code). Alternatively, although less ideal, it would be ok if auxiliary tools like go vet could warn the user about this kind of aliasing.