skip to Main Content
  • I am using VSCode 1.87.2, OS is Ubunu 23.10
  • Using Go extension v0.41.2
  • I disabled all other extensions for testing purposes
  • Using go1.21.0 linux/amd64

I write this snippet of code in my *.go Golang files:

switch {
  case myString == "":
    fmt.Println("Empty string")
  case myString == "foo":
    doFoo()
  case myString == "bar":
    fmt.Println("We got bar now!")
  default:
    fmt.Println("Another default")
}

And VS code is formatting it as:

switch {
case myString == "":
  fmt.Println("Empty string")
case myString == "foo":
  doFoo()
case myString == "bar":
  fmt.Println("We got bar now!")
default:
  fmt.Println("Another default")
}

Question, is there a way I conf configure VSCode / Go extension / other in a REASONABLE (i.e. without to have to write my own VS Code extension or hack around unusual odd settings) so that the formatting of the snippet 1 can be preserved?

What I tried:

  • Tried formatters: gofumpt, gofmt, goimports
  • Tried disabling all extensions (except go).

Not sure what is wrong.

2

Answers


  1. It is, indeed, the Go style to not indent inside a switch for some reason, possibly a hold over from C styles. For example, this is the style used in Effective Go. In addition, the Go community is generally against changing the style and their tools generally are not configurable. VSCode’s own language server and all your mentioned Go tools will follow this style.

    However, goformat will let you adjust the style. For example, indent=2 switch enter=1 will give you a more familiar style with 2 character whitespace indentation and switch blocks will be indented.

    goformat.exe -style "indent=2 switch enter=1" .tmptest.go
    
    package main
    
    import "fmt"
    
    func main() {
      myString := "foo"
    
      switch {
        case myString == "":
          fmt.Println("Empty string")
        case myString == "foo":
          fmt.Println("foo")
        case myString == "bar":
          fmt.Println("We got bar now!")
        default:
          fmt.Println("Another default")
      }
    }
    

    VSCode can be configured to use goformat. In the Go extension search for "Format Flags" and "Format Tool". You can put your style choices into a file and commit it with your project.

    Login or Signup to reply.
  2. VS Code is not formatting your code. At least not directly.

    The GoLang extension is responsible for formatting and will format your code whenever you save a file. By default, it uses gofmt, the ubiquitous and highly opinionated formatter adopted by most Go developers.

    Yes, the extension provides a setting to enable this to be configured to use an alternate formatter if you insist. But IMHO, the best advice is to learn to work with and appreciate the standard formatting, not fight it.

    As you have found, some people find some aspects of the formatting that gofmt applies irritating to varying degrees. I am sure you will encounter more of these as you gain experience with GoLang. All I can say is that the irritation will fade.

    In teams, the value of the time, arguments and frustration saved by the (almost total) elimination of "personal style" that gofmt achieves is not to be underestimated. Neither is the extent to which it is a significant factor in making it easier to pick up GoLang code written by virtually anybody without having to first adjust to their individual style layered over the top of the language syntax.

    All is not (necessarily) lost

    In cases that you find particularly problematic, there is usually some degree of flexibility within the constraints of the standard formatting. For example, in the case of a switch/case, gofmt will preserve (at most) one line of whitespace separation between cases, so you could use:

    switch {
    case myString == "":
      fmt.Println("Empty string")
    
    case myString == "foo":
      doFoo()
    
    case myString == "bar":
      fmt.Println("We got bar now!")
    
    default:
      fmt.Println("Another default")
    }
    

    It’s up to you whether you find that to be an improvement or not. 🙂

    But it is an example of where gofmt allows some flexibility.

    This flexibility can be useful in other ways beyond individual preference and can become a "tool" in its own right. For example, within a single switch you could mix/match whitespace separation to "group" related cases if you find that useful in a specific instance, e.g.:

    switch {
    case myString == "foo":
      doFoo()
    case myString == "bar":
      fmt.Println("We got bar now!")
    
    case myString == "":
      fmt.Println("Empty string")
    default:
      fmt.Println("Another default")
    }
    

    Again, whether that is an "improvement" is largely subjective, but at least gofmt won’t get in your way on this one. 🙂

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search