{
	"Checks": {
		"QF1001": {
			"Title": "Apply De Morgan's law",
			"Text": "",
			"TitleMarkdown": "Apply De Morgan's law",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 5,
			"MergeIf": 0
		},
		"QF1002": {
			"Title": "Convert untagged switch to tagged switch",
			"Text": "An untagged switch that compares a single variable against a series of\nvalues can be replaced with a tagged switch.",
			"TitleMarkdown": "Convert untagged switch to tagged switch",
			"TextMarkdown": "An untagged switch that compares a single variable against a series of\nvalues can be replaced with a tagged switch.",
			"Before": "switch {\ncase x == 1 || x == 2, x == 3:\n    ...\ncase x == 4:\n    ...\ndefault:\n    ...\n}",
			"After": "switch x {\ncase 1, 2, 3:\n    ...\ncase 4:\n    ...\ndefault:\n    ...\n}",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 5,
			"MergeIf": 0
		},
		"QF1003": {
			"Title": "Convert if/else-if chain to tagged switch",
			"Text": "A series of if/else-if checks comparing the same variable against\nvalues can be replaced with a tagged switch.",
			"TitleMarkdown": "Convert if/else-if chain to tagged switch",
			"TextMarkdown": "A series of if/else-if checks comparing the same variable against\nvalues can be replaced with a tagged switch.",
			"Before": "if x == 1 || x == 2 {\n    ...\n} else if x == 3 {\n    ...\n} else {\n    ...\n}",
			"After": "switch x {\ncase 1, 2:\n    ...\ncase 3:\n    ...\ndefault:\n    ...\n}",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 4,
			"MergeIf": 0
		},
		"QF1004": {
			"Title": "Use strings.ReplaceAll instead of strings.Replace with n == -1",
			"Text": "",
			"TitleMarkdown": "Use `strings.ReplaceAll` instead of `strings.Replace` with `n == -1`",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 5,
			"MergeIf": 0
		},
		"QF1005": {
			"Title": "Expand call to math.Pow",
			"Text": "Some uses of math.Pow can be simplified to basic multiplication.",
			"TitleMarkdown": "Expand call to `math.Pow`",
			"TextMarkdown": "Some uses of `math.Pow` can be simplified to basic multiplication.",
			"Before": "math.Pow(x, 2)",
			"After": "x * x",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 5,
			"MergeIf": 0
		},
		"QF1006": {
			"Title": "Lift if+break into loop condition",
			"Text": "",
			"TitleMarkdown": "Lift `if`+`break` into loop condition",
			"TextMarkdown": "",
			"Before": "for {\n    if done {\n        break\n    }\n    ...\n}",
			"After": "for !done {\n    ...\n}",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 5,
			"MergeIf": 0
		},
		"QF1007": {
			"Title": "Merge conditional assignment into variable declaration",
			"Text": "",
			"TitleMarkdown": "Merge conditional assignment into variable declaration",
			"TextMarkdown": "",
			"Before": "x := false\nif someCondition {\n    x = true\n}",
			"After": "x := someCondition",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 5,
			"MergeIf": 0
		},
		"QF1008": {
			"Title": "Omit embedded fields from selector expression",
			"Text": "",
			"TitleMarkdown": "Omit embedded fields from selector expression",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 5,
			"MergeIf": 0
		},
		"QF1009": {
			"Title": "Use time.Time.Equal instead of == operator",
			"Text": "",
			"TitleMarkdown": "Use `time.Time.Equal` instead of `==` operator",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 4,
			"MergeIf": 0
		},
		"QF1010": {
			"Title": "Convert slice of bytes to string when printing it",
			"Text": "",
			"TitleMarkdown": "Convert slice of bytes to string when printing it",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 5,
			"MergeIf": 0
		},
		"QF1011": {
			"Title": "Omit redundant type from variable declaration",
			"Text": "",
			"TitleMarkdown": "Omit redundant type from variable declaration",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 5,
			"MergeIf": 0
		},
		"QF1012": {
			"Title": "Use fmt.Fprintf(x, ...) instead of x.Write(fmt.Sprintf(...))",
			"Text": "",
			"TitleMarkdown": "Use `fmt.Fprintf(x, ...)` instead of `x.Write(fmt.Sprintf(...))`",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2022.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 5,
			"MergeIf": 0
		},
		"S1000": {
			"Title": "Use plain channel send or receive instead of single-case select",
			"Text": "Select statements with a single case can be replaced with a simple\nsend or receive.",
			"TitleMarkdown": "Use plain channel send or receive instead of single-case select",
			"TextMarkdown": "Select statements with a single case can be replaced with a simple\nsend or receive.",
			"Before": "select {\ncase x := \u003c-ch:\n    fmt.Println(x)\n}",
			"After": "x := \u003c-ch\nfmt.Println(x)",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1001": {
			"Title": "Replace for loop with call to copy",
			"Text": "Use copy() for copying elements from one slice to another. For\narrays of identical size, you can use simple assignment.",
			"TitleMarkdown": "Replace for loop with call to copy",
			"TextMarkdown": "Use `copy()` for copying elements from one slice to another. For\narrays of identical size, you can use simple assignment.",
			"Before": "for i, x := range src {\n    dst[i] = x\n}",
			"After": "copy(dst, src)",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 1
		},
		"S1002": {
			"Title": "Omit comparison with boolean constant",
			"Text": "",
			"TitleMarkdown": "Omit comparison with boolean constant",
			"TextMarkdown": "",
			"Before": "if x == true {}",
			"After": "if x {}",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 1
		},
		"S1003": {
			"Title": "Replace call to strings.Index with strings.Contains",
			"Text": "",
			"TitleMarkdown": "Replace call to `strings.Index` with `strings.Contains`",
			"TextMarkdown": "",
			"Before": "if strings.Index(x, y) != -1 {}",
			"After": "if strings.Contains(x, y) {}",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1004": {
			"Title": "Replace call to bytes.Compare with bytes.Equal",
			"Text": "",
			"TitleMarkdown": "Replace call to `bytes.Compare` with `bytes.Equal`",
			"TextMarkdown": "",
			"Before": "if bytes.Compare(x, y) == 0 {}",
			"After": "if bytes.Equal(x, y) {}",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1005": {
			"Title": "Drop unnecessary use of the blank identifier",
			"Text": "In many cases, assigning to the blank identifier is unnecessary.",
			"TitleMarkdown": "Drop unnecessary use of the blank identifier",
			"TextMarkdown": "In many cases, assigning to the blank identifier is unnecessary.",
			"Before": "for _ = range s {}\nx, _ = someMap[key]\n_ = \u003c-ch",
			"After": "for range s{}\nx = someMap[key]\n\u003c-ch",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1006": {
			"Title": "Use 'for { ... }' for infinite loops",
			"Text": "For infinite loops, using for { ... } is the most idiomatic choice.",
			"TitleMarkdown": "Use `for { ... }` for infinite loops",
			"TextMarkdown": "For infinite loops, using `for { ... }` is the most idiomatic choice.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1007": {
			"Title": "Simplify regular expression by using raw string literal",
			"Text": "Raw string literals use backticks instead of quotation marks and do not support\nany escape sequences. This means that the backslash can be used\nfreely, without the need of escaping.\n\nSince regular expressions have their own escape sequences, raw strings\ncan improve their readability.",
			"TitleMarkdown": "Simplify regular expression by using raw string literal",
			"TextMarkdown": "Raw string literals use backticks instead of quotation marks and do not support\nany escape sequences. This means that the backslash can be used\nfreely, without the need of escaping.\n\nSince regular expressions have their own escape sequences, raw strings\ncan improve their readability.",
			"Before": "regexp.Compile(\"\\\\A(\\\\w+) profile: total \\\\d+\\\\n\\\\z\")",
			"After": "regexp.Compile(`\\A(\\w+) profile: total \\d+\\n\\z`)",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1008": {
			"Title": "Simplify returning boolean expression",
			"Text": "",
			"TitleMarkdown": "Simplify returning boolean expression",
			"TextMarkdown": "",
			"Before": "if \u003cexpr\u003e {\n    return true\n}\nreturn false",
			"After": "return \u003cexpr\u003e",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1009": {
			"Title": "Omit redundant nil check on slices",
			"Text": "The len function is defined for all slices, even nil ones, which have\na length of zero. It is not necessary to check if a slice is not nil\nbefore checking that its length is not zero.",
			"TitleMarkdown": "Omit redundant nil check on slices",
			"TextMarkdown": "The `len` function is defined for all slices, even nil ones, which have\na length of zero. It is not necessary to check if a slice is not nil\nbefore checking that its length is not zero.",
			"Before": "if x != nil \u0026\u0026 len(x) != 0 {}",
			"After": "if len(x) != 0 {}",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1010": {
			"Title": "Omit default slice index",
			"Text": "When slicing, the second index defaults to the length of the value,\nmaking s[n:len(s)] and s[n:] equivalent.",
			"TitleMarkdown": "Omit default slice index",
			"TextMarkdown": "When slicing, the second index defaults to the length of the value,\nmaking `s[n:len(s)]` and `s[n:]` equivalent.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1011": {
			"Title": "Use a single append to concatenate two slices",
			"Text": "",
			"TitleMarkdown": "Use a single `append` to concatenate two slices",
			"TextMarkdown": "",
			"Before": "for _, e := range y {\n    x = append(x, e)\n}\n\nfor i := range y {\n    x = append(x, y[i])\n}\n\nfor i := range y {\n    v := y[i]\n    x = append(x, v)\n}",
			"After": "x = append(x, y...)\nx = append(x, y...)\nx = append(x, y...)",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 1
		},
		"S1012": {
			"Title": "Replace time.Now().Sub(x) with time.Since(x)",
			"Text": "The time.Since helper has the same effect as using time.Now().Sub(x)\nbut is easier to read.",
			"TitleMarkdown": "Replace `time.Now().Sub(x)` with `time.Since(x)`",
			"TextMarkdown": "The `time.Since` helper has the same effect as using `time.Now().Sub(x)`\nbut is easier to read.",
			"Before": "time.Now().Sub(x)",
			"After": "time.Since(x)",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1016": {
			"Title": "Use a type conversion instead of manually copying struct fields",
			"Text": "Two struct types with identical fields can be converted between each\nother. In older versions of Go, the fields had to have identical\nstruct tags. Since Go 1.8, however, struct tags are ignored during\nconversions. It is thus not necessary to manually copy every field\nindividually.",
			"TitleMarkdown": "Use a type conversion instead of manually copying struct fields",
			"TextMarkdown": "Two struct types with identical fields can be converted between each\nother. In older versions of Go, the fields had to have identical\nstruct tags. Since Go 1.8, however, struct tags are ignored during\nconversions. It is thus not necessary to manually copy every field\nindividually.",
			"Before": "var x T1\ny := T2{\n    Field1: x.Field1,\n    Field2: x.Field2,\n}",
			"After": "var x T1\ny := T2(x)",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 1
		},
		"S1017": {
			"Title": "Replace manual trimming with strings.TrimPrefix",
			"Text": "Instead of using strings.HasPrefix and manual slicing, use the\nstrings.TrimPrefix function. If the string doesn't start with the\nprefix, the original string will be returned. Using strings.TrimPrefix\nreduces complexity, and avoids common bugs, such as off-by-one\nmistakes.",
			"TitleMarkdown": "Replace manual trimming with `strings.TrimPrefix`",
			"TextMarkdown": "Instead of using `strings.HasPrefix` and manual slicing, use the\n`strings.TrimPrefix` function. If the string doesn't start with the\nprefix, the original string will be returned. Using `strings.TrimPrefix`\nreduces complexity, and avoids common bugs, such as off-by-one\nmistakes.",
			"Before": "if strings.HasPrefix(str, prefix) {\n    str = str[len(prefix):]\n}",
			"After": "str = strings.TrimPrefix(str, prefix)",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1018": {
			"Title": "Use 'copy' for sliding elements",
			"Text": "copy() permits using the same source and destination slice, even with\noverlapping ranges. This makes it ideal for sliding elements in a\nslice.",
			"TitleMarkdown": "Use `copy` for sliding elements",
			"TextMarkdown": "`copy()` permits using the same source and destination slice, even with\noverlapping ranges. This makes it ideal for sliding elements in a\nslice.",
			"Before": "for i := 0; i \u003c n; i++ {\n    bs[i] = bs[offset+i]\n}",
			"After": "copy(bs[:n], bs[offset:])",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1019": {
			"Title": "Simplify 'make' call by omitting redundant arguments",
			"Text": "The 'make' function has default values for the length and capacity\narguments. For channels, the length defaults to zero, and for slices,\nthe capacity defaults to the length.",
			"TitleMarkdown": "Simplify `make` call by omitting redundant arguments",
			"TextMarkdown": "The `make` function has default values for the length and capacity\narguments. For channels, the length defaults to zero, and for slices,\nthe capacity defaults to the length.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 1
		},
		"S1020": {
			"Title": "Omit redundant nil check in type assertion",
			"Text": "",
			"TitleMarkdown": "Omit redundant nil check in type assertion",
			"TextMarkdown": "",
			"Before": "if _, ok := i.(T); ok \u0026\u0026 i != nil {}",
			"After": "if _, ok := i.(T); ok {}",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1021": {
			"Title": "Merge variable declaration and assignment",
			"Text": "",
			"TitleMarkdown": "Merge variable declaration and assignment",
			"TextMarkdown": "",
			"Before": "var x uint\nx = 1",
			"After": "var x uint = 1",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1023": {
			"Title": "Omit redundant control flow",
			"Text": "Functions that have no return value do not need a return statement as\nthe final statement of the function.\n\nSwitches in Go do not have automatic fallthrough, unlike languages\nlike C. It is not necessary to have a break statement as the final\nstatement in a case block.",
			"TitleMarkdown": "Omit redundant control flow",
			"TextMarkdown": "Functions that have no return value do not need a return statement as\nthe final statement of the function.\n\nSwitches in Go do not have automatic fallthrough, unlike languages\nlike C. It is not necessary to have a break statement as the final\nstatement in a case block.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1024": {
			"Title": "Replace x.Sub(time.Now()) with time.Until(x)",
			"Text": "The time.Until helper has the same effect as using x.Sub(time.Now())\nbut is easier to read.",
			"TitleMarkdown": "Replace `x.Sub(time.Now())` with `time.Until(x)`",
			"TextMarkdown": "The `time.Until` helper has the same effect as using `x.Sub(time.Now())`\nbut is easier to read.",
			"Before": "x.Sub(time.Now())",
			"After": "time.Until(x)",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1025": {
			"Title": "Don't use fmt.Sprintf(\"%s\", x) unnecessarily",
			"Text": "In many instances, there are easier and more efficient ways of getting\na value's string representation. Whenever a value's underlying type is\na string already, or the type has a String method, they should be used\ndirectly.\n\nGiven the following shared definitions\n\n```go\ntype T1 string\ntype T2 int\n\nfunc (T2) String() string { return \"Hello, world\" }\n\nvar x string\nvar y T1\nvar z T2\n```\n\nwe can simplify\n\n```go\nfmt.Sprintf(\"%s\", x)\nfmt.Sprintf(\"%s\", y)\nfmt.Sprintf(\"%s\", z)\n```\n\nto\n\n```go\nx\nstring(y)\nz.String()\n```",
			"TitleMarkdown": "Don't use `fmt.Sprintf(\"%s\", x)` unnecessarily",
			"TextMarkdown": "In many instances, there are easier and more efficient ways of getting\na value's string representation. Whenever a value's underlying type is\na string already, or the type has a String method, they should be used\ndirectly.\n\nGiven the following shared definitions\n\n```go\ntype T1 string\ntype T2 int\n\nfunc (T2) String() string { return \"Hello, world\" }\n\nvar x string\nvar y T1\nvar z T2\n```\n\nwe can simplify\n\n```go\nfmt.Sprintf(\"%s\", x)\nfmt.Sprintf(\"%s\", y)\nfmt.Sprintf(\"%s\", z)\n```\n\nto\n\n```go\nx\nstring(y)\nz.String()\n```",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 1
		},
		"S1028": {
			"Title": "Simplify error construction with fmt.Errorf",
			"Text": "",
			"TitleMarkdown": "Simplify error construction with `fmt.Errorf`",
			"TextMarkdown": "",
			"Before": "errors.New(fmt.Sprintf(...))",
			"After": "fmt.Errorf(...)",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1029": {
			"Title": "Range over the string directly",
			"Text": "Ranging over a string will yield byte offsets and runes. If the offset\nisn't used, this is functionally equivalent to converting the string\nto a slice of runes and ranging over that. Ranging directly over the\nstring will be more performant, however, as it avoids allocating a new\nslice, the size of which depends on the length of the string.",
			"TitleMarkdown": "Range over the string directly",
			"TextMarkdown": "Ranging over a string will yield byte offsets and runes. If the offset\nisn't used, this is functionally equivalent to converting the string\nto a slice of runes and ranging over that. Ranging directly over the\nstring will be more performant, however, as it avoids allocating a new\nslice, the size of which depends on the length of the string.",
			"Before": "for _, r := range []rune(s) {}",
			"After": "for _, r := range s {}",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1030": {
			"Title": "Use bytes.Buffer.String or bytes.Buffer.Bytes",
			"Text": "bytes.Buffer has both a String and a Bytes method. It is almost never\nnecessary to use string(buf.Bytes()) or []byte(buf.String()) – simply\nuse the other method.\n\nThe only exception to this are map lookups. Due to a compiler optimization,\nm[string(buf.Bytes())] is more efficient than m[buf.String()].",
			"TitleMarkdown": "Use `bytes.Buffer.String` or `bytes.Buffer.Bytes`",
			"TextMarkdown": "`bytes.Buffer` has both a `String` and a `Bytes` method. It is almost never\nnecessary to use `string(buf.Bytes())` or `[]byte(buf.String())` – simply\nuse the other method.\n\nThe only exception to this are map lookups. Due to a compiler optimization,\n`m[string(buf.Bytes())]` is more efficient than `m[buf.String()]`.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1031": {
			"Title": "Omit redundant nil check around loop",
			"Text": "You can use range on nil slices and maps, the loop will simply never\nexecute. This makes an additional nil check around the loop\nunnecessary.",
			"TitleMarkdown": "Omit redundant nil check around loop",
			"TextMarkdown": "You can use range on nil slices and maps, the loop will simply never\nexecute. This makes an additional nil check around the loop\nunnecessary.",
			"Before": "if s != nil {\n    for _, x := range s {\n        ...\n    }\n}",
			"After": "for _, x := range s {\n    ...\n}",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 1
		},
		"S1032": {
			"Title": "Use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)",
			"Text": "The sort.Ints, sort.Float64s and sort.Strings functions are easier to\nread than sort.Sort(sort.IntSlice(x)), sort.Sort(sort.Float64Slice(x))\nand sort.Sort(sort.StringSlice(x)).",
			"TitleMarkdown": "Use `sort.Ints(x)`, `sort.Float64s(x)`, and `sort.Strings(x)`",
			"TextMarkdown": "The `sort.Ints`, `sort.Float64s` and `sort.Strings` functions are easier to\nread than `sort.Sort(sort.IntSlice(x))`, `sort.Sort(sort.Float64Slice(x))`\nand `sort.Sort(sort.StringSlice(x))`.",
			"Before": "sort.Sort(sort.StringSlice(x))",
			"After": "sort.Strings(x)",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1033": {
			"Title": "Unnecessary guard around call to 'delete'",
			"Text": "Calling delete on a nil map is a no-op.",
			"TitleMarkdown": "Unnecessary guard around call to `delete`",
			"TextMarkdown": "Calling `delete` on a nil map is a no-op.",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1034": {
			"Title": "Use result of type assertion to simplify cases",
			"Text": "",
			"TitleMarkdown": "Use result of type assertion to simplify cases",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1035": {
			"Title": "Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header",
			"Text": "The methods on net/http.Header, namely Add, Del, Get\nand Set, already canonicalize the given header name.",
			"TitleMarkdown": "Redundant call to `net/http.CanonicalHeaderKey` in method call on `net/http.Header`",
			"TextMarkdown": "The methods on `net/http.Header`, namely `Add`, `Del`, `Get`\nand `Set`, already canonicalize the given header name.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1036": {
			"Title": "Unnecessary guard around map access",
			"Text": "When accessing a map key that doesn't exist yet, one receives a zero\nvalue. Often, the zero value is a suitable value, for example when\nusing append or doing integer math.\n\nThe following\n\n```go\nif _, ok := m[\"foo\"]; ok {\n    m[\"foo\"] = append(m[\"foo\"], \"bar\")\n} else {\n    m[\"foo\"] = []string{\"bar\"}\n}\n```\n\ncan be simplified to\n\n```go\nm[\"foo\"] = append(m[\"foo\"], \"bar\")\n```\n\nand\n\n```go\nif _, ok := m2[\"k\"]; ok {\n    m2[\"k\"] += 4\n} else {\n    m2[\"k\"] = 4\n}\n```\n\ncan be simplified to\n\n```go\nm[\"k\"] += 4\n```",
			"TitleMarkdown": "Unnecessary guard around map access",
			"TextMarkdown": "When accessing a map key that doesn't exist yet, one receives a zero\nvalue. Often, the zero value is a suitable value, for example when\nusing append or doing integer math.\n\nThe following\n\n```go\nif _, ok := m[\"foo\"]; ok {\n    m[\"foo\"] = append(m[\"foo\"], \"bar\")\n} else {\n    m[\"foo\"] = []string{\"bar\"}\n}\n```\n\ncan be simplified to\n\n```go\nm[\"foo\"] = append(m[\"foo\"], \"bar\")\n```\n\nand\n\n```go\nif _, ok := m2[\"k\"]; ok {\n    m2[\"k\"] += 4\n} else {\n    m2[\"k\"] = 4\n}\n```\n\ncan be simplified to\n\n```go\nm[\"k\"] += 4\n```",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1037": {
			"Title": "Elaborate way of sleeping",
			"Text": "Using a select statement with a single case receiving\nfrom the result of time.After is a very elaborate way of sleeping that\ncan much simpler be expressed with a simple call to time.Sleep.",
			"TitleMarkdown": "Elaborate way of sleeping",
			"TextMarkdown": "Using a select statement with a single case receiving\nfrom the result of `time.After` is a very elaborate way of sleeping that\ncan much simpler be expressed with a simple call to time.Sleep.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1038": {
			"Title": "Unnecessarily complex way of printing formatted string",
			"Text": "Instead of using fmt.Print(fmt.Sprintf(...)), one can use fmt.Printf(...).",
			"TitleMarkdown": "Unnecessarily complex way of printing formatted string",
			"TextMarkdown": "Instead of using `fmt.Print(fmt.Sprintf(...))`, one can use `fmt.Printf(...)`.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"S1039": {
			"Title": "Unnecessary use of fmt.Sprint",
			"Text": "Calling fmt.Sprint with a single string argument is unnecessary\nand identical to using the string directly.",
			"TitleMarkdown": "Unnecessary use of `fmt.Sprint`",
			"TextMarkdown": "Calling `fmt.Sprint` with a single string argument is unnecessary\nand identical to using the string directly.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 1
		},
		"S1040": {
			"Title": "Type assertion to current type",
			"Text": "The type assertion x.(SomeInterface), when x already has type\nSomeInterface, can only fail if x is nil. Usually, this is\nleft-over code from when x had a different type and you can safely\ndelete the type assertion. If you want to check that x is not nil,\nconsider being explicit and using an actual if x == nil comparison\ninstead of relying on the type assertion panicking.",
			"TitleMarkdown": "Type assertion to current type",
			"TextMarkdown": "The type assertion `x.(SomeInterface)`, when `x` already has type\n`SomeInterface`, can only fail if `x` is nil. Usually, this is\nleft-over code from when `x` had a different type and you can safely\ndelete the type assertion. If you want to check that `x` is not nil,\nconsider being explicit and using an actual `if x == nil` comparison\ninstead of relying on the type assertion panicking.",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 1
		},
		"SA1000": {
			"Title": "Invalid regular expression",
			"Text": "",
			"TitleMarkdown": "Invalid regular expression",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1001": {
			"Title": "Invalid template",
			"Text": "",
			"TitleMarkdown": "Invalid template",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1002": {
			"Title": "Invalid format in time.Parse",
			"Text": "",
			"TitleMarkdown": "Invalid format in `time.Parse`",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1003": {
			"Title": "Unsupported argument to functions in encoding/binary",
			"Text": "The encoding/binary package can only serialize types with known sizes.\nThis precludes the use of the int and uint types, as their sizes\ndiffer on different architectures. Furthermore, it doesn't support\nserializing maps, channels, strings, or functions.\n\nBefore Go 1.8, bool wasn't supported, either.",
			"TitleMarkdown": "Unsupported argument to functions in `encoding/binary`",
			"TextMarkdown": "The `encoding/binary` package can only serialize types with known sizes.\nThis precludes the use of the `int` and `uint` types, as their sizes\ndiffer on different architectures. Furthermore, it doesn't support\nserializing maps, channels, strings, or functions.\n\nBefore Go 1.8, `bool` wasn't supported, either.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1004": {
			"Title": "Suspiciously small untyped constant in time.Sleep",
			"Text": "The time.Sleep function takes a time.Duration as its only argument.\nDurations are expressed in nanoseconds. Thus, calling time.Sleep(1)\nwill sleep for 1 nanosecond. This is a common source of bugs, as sleep\nfunctions in other languages often accept seconds or milliseconds.\n\nThe time package provides constants such as time.Second to express\nlarge durations. These can be combined with arithmetic to express\narbitrary durations, for example 5 * time.Second for 5 seconds.\n\nIf you truly meant to sleep for a tiny amount of time, use\nn * time.Nanosecond to signal to Staticcheck that you did mean to sleep\nfor some amount of nanoseconds.",
			"TitleMarkdown": "Suspiciously small untyped constant in `time.Sleep`",
			"TextMarkdown": "The `time`.Sleep function takes a `time.Duration` as its only argument.\nDurations are expressed in nanoseconds. Thus, calling `time.Sleep(1)`\nwill sleep for 1 nanosecond. This is a common source of bugs, as sleep\nfunctions in other languages often accept seconds or milliseconds.\n\nThe `time` package provides constants such as `time.Second` to express\nlarge durations. These can be combined with arithmetic to express\narbitrary durations, for example `5 * time.Second` for 5 seconds.\n\nIf you truly meant to sleep for a tiny amount of time, use\n`n * time.Nanosecond` to signal to Staticcheck that you did mean to sleep\nfor some amount of nanoseconds.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1005": {
			"Title": "Invalid first argument to exec.Command",
			"Text": "os/exec runs programs directly (using variants of the fork and exec\nsystem calls on Unix systems). This shouldn't be confused with running\na command in a shell. The shell will allow for features such as input\nredirection, pipes, and general scripting. The shell is also\nresponsible for splitting the user's input into a program name and its\narguments. For example, the equivalent to\n\n```go\nls / /tmp\n```\n\nwould be\n\n```go\nexec.Command(\"ls\", \"/\", \"/tmp\")\n```\n\nIf you want to run a command in a shell, consider using something like\nthe following – but be aware that not all systems, particularly\nWindows, will have a /bin/sh program:\n\n```go\nexec.Command(\"/bin/sh\", \"-c\", \"ls | grep Awesome\")\n```",
			"TitleMarkdown": "Invalid first argument to `exec.Command`",
			"TextMarkdown": "`os/exec` runs programs directly (using variants of the fork and exec\nsystem calls on Unix systems). This shouldn't be confused with running\na command in a shell. The shell will allow for features such as input\nredirection, pipes, and general scripting. The shell is also\nresponsible for splitting the user's input into a program name and its\narguments. For example, the equivalent to\n\n```go\nls / /tmp\n```\n\nwould be\n\n```go\nexec.Command(\"ls\", \"/\", \"/tmp\")\n```\n\nIf you want to run a command in a shell, consider using something like\nthe following – but be aware that not all systems, particularly\nWindows, will have a `/bin/sh` program:\n\n```go\nexec.Command(\"/bin/sh\", \"-c\", \"ls | grep Awesome\")\n```",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1006": {
			"Title": "Printf with dynamic first argument and no further arguments",
			"Text": "Using fmt.Printf with a dynamic first argument can lead to unexpected\noutput. The first argument is a format string, where certain character\ncombinations have special meaning. If, for example, a user were to\nenter a string such as\n\n```go\nInterest rate: 5%\n```\n\nand you printed it with\n\n```go\nfmt.Printf(s)\n```\n\nit would lead to the following output:\n\n```go\nInterest rate: 5%!(NOVERB).\n```\n\nSimilarly, forming the first parameter via string concatenation with\nuser input should be avoided for the same reason. When printing user\ninput, either use a variant of fmt.Print, or use the %s Printf verb\nand pass the string as an argument.",
			"TitleMarkdown": "`Printf` with dynamic first argument and no further arguments",
			"TextMarkdown": "Using `fmt.Printf` with a dynamic first argument can lead to unexpected\noutput. The first argument is a format string, where certain character\ncombinations have special meaning. If, for example, a user were to\nenter a string such as\n\n```go\nInterest rate: 5%\n```\n\nand you printed it with\n\n```go\nfmt.Printf(s)\n```\n\nit would lead to the following output:\n\n```go\nInterest rate: 5%!(NOVERB).\n```\n\nSimilarly, forming the first parameter via string concatenation with\nuser input should be avoided for the same reason. When printing user\ninput, either use a variant of `fmt.Print`, or use the `%s` Printf verb\nand pass the string as an argument.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1007": {
			"Title": "Invalid URL in net/url.Parse",
			"Text": "",
			"TitleMarkdown": "Invalid URL in `net/url.Parse`",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1008": {
			"Title": "Non-canonical key in http.Header map",
			"Text": "Keys in http.Header maps are canonical, meaning they follow a specific\ncombination of uppercase and lowercase letters. Methods such as\nhttp.Header.Add and http.Header.Del convert inputs into this canonical\nform before manipulating the map.\n\nWhen manipulating http.Header maps directly, as opposed to using the\nprovided methods, care should be taken to stick to canonical form in\norder to avoid inconsistencies. The following piece of code\ndemonstrates one such inconsistency:\n\n```go\nh := http.Header{}\nh[\"etag\"] = []string{\"1234\"}\nh.Add(\"etag\", \"5678\")\nfmt.Println(h)\n\n// Output:\n// map[Etag:[5678] etag:[1234]]\n```\n\nThe easiest way of obtaining the canonical form of a key is to use\nhttp.CanonicalHeaderKey.",
			"TitleMarkdown": "Non-canonical key in `http.Header` map",
			"TextMarkdown": "Keys in `http.Header` maps are canonical, meaning they follow a specific\ncombination of uppercase and lowercase letters. Methods such as\n`http.Header.Add` and `http.Header.Del` convert inputs into this canonical\nform before manipulating the map.\n\nWhen manipulating `http.Header` maps directly, as opposed to using the\nprovided methods, care should be taken to stick to canonical form in\norder to avoid inconsistencies. The following piece of code\ndemonstrates one such inconsistency:\n\n```go\nh := http.Header{}\nh[\"etag\"] = []string{\"1234\"}\nh.Add(\"etag\", \"5678\")\nfmt.Println(h)\n\n// Output:\n// map[Etag:[5678] etag:[1234]]\n```\n\nThe easiest way of obtaining the canonical form of a key is to use\n`http.CanonicalHeaderKey`.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1010": {
			"Title": "(*regexp.Regexp).FindAll called with n == 0, which will always return zero results",
			"Text": "If n \u003e= 0, the function returns at most n matches/submatches. To\nreturn all results, specify a negative number.",
			"TitleMarkdown": "`(*regexp.Regexp).FindAll` called with `n == 0`, which will always return zero results",
			"TextMarkdown": "If `n \u003e= 0`, the function returns at most `n` matches/submatches. To\nreturn all results, specify a negative number.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1011": {
			"Title": "Various methods in the 'strings' package expect valid UTF-8, but invalid input is provided",
			"Text": "",
			"TitleMarkdown": "Various methods in the `strings` package expect valid UTF-8, but invalid input is provided",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1012": {
			"Title": "A nil context.Context is being passed to a function, consider using context.TODO instead",
			"Text": "",
			"TitleMarkdown": "A nil `context.Context` is being passed to a function, consider using `context.TODO` instead",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1013": {
			"Title": "io.Seeker.Seek is being called with the whence constant as the first argument, but it should be the second",
			"Text": "",
			"TitleMarkdown": "`io.Seeker.Seek` is being called with the whence constant as the first argument, but it should be the second",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1014": {
			"Title": "Non-pointer value passed to Unmarshal or Decode",
			"Text": "",
			"TitleMarkdown": "Non-pointer value passed to `Unmarshal` or `Decode`",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1015": {
			"Title": "Using time.Tick in a way that will leak. Consider using time.NewTicker, and only use time.Tick in tests, commands and endless functions",
			"Text": "",
			"TitleMarkdown": "Using `time.Tick` in a way that will leak. Consider using `time.NewTicker`, and only use `time.Tick` in tests, commands and endless functions",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1016": {
			"Title": "Trapping a signal that cannot be trapped",
			"Text": "Not all signals can be intercepted by a process. Specifically, on\nUNIX-like systems, the syscall.SIGKILL and syscall.SIGSTOP signals are\nnever passed to the process, but instead handled directly by the\nkernel. It is therefore pointless to try and handle these signals.",
			"TitleMarkdown": "Trapping a signal that cannot be trapped",
			"TextMarkdown": "Not all signals can be intercepted by a process. Specifically, on\nUNIX-like systems, the `syscall.SIGKILL` and `syscall.SIGSTOP` signals are\nnever passed to the process, but instead handled directly by the\nkernel. It is therefore pointless to try and handle these signals.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1017": {
			"Title": "Channels used with os/signal.Notify should be buffered",
			"Text": "The os/signal package uses non-blocking channel sends when delivering\nsignals. If the receiving end of the channel isn't ready and the\nchannel is either unbuffered or full, the signal will be dropped. To\navoid missing signals, the channel should be buffered and of the\nappropriate size. For a channel used for notification of just one\nsignal value, a buffer of size 1 is sufficient.",
			"TitleMarkdown": "Channels used with `os/signal.Notify` should be buffered",
			"TextMarkdown": "The `os/signal` package uses non-blocking channel sends when delivering\nsignals. If the receiving end of the channel isn't ready and the\nchannel is either unbuffered or full, the signal will be dropped. To\navoid missing signals, the channel should be buffered and of the\nappropriate size. For a channel used for notification of just one\nsignal value, a buffer of size 1 is sufficient.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1018": {
			"Title": "strings.Replace called with n == 0, which does nothing",
			"Text": "With n == 0, zero instances will be replaced. To replace all\ninstances, use a negative number, or use strings.ReplaceAll.",
			"TitleMarkdown": "`strings.Replace` called with `n == 0`, which does nothing",
			"TextMarkdown": "With `n == 0`, zero instances will be replaced. To replace all\ninstances, use a negative number, or use `strings.ReplaceAll`.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1019": {
			"Title": "Using a deprecated function, variable, constant or field",
			"Text": "",
			"TitleMarkdown": "Using a deprecated function, variable, constant or field",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 2,
			"MergeIf": 0
		},
		"SA1020": {
			"Title": "Using an invalid host:port pair with a net.Listen-related function",
			"Text": "",
			"TitleMarkdown": "Using an invalid host:port pair with a `net.Listen`-related function",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1021": {
			"Title": "Using bytes.Equal to compare two net.IP",
			"Text": "A net.IP stores an IPv4 or IPv6 address as a slice of bytes. The\nlength of the slice for an IPv4 address, however, can be either 4 or\n16 bytes long, using different ways of representing IPv4 addresses. In\norder to correctly compare two net.IPs, the net.IP.Equal method should\nbe used, as it takes both representations into account.",
			"TitleMarkdown": "Using `bytes.Equal` to compare two `net.IP`",
			"TextMarkdown": "A `net.IP` stores an IPv4 or IPv6 address as a slice of bytes. The\nlength of the slice for an IPv4 address, however, can be either 4 or\n16 bytes long, using different ways of representing IPv4 addresses. In\norder to correctly compare two `net.IP`s, the `net.IP.Equal` method should\nbe used, as it takes both representations into account.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1023": {
			"Title": "Modifying the buffer in an io.Writer implementation",
			"Text": "Write must not modify the slice data, even temporarily.",
			"TitleMarkdown": "Modifying the buffer in an `io.Writer` implementation",
			"TextMarkdown": "`Write` must not modify the slice data, even temporarily.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1024": {
			"Title": "A string cutset contains duplicate characters",
			"Text": "The strings.TrimLeft and strings.TrimRight functions take cutsets, not\nprefixes. A cutset is treated as a set of characters to remove from a\nstring. For example,\n\n```go\nstrings.TrimLeft(\"42133word\", \"1234\")\n```\n\nwill result in the string \"word\" – any characters that are 1, 2, 3 or\n4 are cut from the left of the string.\n\nIn order to remove one string from another, use strings.TrimPrefix instead.",
			"TitleMarkdown": "A string cutset contains duplicate characters",
			"TextMarkdown": "The `strings.TrimLeft` and `strings.TrimRight` functions take cutsets, not\nprefixes. A cutset is treated as a set of characters to remove from a\nstring. For example,\n\n```go\nstrings.TrimLeft(\"42133word\", \"1234\")\n```\n\nwill result in the string `\"word\"` – any characters that are 1, 2, 3 or\n4 are cut from the left of the string.\n\nIn order to remove one string from another, use `strings.TrimPrefix` instead.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1025": {
			"Title": "It is not possible to use (*time.Timer).Reset's return value correctly",
			"Text": "",
			"TitleMarkdown": "It is not possible to use `(*time.Timer).Reset`'s return value correctly",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1026": {
			"Title": "Cannot marshal channels or functions",
			"Text": "",
			"TitleMarkdown": "Cannot marshal channels or functions",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1027": {
			"Title": "Atomic access to 64-bit variable must be 64-bit aligned",
			"Text": "On ARM, x86-32, and 32-bit MIPS, it is the caller's responsibility to\narrange for 64-bit alignment of 64-bit words accessed atomically. The\nfirst word in a variable or in an allocated struct, array, or slice\ncan be relied upon to be 64-bit aligned.\n\nYou can use the structlayout tool to inspect the alignment of fields\nin a struct.",
			"TitleMarkdown": "Atomic access to 64-bit variable must be 64-bit aligned",
			"TextMarkdown": "On ARM, x86-32, and 32-bit MIPS, it is the caller's responsibility to\narrange for 64-bit alignment of 64-bit words accessed atomically. The\nfirst word in a variable or in an allocated struct, array, or slice\ncan be relied upon to be 64-bit aligned.\n\nYou can use the structlayout tool to inspect the alignment of fields\nin a struct.",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1028": {
			"Title": "sort.Slice can only be used on slices",
			"Text": "The first argument of sort.Slice must be a slice.",
			"TitleMarkdown": "`sort.Slice` can only be used on slices",
			"TextMarkdown": "The first argument of `sort.Slice` must be a slice.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA1029": {
			"Title": "Inappropriate key in call to context.WithValue",
			"Text": "The provided key must be comparable and should not be\nof type string or any other built-in type to avoid collisions between\npackages using context. Users of WithValue should define their own\ntypes for keys.\n\nTo avoid allocating when assigning to an interface{},\ncontext keys often have concrete type struct{}. Alternatively,\nexported context key variables' static type should be a pointer or\ninterface.",
			"TitleMarkdown": "Inappropriate key in call to `context.WithValue`",
			"TextMarkdown": "The provided key must be comparable and should not be\nof type `string` or any other built-in type to avoid collisions between\npackages using context. Users of `WithValue` should define their own\ntypes for keys.\n\nTo avoid allocating when assigning to an `interface{}`,\ncontext keys often have concrete type `struct{}`. Alternatively,\nexported context key variables' static type should be a pointer or\ninterface.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA1030": {
			"Title": "Invalid argument in call to a strconv function",
			"Text": "This check validates the format, number base and bit size arguments of\nthe various parsing and formatting functions in strconv.",
			"TitleMarkdown": "Invalid argument in call to a `strconv` function",
			"TextMarkdown": "This check validates the format, number base and bit size arguments of\nthe various parsing and formatting functions in `strconv`.",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA2000": {
			"Title": "sync.WaitGroup.Add called inside the goroutine, leading to a race condition",
			"Text": "",
			"TitleMarkdown": "`sync.WaitGroup.Add` called inside the goroutine, leading to a race condition",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA2001": {
			"Title": "Empty critical section, did you mean to defer the unlock?",
			"Text": "Empty critical sections of the kind\n\n```go\nmu.Lock()\nmu.Unlock()\n```\n\nare very often a typo, and the following was intended instead:\n\n```go\nmu.Lock()\ndefer mu.Unlock()\n```\n\nDo note that sometimes empty critical sections can be useful, as a\nform of signaling to wait on another goroutine. Many times, there are\nsimpler ways of achieving the same effect. When that isn't the case,\nthe code should be amply commented to avoid confusion. Combining such\ncomments with a //lint:ignore directive can be used to suppress this\nrare false positive.",
			"TitleMarkdown": "Empty critical section, did you mean to defer the unlock?",
			"TextMarkdown": "Empty critical sections of the kind\n\n```go\nmu.Lock()\nmu.Unlock()\n```\n\nare very often a typo, and the following was intended instead:\n\n```go\nmu.Lock()\ndefer mu.Unlock()\n```\n\nDo note that sometimes empty critical sections can be useful, as a\nform of signaling to wait on another goroutine. Many times, there are\nsimpler ways of achieving the same effect. When that isn't the case,\nthe code should be amply commented to avoid confusion. Combining such\ncomments with a `//lint:ignore` directive can be used to suppress this\nrare false positive.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA2002": {
			"Title": "Called testing.T.FailNow or SkipNow in a goroutine, which isn't allowed",
			"Text": "",
			"TitleMarkdown": "Called `testing.T.FailNow` or `SkipNow` in a goroutine, which isn't allowed",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA2003": {
			"Title": "Deferred Lock right after locking, likely meant to defer Unlock instead",
			"Text": "",
			"TitleMarkdown": "Deferred `Lock` right after locking, likely meant to defer `Unlock` instead",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA3000": {
			"Title": "TestMain doesn't call os.Exit, hiding test failures",
			"Text": "Test executables (and in turn 'go test') exit with a non-zero status\ncode if any tests failed. When specifying your own TestMain function,\nit is your responsibility to arrange for this, by calling os.Exit with\nthe correct code. The correct code is returned by (*testing.M).Run, so\nthe usual way of implementing TestMain is to end it with\nos.Exit(m.Run()).",
			"TitleMarkdown": "`TestMain` doesn't call `os.Exit`, hiding test failures",
			"TextMarkdown": "Test executables (and in turn `go test`) exit with a non-zero status\ncode if any tests failed. When specifying your own `TestMain` function,\nit is your responsibility to arrange for this, by calling `os.Exit` with\nthe correct code. The correct code is returned by `(*testing.M).Run`, so\nthe usual way of implementing `TestMain` is to end it with\n`os.Exit(m.Run())`.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA3001": {
			"Title": "Assigning to b.N in benchmarks distorts the results",
			"Text": "The testing package dynamically sets b.N to improve the reliability of\nbenchmarks and uses it in computations to determine the duration of a\nsingle operation. Benchmark code must not alter b.N as this would\nfalsify results.",
			"TitleMarkdown": "Assigning to `b.N` in benchmarks distorts the results",
			"TextMarkdown": "The testing package dynamically sets `b.N` to improve the reliability of\nbenchmarks and uses it in computations to determine the duration of a\nsingle operation. Benchmark code must not alter `b.N` as this would\nfalsify results.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA4000": {
			"Title": "Binary operator has identical expressions on both sides",
			"Text": "",
			"TitleMarkdown": "Binary operator has identical expressions on both sides",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4001": {
			"Title": "\u0026*x gets simplified to x, it does not copy x",
			"Text": "",
			"TitleMarkdown": "`\u0026*x` gets simplified to `x`, it does not copy `x`",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4003": {
			"Title": "Comparing unsigned values against negative values is pointless",
			"Text": "",
			"TitleMarkdown": "Comparing unsigned values against negative values is pointless",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 1
		},
		"SA4004": {
			"Title": "The loop exits unconditionally after one iteration",
			"Text": "",
			"TitleMarkdown": "The loop exits unconditionally after one iteration",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 1
		},
		"SA4005": {
			"Title": "Field assignment that will never be observed. Did you mean to use a pointer receiver?",
			"Text": "",
			"TitleMarkdown": "Field assignment that will never be observed. Did you mean to use a pointer receiver?",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4006": {
			"Title": "A value assigned to a variable is never read before being overwritten. Forgotten error check or dead code?",
			"Text": "",
			"TitleMarkdown": "A value assigned to a variable is never read before being overwritten. Forgotten error check or dead code?",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 1
		},
		"SA4008": {
			"Title": "The variable in the loop condition never changes, are you incrementing the wrong variable?",
			"Text": "",
			"TitleMarkdown": "The variable in the loop condition never changes, are you incrementing the wrong variable?",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 1
		},
		"SA4009": {
			"Title": "A function argument is overwritten before its first use",
			"Text": "",
			"TitleMarkdown": "A function argument is overwritten before its first use",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4010": {
			"Title": "The result of append will never be observed anywhere",
			"Text": "",
			"TitleMarkdown": "The result of `append` will never be observed anywhere",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 1
		},
		"SA4011": {
			"Title": "Break statement with no effect. Did you mean to break out of an outer loop?",
			"Text": "",
			"TitleMarkdown": "Break statement with no effect. Did you mean to break out of an outer loop?",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4012": {
			"Title": "Comparing a value against NaN even though no value is equal to NaN",
			"Text": "",
			"TitleMarkdown": "Comparing a value against NaN even though no value is equal to NaN",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4013": {
			"Title": "Negating a boolean twice (!!b) is the same as writing b. This is either redundant, or a typo.",
			"Text": "",
			"TitleMarkdown": "Negating a boolean twice (`!!b`) is the same as writing `b`. This is either redundant, or a typo.",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4014": {
			"Title": "An if/else if chain has repeated conditions and no side-effects; if the condition didn't match the first time, it won't match the second time, either",
			"Text": "",
			"TitleMarkdown": "An if/else if chain has repeated conditions and no side-effects; if the condition didn't match the first time, it won't match the second time, either",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 1
		},
		"SA4015": {
			"Title": "Calling functions like math.Ceil on floats converted from integers doesn't do anything useful",
			"Text": "",
			"TitleMarkdown": "Calling functions like `math.Ceil` on floats converted from integers doesn't do anything useful",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 1
		},
		"SA4016": {
			"Title": "Certain bitwise operations, such as x ^ 0, do not do anything useful",
			"Text": "",
			"TitleMarkdown": "Certain bitwise operations, such as `x ^ 0`, do not do anything useful",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4017": {
			"Title": "Discarding the return values of a function without side effects, making the call pointless",
			"Text": "",
			"TitleMarkdown": "Discarding the return values of a function without side effects, making the call pointless",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 1
		},
		"SA4018": {
			"Title": "Self-assignment of variables",
			"Text": "",
			"TitleMarkdown": "Self-assignment of variables",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4019": {
			"Title": "Multiple, identical build constraints in the same file",
			"Text": "",
			"TitleMarkdown": "Multiple, identical build constraints in the same file",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4020": {
			"Title": "Unreachable case clause in a type switch",
			"Text": "In a type switch like the following\n\n```go\ntype T struct{}\nfunc (T) Read(b []byte) (int, error) { return 0, nil }\n\nvar v interface{} = T{}\n\nswitch v.(type) {\ncase io.Reader:\n    // ...\ncase T:\n    // unreachable\n}\n```\n\nthe second case clause can never be reached because T implements\nio.Reader and case clauses are evaluated in source order.\n\nAnother example:\n\n```go\ntype T struct{}\nfunc (T) Read(b []byte) (int, error) { return 0, nil }\nfunc (T) Close() error { return nil }\n\nvar v interface{} = T{}\n\nswitch v.(type) {\ncase io.Reader:\n    // ...\ncase io.ReadCloser:\n    // unreachable\n}\n```\n\nEven though T has a Close method and thus implements io.ReadCloser,\nio.Reader will always match first. The method set of io.Reader is a\nsubset of io.ReadCloser. Thus it is impossible to match the second\ncase without matching the first case.\n\n\n#### Structurally equivalent interfaces\n\nA special case of the previous example are structurally identical\ninterfaces. Given these declarations\n\n```go\ntype T error\ntype V error\n\nfunc doSomething() error {\n    err, ok := doAnotherThing()\n    if ok {\n        return T(err)\n    }\n\n    return U(err)\n}\n```\n\nthe following type switch will have an unreachable case clause:\n\n```go\nswitch doSomething().(type) {\ncase T:\n    // ...\ncase V:\n    // unreachable\n}\n```\n\nT will always match before V because they are structurally equivalent\nand therefore doSomething()'s return value implements both.",
			"TitleMarkdown": "Unreachable case clause in a type switch",
			"TextMarkdown": "In a type switch like the following\n\n```go\ntype T struct{}\nfunc (T) Read(b []byte) (int, error) { return 0, nil }\n\nvar v interface{} = T{}\n\nswitch v.(type) {\ncase io.Reader:\n    // ...\ncase T:\n    // unreachable\n}\n```\n\nthe second case clause can never be reached because `T` implements\n`io.Reader` and case clauses are evaluated in source order.\n\nAnother example:\n\n```go\ntype T struct{}\nfunc (T) Read(b []byte) (int, error) { return 0, nil }\nfunc (T) Close() error { return nil }\n\nvar v interface{} = T{}\n\nswitch v.(type) {\ncase io.Reader:\n    // ...\ncase io.ReadCloser:\n    // unreachable\n}\n```\n\nEven though `T` has a `Close` method and thus implements `io.ReadCloser`,\n`io.Reader` will always match first. The method set of `io.Reader` is a\nsubset of `io.ReadCloser`. Thus it is impossible to match the second\ncase without matching the first case.\n\n\n#### Structurally equivalent interfaces\n\nA special case of the previous example are structurally identical\ninterfaces. Given these declarations\n\n```go\ntype T error\ntype V error\n\nfunc doSomething() error {\n    err, ok := doAnotherThing()\n    if ok {\n        return T(err)\n    }\n\n    return U(err)\n}\n```\n\nthe following type switch will have an unreachable case clause:\n\n```go\nswitch doSomething().(type) {\ncase T:\n    // ...\ncase V:\n    // unreachable\n}\n```\n\n`T` will always match before V because they are structurally equivalent\nand therefore `doSomething()`'s return value implements both.",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 1
		},
		"SA4021": {
			"Title": "'x = append(y)' is equivalent to 'x = y'",
			"Text": "",
			"TitleMarkdown": "`x = append(y)` is equivalent to `x = y`",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4022": {
			"Title": "Comparing the address of a variable against nil",
			"Text": "Code such as 'if \u0026x == nil' is meaningless, because taking the address of a variable always yields a non-nil pointer.",
			"TitleMarkdown": "Comparing the address of a variable against nil",
			"TextMarkdown": "Code such as `if \u0026x == nil` is meaningless, because taking the address of a variable always yields a non-nil pointer.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4023": {
			"Title": "Impossible comparison of interface value with untyped nil",
			"Text": "Under the covers, interfaces are implemented as two elements, a\ntype T and a value V. V is a concrete value such as an int,\nstruct or pointer, never an interface itself, and has type T. For\ninstance, if we store the int value 3 in an interface, the\nresulting interface value has, schematically, (T=int, V=3). The\nvalue V is also known as the interface's dynamic value, since a\ngiven interface variable might hold different values V (and\ncorresponding types T) during the execution of the program.\n\nAn interface value is nil only if the V and T are both\nunset, (T=nil, V is not set), In particular, a nil interface will\nalways hold a nil type. If we store a nil pointer of type *int\ninside an interface value, the inner type will be *int regardless\nof the value of the pointer: (T=*int, V=nil). Such an interface\nvalue will therefore be non-nil even when the pointer value V\ninside is nil.\n\nThis situation can be confusing, and arises when a nil value is\nstored inside an interface value such as an error return:\n\n```go\nfunc returnsError() error {\n    var p *MyError = nil\n    if bad() {\n        p = ErrBad\n    }\n    return p // Will always return a non-nil error.\n}\n```\n\nIf all goes well, the function returns a nil p, so the return\nvalue is an error interface value holding (T=*MyError, V=nil).\nThis means that if the caller compares the returned error to nil,\nit will always look as if there was an error even if nothing bad\nhappened. To return a proper nil error to the caller, the\nfunction must return an explicit nil:\n\n```go\nfunc returnsError() error {\n    if bad() {\n        return ErrBad\n    }\n    return nil\n}\n```\n\nIt's a good idea for functions that return errors always to use\nthe error type in their signature (as we did above) rather than a\nconcrete type such as *MyError, to help guarantee the error is\ncreated correctly. As an example, os.Open returns an error even\nthough, if not nil, it's always of concrete type *os.PathError.\n\nSimilar situations to those described here can arise whenever\ninterfaces are used. Just keep in mind that if any concrete value\nhas been stored in the interface, the interface will not be nil.\nFor more information, see The Laws of\nReflection (https://golang.org/doc/articles/laws_of_reflection.html).\n\nThis text has been copied from\nhttps://golang.org/doc/faq#nil_error, licensed under the Creative\nCommons Attribution 3.0 License.",
			"TitleMarkdown": "Impossible comparison of interface value with untyped nil",
			"TextMarkdown": "Under the covers, interfaces are implemented as two elements, a\ntype T and a value V. V is a concrete value such as an int,\nstruct or pointer, never an interface itself, and has type T. For\ninstance, if we store the int value 3 in an interface, the\nresulting interface value has, schematically, (T=int, V=3). The\nvalue V is also known as the interface's dynamic value, since a\ngiven interface variable might hold different values V (and\ncorresponding types T) during the execution of the program.\n\nAn interface value is nil only if the V and T are both\nunset, (T=nil, V is not set), In particular, a nil interface will\nalways hold a nil type. If we store a nil pointer of type *int\ninside an interface value, the inner type will be *int regardless\nof the value of the pointer: (T=*int, V=nil). Such an interface\nvalue will therefore be non-nil even when the pointer value V\ninside is nil.\n\nThis situation can be confusing, and arises when a nil value is\nstored inside an interface value such as an error return:\n\n```go\nfunc returnsError() error {\n    var p *MyError = nil\n    if bad() {\n        p = ErrBad\n    }\n    return p // Will always return a non-nil error.\n}\n```\n\nIf all goes well, the function returns a nil p, so the return\nvalue is an error interface value holding (T=*MyError, V=nil).\nThis means that if the caller compares the returned error to nil,\nit will always look as if there was an error even if nothing bad\nhappened. To return a proper nil error to the caller, the\nfunction must return an explicit nil:\n\n```go\nfunc returnsError() error {\n    if bad() {\n        return ErrBad\n    }\n    return nil\n}\n```\n\nIt's a good idea for functions that return errors always to use\nthe error type in their signature (as we did above) rather than a\nconcrete type such as `*MyError`, to help guarantee the error is\ncreated correctly. As an example, `os.Open` returns an error even\nthough, if not nil, it's always of concrete type *os.PathError.\n\nSimilar situations to those described here can arise whenever\ninterfaces are used. Just keep in mind that if any concrete value\nhas been stored in the interface, the interface will not be nil.\nFor more information, see The Laws of\nReflection (https://golang.org/doc/articles/laws_of_reflection.html).\n\nThis text has been copied from\nhttps://golang.org/doc/faq#nil_error, licensed under the Creative\nCommons Attribution 3.0 License.",
			"Before": "",
			"After": "",
			"Since": "2020.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4024": {
			"Title": "Checking for impossible return value from a builtin function",
			"Text": "Return values of the len and cap builtins cannot be negative.\n\nSee https://golang.org/pkg/builtin/#len and https://golang.org/pkg/builtin/#cap.\n\nExample:\n\n```go\nif len(slice) \u003c 0 {\n    fmt.Println(\"unreachable code\")\n}\n```",
			"TitleMarkdown": "Checking for impossible return value from a builtin function",
			"TextMarkdown": "Return values of the `len` and `cap` builtins cannot be negative.\n\nSee https://golang.org/pkg/builtin/#len and https://golang.org/pkg/builtin/#cap.\n\nExample:\n\n```go\nif len(slice) \u003c 0 {\n    fmt.Println(\"unreachable code\")\n}\n```",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4025": {
			"Title": "Integer division of literals that results in zero",
			"Text": "When dividing two integer constants, the result will\nalso be an integer. Thus, a division such as 2 / 3 results in 0.\nThis is true for all of the following examples:\n\n\t_ = 2 / 3\n\tconst _ = 2 / 3\n\tconst _ float64 = 2 / 3\n\t_ = float64(2 / 3)\n\nStaticcheck will flag such divisions if both sides of the division are\ninteger literals, as it is highly unlikely that the division was\nintended to truncate to zero. Staticcheck will not flag integer\ndivision involving named constants, to avoid noisy positives.",
			"TitleMarkdown": "Integer division of literals that results in zero",
			"TextMarkdown": "When dividing two integer constants, the result will\nalso be an integer. Thus, a division such as `2 / 3` results in `0`.\nThis is true for all of the following examples:\n\n\t_ = 2 / 3\n\tconst _ = 2 / 3\n\tconst _ float64 = 2 / 3\n\t_ = float64(2 / 3)\n\nStaticcheck will flag such divisions if both sides of the division are\ninteger literals, as it is highly unlikely that the division was\nintended to truncate to zero. Staticcheck will not flag integer\ndivision involving named constants, to avoid noisy positives.",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4026": {
			"Title": "Go constants cannot express negative zero",
			"Text": "In IEEE 754 floating point math, zero has a sign and can be positive\nor negative. This can be useful in certain numerical code.\n\nGo constants, however, cannot express negative zero. This means that\nthe literals -0.0 and 0.0 have the same ideal value (zero) and\nwill both represent positive zero at runtime.\n\nTo explicitly and reliably create a negative zero, you can use the\nmath.Copysign function: math.Copysign(0, -1).",
			"TitleMarkdown": "Go constants cannot express negative zero",
			"TextMarkdown": "In IEEE 754 floating point math, zero has a sign and can be positive\nor negative. This can be useful in certain numerical code.\n\nGo constants, however, cannot express negative zero. This means that\nthe literals `-0.0` and `0.0` have the same ideal value (zero) and\nwill both represent positive zero at runtime.\n\nTo explicitly and reliably create a negative zero, you can use the\n`math.Copysign` function: `math.Copysign(0, -1)`.",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4027": {
			"Title": "(*net/url.URL).Query returns a copy, modifying it doesn't change the URL",
			"Text": "(*net/url.URL).Query parses the current value of net/url.URL.RawQuery\nand returns it as a map of type net/url.Values. Subsequent changes to\nthis map will not affect the URL unless the map gets encoded and\nassigned to the URL's RawQuery.\n\nAs a consequence, the following code pattern is an expensive no-op:\nu.Query().Add(key, value).",
			"TitleMarkdown": "`(*net/url.URL).Query` returns a copy, modifying it doesn't change the URL",
			"TextMarkdown": "`(*net/url.URL).Query` parses the current value of `net/url.URL.RawQuery`\nand returns it as a map of type `net/url.Values`. Subsequent changes to\nthis map will not affect the URL unless the map gets encoded and\nassigned to the URL's `RawQuery`.\n\nAs a consequence, the following code pattern is an expensive no-op:\n`u.Query().Add(key, value)`.",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4028": {
			"Title": "x % 1 is always zero",
			"Text": "",
			"TitleMarkdown": "`x % 1` is always zero",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2022.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4029": {
			"Title": "Ineffective attempt at sorting slice",
			"Text": "sort.Float64Slice, sort.IntSlice, and sort.StringSlice are\ntypes, not functions. Doing x = sort.StringSlice(x) does nothing,\nespecially not sort any values. The correct usage is\nsort.Sort(sort.StringSlice(x)) or sort.StringSlice(x).Sort(),\nbut there are more convenient helpers, namely sort.Float64s,\nsort.Ints, and sort.Strings.",
			"TitleMarkdown": "Ineffective attempt at sorting slice",
			"TextMarkdown": "`sort.Float64Slice`, `sort.IntSlice`, and `sort.StringSlice` are\ntypes, not functions. Doing `x = sort.StringSlice(x)` does nothing,\nespecially not sort any values. The correct usage is\n`sort.Sort(sort.StringSlice(x))` or `sort.StringSlice(x).Sort()`,\nbut there are more convenient helpers, namely `sort.Float64s`,\n`sort.Ints`, and `sort.Strings`.",
			"Before": "",
			"After": "",
			"Since": "2022.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4030": {
			"Title": "Ineffective attempt at generating random number",
			"Text": "Functions in the math/rand package that accept upper limits, such\nas Intn, generate random numbers in the half-open interval [0,n). In\nother words, the generated numbers will be \u003e= 0 and \u003c n – they\ndon't include n. rand.Intn(1) therefore doesn't generate 0\nor 1, it always generates 0.",
			"TitleMarkdown": "Ineffective attempt at generating random number",
			"TextMarkdown": "Functions in the `math/rand` package that accept upper limits, such\nas `Intn`, generate random numbers in the half-open interval [0,n). In\nother words, the generated numbers will be `\u003e= 0` and `\u003c n` – they\ndon't include `n`. `rand.Intn(1)` therefore doesn't generate `0`\nor `1`, it always generates `0`.",
			"Before": "",
			"After": "",
			"Since": "2022.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA4031": {
			"Title": "Checking never-nil value against nil",
			"Text": "",
			"TitleMarkdown": "Checking never-nil value against nil",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2022.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA5000": {
			"Title": "Assignment to nil map",
			"Text": "",
			"TitleMarkdown": "Assignment to nil map",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA5001": {
			"Title": "Deferring Close before checking for a possible error",
			"Text": "",
			"TitleMarkdown": "Deferring `Close` before checking for a possible error",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA5002": {
			"Title": "The empty for loop ('for {}') spins and can block the scheduler",
			"Text": "",
			"TitleMarkdown": "The empty for loop (`for {}`) spins and can block the scheduler",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA5003": {
			"Title": "Defers in infinite loops will never execute",
			"Text": "Defers are scoped to the surrounding function, not the surrounding\nblock. In a function that never returns, i.e. one containing an\ninfinite loop, defers will never execute.",
			"TitleMarkdown": "Defers in infinite loops will never execute",
			"TextMarkdown": "Defers are scoped to the surrounding function, not the surrounding\nblock. In a function that never returns, i.e. one containing an\ninfinite loop, defers will never execute.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA5004": {
			"Title": "'for { select { ...' with an empty default branch spins",
			"Text": "",
			"TitleMarkdown": "`for { select { ...` with an empty default branch spins",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA5005": {
			"Title": "The finalizer references the finalized object, preventing garbage collection",
			"Text": "A finalizer is a function associated with an object that runs when the\ngarbage collector is ready to collect said object, that is when the\nobject is no longer referenced by anything.\n\nIf the finalizer references the object, however, it will always remain\nas the final reference to that object, preventing the garbage\ncollector from collecting the object. The finalizer will never run,\nand the object will never be collected, leading to a memory leak. That\nis why the finalizer should instead use its first argument to operate\non the object. That way, the number of references can temporarily go\nto zero before the object is being passed to the finalizer.",
			"TitleMarkdown": "The finalizer references the finalized object, preventing garbage collection",
			"TextMarkdown": "A finalizer is a function associated with an object that runs when the\ngarbage collector is ready to collect said object, that is when the\nobject is no longer referenced by anything.\n\nIf the finalizer references the object, however, it will always remain\nas the final reference to that object, preventing the garbage\ncollector from collecting the object. The finalizer will never run,\nand the object will never be collected, leading to a memory leak. That\nis why the finalizer should instead use its first argument to operate\non the object. That way, the number of references can temporarily go\nto zero before the object is being passed to the finalizer.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA5007": {
			"Title": "Infinite recursive call",
			"Text": "A function that calls itself recursively needs to have an exit\ncondition. Otherwise it will recurse forever, until the system runs\nout of memory.\n\nThis issue can be caused by simple bugs such as forgetting to add an\nexit condition. It can also happen \"on purpose\". Some languages have\ntail call optimization which makes certain infinite recursive calls\nsafe to use. Go, however, does not implement TCO, and as such a loop\nshould be used instead.",
			"TitleMarkdown": "Infinite recursive call",
			"TextMarkdown": "A function that calls itself recursively needs to have an exit\ncondition. Otherwise it will recurse forever, until the system runs\nout of memory.\n\nThis issue can be caused by simple bugs such as forgetting to add an\nexit condition. It can also happen \"on purpose\". Some languages have\ntail call optimization which makes certain infinite recursive calls\nsafe to use. Go, however, does not implement TCO, and as such a loop\nshould be used instead.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA5008": {
			"Title": "Invalid struct tag",
			"Text": "",
			"TitleMarkdown": "Invalid struct tag",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA5009": {
			"Title": "Invalid Printf call",
			"Text": "",
			"TitleMarkdown": "Invalid Printf call",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA5010": {
			"Title": "Impossible type assertion",
			"Text": "Some type assertions can be statically proven to be\nimpossible. This is the case when the method sets of both\narguments of the type assertion conflict with each other, for\nexample by containing the same method with different\nsignatures.\n\nThe Go compiler already applies this check when asserting from an\ninterface value to a concrete type. If the concrete type misses\nmethods from the interface, or if function signatures don't match,\nthen the type assertion can never succeed.\n\nThis check applies the same logic when asserting from one interface to\nanother. If both interface types contain the same method but with\ndifferent signatures, then the type assertion can never succeed,\neither.",
			"TitleMarkdown": "Impossible type assertion",
			"TextMarkdown": "Some type assertions can be statically proven to be\nimpossible. This is the case when the method sets of both\narguments of the type assertion conflict with each other, for\nexample by containing the same method with different\nsignatures.\n\nThe Go compiler already applies this check when asserting from an\ninterface value to a concrete type. If the concrete type misses\nmethods from the interface, or if function signatures don't match,\nthen the type assertion can never succeed.\n\nThis check applies the same logic when asserting from one interface to\nanother. If both interface types contain the same method but with\ndifferent signatures, then the type assertion can never succeed,\neither.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA5011": {
			"Title": "Possible nil pointer dereference",
			"Text": "A pointer is being dereferenced unconditionally, while\nalso being checked against nil in another place. This suggests that\nthe pointer may be nil and dereferencing it may panic. This is\ncommonly a result of improperly ordered code or missing return\nstatements. Consider the following examples:\n\n```go\nfunc fn(x *int) {\n    fmt.Println(*x)\n\n    // This nil check is equally important for the previous dereference\n    if x != nil {\n        foo(*x)\n    }\n}\n\nfunc TestFoo(t *testing.T) {\n    x := compute()\n    if x == nil {\n        t.Errorf(\"nil pointer received\")\n    }\n\n    // t.Errorf does not abort the test, so if x is nil, the next line will panic.\n    foo(*x)\n}\n```\n\nStaticcheck tries to deduce which functions abort control flow.\nFor example, it is aware that a function will not continue\nexecution after a call to panic or log.Fatal. However, sometimes\nthis detection fails, in particular in the presence of\nconditionals. Consider the following example:\n\n```go\nfunc Log(msg string, level int) {\n    fmt.Println(msg)\n    if level == levelFatal {\n        os.Exit(1)\n    }\n}\n\nfunc Fatal(msg string) {\n    Log(msg, levelFatal)\n}\n\nfunc fn(x *int) {\n    if x == nil {\n        Fatal(\"unexpected nil pointer\")\n    }\n    fmt.Println(*x)\n}\n```\n\nStaticcheck will flag the dereference of x, even though it is perfectly\nsafe. Staticcheck is not able to deduce that a call to\nFatal will exit the program. For the time being, the easiest\nworkaround is to modify the definition of Fatal like so:\n\n```go\nfunc Fatal(msg string) {\n    Log(msg, levelFatal)\n    panic(\"unreachable\")\n}\n```\n\nWe also hard-code functions from common logging packages such as\nlogrus. Please file an issue if we're missing support for a\npopular package.",
			"TitleMarkdown": "Possible nil pointer dereference",
			"TextMarkdown": "A pointer is being dereferenced unconditionally, while\nalso being checked against nil in another place. This suggests that\nthe pointer may be nil and dereferencing it may panic. This is\ncommonly a result of improperly ordered code or missing return\nstatements. Consider the following examples:\n\n```go\nfunc fn(x *int) {\n    fmt.Println(*x)\n\n    // This nil check is equally important for the previous dereference\n    if x != nil {\n        foo(*x)\n    }\n}\n\nfunc TestFoo(t *testing.T) {\n    x := compute()\n    if x == nil {\n        t.Errorf(\"nil pointer received\")\n    }\n\n    // t.Errorf does not abort the test, so if x is nil, the next line will panic.\n    foo(*x)\n}\n```\n\nStaticcheck tries to deduce which functions abort control flow.\nFor example, it is aware that a function will not continue\nexecution after a call to `panic` or `log.Fatal`. However, sometimes\nthis detection fails, in particular in the presence of\nconditionals. Consider the following example:\n\n```go\nfunc Log(msg string, level int) {\n    fmt.Println(msg)\n    if level == levelFatal {\n        os.Exit(1)\n    }\n}\n\nfunc Fatal(msg string) {\n    Log(msg, levelFatal)\n}\n\nfunc fn(x *int) {\n    if x == nil {\n        Fatal(\"unexpected nil pointer\")\n    }\n    fmt.Println(*x)\n}\n```\n\nStaticcheck will flag the dereference of `x`, even though it is perfectly\nsafe. Staticcheck is not able to deduce that a call to\nFatal will exit the program. For the time being, the easiest\nworkaround is to modify the definition of Fatal like so:\n\n```go\nfunc Fatal(msg string) {\n    Log(msg, levelFatal)\n    panic(\"unreachable\")\n}\n```\n\nWe also hard-code functions from common logging packages such as\nlogrus. Please file an issue if we're missing support for a\npopular package.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA5012": {
			"Title": "Passing odd-sized slice to function expecting even size",
			"Text": "Some functions that take slices as parameters expect the slices to have an even number of elements. \nOften, these functions treat elements in a slice as pairs. \nFor example, strings.NewReplacer takes pairs of old and new strings, \nand calling it with an odd number of elements would be an error.",
			"TitleMarkdown": "Passing odd-sized slice to function expecting even size",
			"TextMarkdown": "Some functions that take slices as parameters expect the slices to have an even number of elements. \nOften, these functions treat elements in a slice as pairs. \nFor example, `strings.NewReplacer` takes pairs of old and new strings, \nand calling it with an odd number of elements would be an error.",
			"Before": "",
			"After": "",
			"Since": "2020.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 1,
			"MergeIf": 0
		},
		"SA6000": {
			"Title": "Using regexp.Match or related in a loop, should use regexp.Compile",
			"Text": "",
			"TitleMarkdown": "Using `regexp.Match` or related in a loop, should use `regexp.Compile`",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA6001": {
			"Title": "Missing an optimization opportunity when indexing maps by byte slices",
			"Text": "Map keys must be comparable, which precludes the use of byte slices.\nThis usually leads to using string keys and converting byte slices to\nstrings.\n\nNormally, a conversion of a byte slice to a string needs to copy the data and\ncauses allocations. The compiler, however, recognizes m[string(b)] and\nuses the data of b directly, without copying it, because it knows that\nthe data can't change during the map lookup. This leads to the\ncounter-intuitive situation that\n\n```go\nk := string(b)\nprintln(m[k])\nprintln(m[k])\n```\n\nwill be less efficient than\n\n```go\nprintln(m[string(b)])\nprintln(m[string(b)])\n```\n\nbecause the first version needs to copy and allocate, while the second\none does not.\n\nFor some history on this optimization, check out commit\nf5f5a8b6209f84961687d993b93ea0d397f5d5bf in the Go repository.",
			"TitleMarkdown": "Missing an optimization opportunity when indexing maps by byte slices",
			"TextMarkdown": "Map keys must be comparable, which precludes the use of byte slices.\nThis usually leads to using string keys and converting byte slices to\nstrings.\n\nNormally, a conversion of a byte slice to a string needs to copy the data and\ncauses allocations. The compiler, however, recognizes `m[string(b)]` and\nuses the data of `b` directly, without copying it, because it knows that\nthe data can't change during the map lookup. This leads to the\ncounter-intuitive situation that\n\n```go\nk := string(b)\nprintln(m[k])\nprintln(m[k])\n```\n\nwill be less efficient than\n\n```go\nprintln(m[string(b)])\nprintln(m[string(b)])\n```\n\nbecause the first version needs to copy and allocate, while the second\none does not.\n\nFor some history on this optimization, check out commit\nf5f5a8b6209f84961687d993b93ea0d397f5d5bf in the Go repository.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA6002": {
			"Title": "Storing non-pointer values in sync.Pool allocates memory",
			"Text": "A sync.Pool is used to avoid unnecessary allocations and reduce the\namount of work the garbage collector has to do.\n\nWhen passing a value that is not a pointer to a function that accepts\nan interface, the value needs to be placed on the heap, which means an\nadditional allocation. Slices are a common thing to put in sync.Pools,\nand they're structs with 3 fields (length, capacity, and a pointer to\nan array). In order to avoid the extra allocation, one should store a\npointer to the slice instead.\n\nSee the comments on https://go-review.googlesource.com/c/go/+/24371\nthat discuss this problem.",
			"TitleMarkdown": "Storing non-pointer values in `sync.Pool` allocates memory",
			"TextMarkdown": "A `sync.Pool` is used to avoid unnecessary allocations and reduce the\namount of work the garbage collector has to do.\n\nWhen passing a value that is not a pointer to a function that accepts\nan interface, the value needs to be placed on the heap, which means an\nadditional allocation. Slices are a common thing to put in sync.Pools,\nand they're structs with 3 fields (length, capacity, and a pointer to\nan array). In order to avoid the extra allocation, one should store a\npointer to the slice instead.\n\nSee the comments on https://go-review.googlesource.com/c/go/+/24371\nthat discuss this problem.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA6003": {
			"Title": "Converting a string to a slice of runes before ranging over it",
			"Text": "You may want to loop over the runes in a string. Instead of converting\nthe string to a slice of runes and looping over that, you can loop\nover the string itself. That is,\n\n```go\nfor _, r := range s {}\n```\n\nand\n\n```go\nfor _, r := range []rune(s) {}\n```\n\nwill yield the same values. The first version, however, will be faster\nand avoid unnecessary memory allocations.\n\nDo note that if you are interested in the indices, ranging over a\nstring and over a slice of runes will yield different indices. The\nfirst one yields byte offsets, while the second one yields indices in\nthe slice of runes.",
			"TitleMarkdown": "Converting a string to a slice of runes before ranging over it",
			"TextMarkdown": "You may want to loop over the runes in a string. Instead of converting\nthe string to a slice of runes and looping over that, you can loop\nover the string itself. That is,\n\n```go\nfor _, r := range s {}\n```\n\nand\n\n```go\nfor _, r := range []rune(s) {}\n```\n\nwill yield the same values. The first version, however, will be faster\nand avoid unnecessary memory allocations.\n\nDo note that if you are interested in the indices, ranging over a\nstring and over a slice of runes will yield different indices. The\nfirst one yields byte offsets, while the second one yields indices in\nthe slice of runes.",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA6005": {
			"Title": "Inefficient string comparison with strings.ToLower or strings.ToUpper",
			"Text": "Converting two strings to the same case and comparing them like so\n\n```go\nif strings.ToLower(s1) == strings.ToLower(s2) {\n    ...\n}\n```\n\nis significantly more expensive than comparing them with\nstrings.EqualFold(s1, s2). This is due to memory usage as well as\ncomputational complexity.\n\nstrings.ToLower will have to allocate memory for the new strings, as\nwell as convert both strings fully, even if they differ on the very\nfirst byte. strings.EqualFold, on the other hand, compares the strings\none character at a time. It doesn't need to create two intermediate\nstrings and can return as soon as the first non-matching character has\nbeen found.\n\nFor a more in-depth explanation of this issue, see\nhttps://blog.digitalocean.com/how-to-efficiently-compare-strings-in-go/",
			"TitleMarkdown": "Inefficient string comparison with `strings.ToLower` or `strings.ToUpper`",
			"TextMarkdown": "Converting two strings to the same case and comparing them like so\n\n```go\nif strings.ToLower(s1) == strings.ToLower(s2) {\n    ...\n}\n```\n\nis significantly more expensive than comparing them with\n`strings.EqualFold(s1, s2)`. This is due to memory usage as well as\ncomputational complexity.\n\n`strings.ToLower` will have to allocate memory for the new strings, as\nwell as convert both strings fully, even if they differ on the very\nfirst byte. strings.EqualFold, on the other hand, compares the strings\none character at a time. It doesn't need to create two intermediate\nstrings and can return as soon as the first non-matching character has\nbeen found.\n\nFor a more in-depth explanation of this issue, see\nhttps://blog.digitalocean.com/how-to-efficiently-compare-strings-in-go/",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA9001": {
			"Title": "Defers in range loops may not run when you expect them to",
			"Text": "",
			"TitleMarkdown": "Defers in range loops may not run when you expect them to",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA9002": {
			"Title": "Using a non-octal os.FileMode that looks like it was meant to be in octal.",
			"Text": "",
			"TitleMarkdown": "Using a non-octal `os.FileMode` that looks like it was meant to be in octal.",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA9003": {
			"Title": "Empty body in an if or else branch",
			"Text": "",
			"TitleMarkdown": "Empty body in an if or else branch",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2017.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA9004": {
			"Title": "Only the first constant has an explicit type",
			"Text": "In a constant declaration such as the following:\n\n```go\nconst (\n    First byte = 1\n    Second     = 2\n)\n```\n\nthe constant Second does not have the same type as the constant First.\nThis construct shouldn't be confused with\n\n```go\nconst (\n    First byte = iota\n    Second\n)\n```\n\nwhere First and Second do indeed have the same type. The type is only\npassed on when no explicit value is assigned to the constant.\n\nWhen declaring enumerations with explicit values it is therefore\nimportant not to write\n\n```go\nconst (\n      EnumFirst EnumType = 1\n      EnumSecond         = 2\n      EnumThird          = 3\n)\n```\n\nThis discrepancy in types can cause various confusing behaviors and\nbugs.\n\n\n#### Wrong type in variable declarations\n\nThe most obvious issue with such incorrect enumerations expresses\nitself as a compile error:\n\n```go\npackage pkg\n\nconst (\n    EnumFirst  uint8 = 1\n    EnumSecond       = 2\n)\n\nfunc fn(useFirst bool) {\n    x := EnumSecond\n    if useFirst {\n        x = EnumFirst\n    }\n}\n```\n\nfails to compile with\n\n```go\n./const.go:11:5: cannot use EnumFirst (type uint8) as type int in assignment\n```\n\n\n#### Losing method sets\n\nA more subtle issue occurs with types that have methods and optional\ninterfaces. Consider the following:\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype Enum int\n\nfunc (e Enum) String() string {\n    return \"an enum\"\n}\n\nconst (\n    EnumFirst  Enum = 1\n    EnumSecond      = 2\n)\n\nfunc main() {\n    fmt.Println(EnumFirst)\n    fmt.Println(EnumSecond)\n}\n```\n\nThis code will output\n\n```go\nan enum\n2\n```\n\nas EnumSecond has no explicit type, and thus defaults to int.",
			"TitleMarkdown": "Only the first constant has an explicit type",
			"TextMarkdown": "In a constant declaration such as the following:\n\n```go\nconst (\n    First byte = 1\n    Second     = 2\n)\n```\n\nthe constant Second does not have the same type as the constant First.\nThis construct shouldn't be confused with\n\n```go\nconst (\n    First byte = iota\n    Second\n)\n```\n\nwhere `First` and `Second` do indeed have the same type. The type is only\npassed on when no explicit value is assigned to the constant.\n\nWhen declaring enumerations with explicit values it is therefore\nimportant not to write\n\n```go\nconst (\n      EnumFirst EnumType = 1\n      EnumSecond         = 2\n      EnumThird          = 3\n)\n```\n\nThis discrepancy in types can cause various confusing behaviors and\nbugs.\n\n\n#### Wrong type in variable declarations\n\nThe most obvious issue with such incorrect enumerations expresses\nitself as a compile error:\n\n```go\npackage pkg\n\nconst (\n    EnumFirst  uint8 = 1\n    EnumSecond       = 2\n)\n\nfunc fn(useFirst bool) {\n    x := EnumSecond\n    if useFirst {\n        x = EnumFirst\n    }\n}\n```\n\nfails to compile with\n\n```go\n./const.go:11:5: cannot use EnumFirst (type uint8) as type int in assignment\n```\n\n\n#### Losing method sets\n\nA more subtle issue occurs with types that have methods and optional\ninterfaces. Consider the following:\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype Enum int\n\nfunc (e Enum) String() string {\n    return \"an enum\"\n}\n\nconst (\n    EnumFirst  Enum = 1\n    EnumSecond      = 2\n)\n\nfunc main() {\n    fmt.Println(EnumFirst)\n    fmt.Println(EnumSecond)\n}\n```\n\nThis code will output\n\n```go\nan enum\n2\n```\n\nas `EnumSecond` has no explicit type, and thus defaults to `int`.",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA9005": {
			"Title": "Trying to marshal a struct with no public fields nor custom marshaling",
			"Text": "The encoding/json and encoding/xml packages only operate on exported\nfields in structs, not unexported ones. It is usually an error to try\nto (un)marshal structs that only consist of unexported fields.\n\nThis check will not flag calls involving types that define custom\nmarshaling behavior, e.g. via MarshalJSON methods. It will also not\nflag empty structs.",
			"TitleMarkdown": "Trying to marshal a struct with no public fields nor custom marshaling",
			"TextMarkdown": "The `encoding/json` and `encoding/xml` packages only operate on exported\nfields in structs, not unexported ones. It is usually an error to try\nto (un)marshal structs that only consist of unexported fields.\n\nThis check will not flag calls involving types that define custom\nmarshaling behavior, e.g. via `MarshalJSON` methods. It will also not\nflag empty structs.",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 1
		},
		"SA9006": {
			"Title": "Dubious bit shifting of a fixed size integer value",
			"Text": "Bit shifting a value past its size will always clear the value.\n\nFor instance:\n\n```go\nv := int8(42)\nv \u003e\u003e= 8\n```\n\nwill always result in 0.\n\nThis check flags bit shifting operations on fixed size integer values only.\nThat is, int, uint and uintptr are never flagged to avoid potential false\npositives in somewhat exotic but valid bit twiddling tricks:\n\n```go\n// Clear any value above 32 bits if integers are more than 32 bits.\nfunc f(i int) int {\n    v := i \u003e\u003e 32\n    v = v \u003c\u003c 32\n    return i-v\n}\n```",
			"TitleMarkdown": "Dubious bit shifting of a fixed size integer value",
			"TextMarkdown": "Bit shifting a value past its size will always clear the value.\n\nFor instance:\n\n```go\nv := int8(42)\nv \u003e\u003e= 8\n```\n\nwill always result in 0.\n\nThis check flags bit shifting operations on fixed size integer values only.\nThat is, int, uint and uintptr are never flagged to avoid potential false\npositives in somewhat exotic but valid bit twiddling tricks:\n\n```go\n// Clear any value above 32 bits if integers are more than 32 bits.\nfunc f(i int) int {\n    v := i \u003e\u003e 32\n    v = v \u003c\u003c 32\n    return i-v\n}\n```",
			"Before": "",
			"After": "",
			"Since": "2020.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA9007": {
			"Title": "Deleting a directory that shouldn't be deleted",
			"Text": "It is virtually never correct to delete system directories such as\n/tmp or the user's home directory. However, it can be fairly easy to\ndo by mistake, for example by mistakingly using os.TempDir instead\nof ioutil.TempDir, or by forgetting to add a suffix to the result\nof os.UserHomeDir.\n\nWriting\n\n```go\nd := os.TempDir()\ndefer os.RemoveAll(d)\n```\n\nin your unit tests will have a devastating effect on the stability of your system.\n\nThis check flags attempts at deleting the following directories:\n\n- os.TempDir\n- os.UserCacheDir\n- os.UserConfigDir\n- os.UserHomeDir",
			"TitleMarkdown": "Deleting a directory that shouldn't be deleted",
			"TextMarkdown": "It is virtually never correct to delete system directories such as\n/tmp or the user's home directory. However, it can be fairly easy to\ndo by mistake, for example by mistakingly using `os.TempDir` instead\nof `ioutil.TempDir`, or by forgetting to add a suffix to the result\nof `os.UserHomeDir`.\n\nWriting\n\n```go\nd := os.TempDir()\ndefer os.RemoveAll(d)\n```\n\nin your unit tests will have a devastating effect on the stability of your system.\n\nThis check flags attempts at deleting the following directories:\n\n- os.TempDir\n- os.UserCacheDir\n- os.UserConfigDir\n- os.UserHomeDir",
			"Before": "",
			"After": "",
			"Since": "2022.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"SA9008": {
			"Title": "else branch of a type assertion is probably not reading the right value",
			"Text": "When declaring variables as part of an if statement (like in 'if\nfoo := ...; foo {'), the same variables will also be in the scope of\nthe else branch. This means that in the following example\n\n```go\nif x, ok := x.(int); ok {\n    // ...\n} else {\n    fmt.Printf(\"unexpected type %T\", x)\n}\n```\n\nx in the else branch will refer to the x from x, ok\n:=; it will not refer to the x that is being type-asserted. The\nresult of a failed type assertion is the zero value of the type that\nis being asserted to, so x in the else branch will always have the\nvalue 0 and the type int.",
			"TitleMarkdown": "`else` branch of a type assertion is probably not reading the right value",
			"TextMarkdown": "When declaring variables as part of an `if` statement (like in `if\nfoo := ...; foo {`), the same variables will also be in the scope of\nthe `else` branch. This means that in the following example\n\n```go\nif x, ok := x.(int); ok {\n    // ...\n} else {\n    fmt.Printf(\"unexpected type %T\", x)\n}\n```\n\n`x` in the `else` branch will refer to the `x` from `x, ok\n:=`; it will not refer to the `x` that is being type-asserted. The\nresult of a failed type assertion is the zero value of the type that\nis being asserted to, so `x` in the else branch will always have the\nvalue `0` and the type `int`.",
			"Before": "",
			"After": "",
			"Since": "2022.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 3,
			"MergeIf": 0
		},
		"ST1000": {
			"Title": "Incorrect or missing package comment",
			"Text": "Packages must have a package comment that is formatted according to\nthe guidelines laid out in\nhttps://github.com/golang/go/wiki/CodeReviewComments#package-comments.",
			"TitleMarkdown": "Incorrect or missing package comment",
			"TextMarkdown": "Packages must have a package comment that is formatted according to\nthe guidelines laid out in\nhttps://github.com/golang/go/wiki/CodeReviewComments#package-comments.",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": true,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1001": {
			"Title": "Dot imports are discouraged",
			"Text": "Dot imports that aren't in external test packages are discouraged.\n\nThe dot_import_whitelist option can be used to whitelist certain\nimports.\n\nQuoting Go Code Review Comments:\n\n\u003e The import . form can be useful in tests that, due to circular\n\u003e dependencies, cannot be made part of the package being tested:\n\u003e \n\u003e     package foo_test\n\u003e \n\u003e     import (\n\u003e         \"bar/testutil\" // also imports \"foo\"\n\u003e         . \"foo\"\n\u003e     )\n\u003e \n\u003e In this case, the test file cannot be in package foo because it\n\u003e uses bar/testutil, which imports foo. So we use the import .\n\u003e form to let the file pretend to be part of package foo even though\n\u003e it is not. Except for this one case, do not use import . in your\n\u003e programs. It makes the programs much harder to read because it is\n\u003e unclear whether a name like Quux is a top-level identifier in the\n\u003e current package or in an imported package.",
			"TitleMarkdown": "Dot imports are discouraged",
			"TextMarkdown": "Dot imports that aren't in external test packages are discouraged.\n\nThe `dot_import_whitelist` option can be used to whitelist certain\nimports.\n\nQuoting Go Code Review Comments:\n\n\u003e The `import .` form can be useful in tests that, due to circular\n\u003e dependencies, cannot be made part of the package being tested:\n\u003e \n\u003e     package foo_test\n\u003e \n\u003e     import (\n\u003e         \"bar/testutil\" // also imports \"foo\"\n\u003e         . \"foo\"\n\u003e     )\n\u003e \n\u003e In this case, the test file cannot be in package foo because it\n\u003e uses `bar/testutil`, which imports `foo`. So we use the `import .`\n\u003e form to let the file pretend to be part of package foo even though\n\u003e it is not. Except for this one case, do not use `import .` in your\n\u003e programs. It makes the programs much harder to read because it is\n\u003e unclear whether a name like `Quux` is a top-level identifier in the\n\u003e current package or in an imported package.",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": [
				"dot_import_whitelist"
			],
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1003": {
			"Title": "Poorly chosen identifier",
			"Text": "Identifiers, such as variable and package names, follow certain rules.\n\nSee the following links for details:\n\n- https://golang.org/doc/effective_go.html#package-names\n- https://golang.org/doc/effective_go.html#mixed-caps\n- https://github.com/golang/go/wiki/CodeReviewComments#initialisms\n- https://github.com/golang/go/wiki/CodeReviewComments#variable-names",
			"TitleMarkdown": "Poorly chosen identifier",
			"TextMarkdown": "Identifiers, such as variable and package names, follow certain rules.\n\nSee the following links for details:\n\n- https://golang.org/doc/effective_go.html#package-names\n- https://golang.org/doc/effective_go.html#mixed-caps\n- https://github.com/golang/go/wiki/CodeReviewComments#initialisms\n- https://github.com/golang/go/wiki/CodeReviewComments#variable-names",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": true,
			"Options": [
				"initialisms"
			],
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1005": {
			"Title": "Incorrectly formatted error string",
			"Text": "Error strings follow a set of guidelines to ensure uniformity and good\ncomposability.\n\nQuoting Go Code Review Comments:\n\n\u003e Error strings should not be capitalized (unless beginning with\n\u003e proper nouns or acronyms) or end with punctuation, since they are\n\u003e usually printed following other context. That is, use\n\u003e fmt.Errorf(\"something bad\") not fmt.Errorf(\"Something bad\"), so\n\u003e that log.Printf(\"Reading %s: %v\", filename, err) formats without a\n\u003e spurious capital letter mid-message.",
			"TitleMarkdown": "Incorrectly formatted error string",
			"TextMarkdown": "Error strings follow a set of guidelines to ensure uniformity and good\ncomposability.\n\nQuoting Go Code Review Comments:\n\n\u003e Error strings should not be capitalized (unless beginning with\n\u003e proper nouns or acronyms) or end with punctuation, since they are\n\u003e usually printed following other context. That is, use\n\u003e `fmt.Errorf(\"something bad\")` not `fmt.Errorf(\"Something bad\")`, so\n\u003e that `log.Printf(\"Reading %s: %v\", filename, err)` formats without a\n\u003e spurious capital letter mid-message.",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1006": {
			"Title": "Poorly chosen receiver name",
			"Text": "Quoting Go Code Review Comments:\n\n\u003e The name of a method's receiver should be a reflection of its\n\u003e identity; often a one or two letter abbreviation of its type\n\u003e suffices (such as \"c\" or \"cl\" for \"Client\"). Don't use generic\n\u003e names such as \"me\", \"this\" or \"self\", identifiers typical of\n\u003e object-oriented languages that place more emphasis on methods as\n\u003e opposed to functions. The name need not be as descriptive as that\n\u003e of a method argument, as its role is obvious and serves no\n\u003e documentary purpose. It can be very short as it will appear on\n\u003e almost every line of every method of the type; familiarity admits\n\u003e brevity. Be consistent, too: if you call the receiver \"c\" in one\n\u003e method, don't call it \"cl\" in another.",
			"TitleMarkdown": "Poorly chosen receiver name",
			"TextMarkdown": "Quoting Go Code Review Comments:\n\n\u003e The name of a method's receiver should be a reflection of its\n\u003e identity; often a one or two letter abbreviation of its type\n\u003e suffices (such as \"c\" or \"cl\" for \"Client\"). Don't use generic\n\u003e names such as \"me\", \"this\" or \"self\", identifiers typical of\n\u003e object-oriented languages that place more emphasis on methods as\n\u003e opposed to functions. The name need not be as descriptive as that\n\u003e of a method argument, as its role is obvious and serves no\n\u003e documentary purpose. It can be very short as it will appear on\n\u003e almost every line of every method of the type; familiarity admits\n\u003e brevity. Be consistent, too: if you call the receiver \"c\" in one\n\u003e method, don't call it \"cl\" in another.",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1008": {
			"Title": "A function's error value should be its last return value",
			"Text": "A function's error value should be its last return value.",
			"TitleMarkdown": "A function's error value should be its last return value",
			"TextMarkdown": "A function's error value should be its last return value.",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1011": {
			"Title": "Poorly chosen name for variable of type time.Duration",
			"Text": "time.Duration values represent an amount of time, which is represented\nas a count of nanoseconds. An expression like 5 * time.Microsecond\nyields the value 5000. It is therefore not appropriate to suffix a\nvariable of type time.Duration with any time unit, such as Msec or\nMilli.",
			"TitleMarkdown": "Poorly chosen name for variable of type `time.Duration`",
			"TextMarkdown": "`time.Duration` values represent an amount of time, which is represented\nas a count of nanoseconds. An expression like `5 * time.Microsecond`\nyields the value `5000`. It is therefore not appropriate to suffix a\nvariable of type `time.Duration` with any time unit, such as `Msec` or\n`Milli`.",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1012": {
			"Title": "Poorly chosen name for error variable",
			"Text": "Error variables that are part of an API should be called errFoo or\nErrFoo.",
			"TitleMarkdown": "Poorly chosen name for error variable",
			"TextMarkdown": "Error variables that are part of an API should be called `errFoo` or\n`ErrFoo`.",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1013": {
			"Title": "Should use constants for HTTP error codes, not magic numbers",
			"Text": "HTTP has a tremendous number of status codes. While some of those are\nwell known (200, 400, 404, 500), most of them are not. The net/http\npackage provides constants for all status codes that are part of the\nvarious specifications. It is recommended to use these constants\ninstead of hard-coding magic numbers, to vastly improve the\nreadability of your code.",
			"TitleMarkdown": "Should use constants for HTTP error codes, not magic numbers",
			"TextMarkdown": "HTTP has a tremendous number of status codes. While some of those are\nwell known (200, 400, 404, 500), most of them are not. The `net/http`\npackage provides constants for all status codes that are part of the\nvarious specifications. It is recommended to use these constants\ninstead of hard-coding magic numbers, to vastly improve the\nreadability of your code.",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": [
				"http_status_code_whitelist"
			],
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1015": {
			"Title": "A switch's default case should be the first or last case",
			"Text": "",
			"TitleMarkdown": "A switch's default case should be the first or last case",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1016": {
			"Title": "Use consistent method receiver names",
			"Text": "",
			"TitleMarkdown": "Use consistent method receiver names",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2019.1",
			"NonDefault": true,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1017": {
			"Title": "Don't use Yoda conditions",
			"Text": "Yoda conditions are conditions of the kind 'if 42 == x', where the\nliteral is on the left side of the comparison. These are a common\nidiom in languages in which assignment is an expression, to avoid bugs\nof the kind 'if (x = 42)'. In Go, which doesn't allow for this kind of\nbug, we prefer the more idiomatic 'if x == 42'.",
			"TitleMarkdown": "Don't use Yoda conditions",
			"TextMarkdown": "Yoda conditions are conditions of the kind `if 42 == x`, where the\nliteral is on the left side of the comparison. These are a common\nidiom in languages in which assignment is an expression, to avoid bugs\nof the kind `if (x = 42)`. In Go, which doesn't allow for this kind of\nbug, we prefer the more idiomatic `if x == 42`.",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1018": {
			"Title": "Avoid zero-width and control characters in string literals",
			"Text": "",
			"TitleMarkdown": "Avoid zero-width and control characters in string literals",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2019.2",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1019": {
			"Title": "Importing the same package multiple times",
			"Text": "Go allows importing the same package multiple times, as long as\ndifferent import aliases are being used. That is, the following\nbit of code is valid:\n\n```go\nimport (\n    \"fmt\"\n    fumpt \"fmt\"\n    format \"fmt\"\n    _ \"fmt\"\n)\n```\n\nHowever, this is very rarely done on purpose. Usually, it is a\nsign of code that got refactored, accidentally adding duplicate\nimport statements. It is also a rarely known feature, which may\ncontribute to confusion.\n\nDo note that sometimes, this feature may be used\nintentionally (see for example\nhttps://github.com/golang/go/commit/3409ce39bfd7584523b7a8c150a310cea92d879d)\n– if you want to allow this pattern in your code base, you're\nadvised to disable this check.",
			"TitleMarkdown": "Importing the same package multiple times",
			"TextMarkdown": "Go allows importing the same package multiple times, as long as\ndifferent import aliases are being used. That is, the following\nbit of code is valid:\n\n```go\nimport (\n    \"fmt\"\n    fumpt \"fmt\"\n    format \"fmt\"\n    _ \"fmt\"\n)\n```\n\nHowever, this is very rarely done on purpose. Usually, it is a\nsign of code that got refactored, accidentally adding duplicate\nimport statements. It is also a rarely known feature, which may\ncontribute to confusion.\n\nDo note that sometimes, this feature may be used\nintentionally (see for example\nhttps://github.com/golang/go/commit/3409ce39bfd7584523b7a8c150a310cea92d879d)\n– if you want to allow this pattern in your code base, you're\nadvised to disable this check.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": false,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1020": {
			"Title": "The documentation of an exported function should start with the function's name",
			"Text": "Doc comments work best as complete sentences, which\nallow a wide variety of automated presentations. The first sentence\nshould be a one-sentence summary that starts with the name being\ndeclared.\n\nIf every doc comment begins with the name of the item it describes,\nyou can use the doc subcommand of the go tool and run the output\nthrough grep.\n\nSee https://golang.org/doc/effective_go.html#commentary for more\ninformation on how to write good documentation.",
			"TitleMarkdown": "The documentation of an exported function should start with the function's name",
			"TextMarkdown": "Doc comments work best as complete sentences, which\nallow a wide variety of automated presentations. The first sentence\nshould be a one-sentence summary that starts with the name being\ndeclared.\n\nIf every doc comment begins with the name of the item it describes,\nyou can use the `doc` subcommand of the `go` tool and run the output\nthrough grep.\n\nSee https://golang.org/doc/effective_go.html#commentary for more\ninformation on how to write good documentation.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": true,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1021": {
			"Title": "The documentation of an exported type should start with type's name",
			"Text": "Doc comments work best as complete sentences, which\nallow a wide variety of automated presentations. The first sentence\nshould be a one-sentence summary that starts with the name being\ndeclared.\n\nIf every doc comment begins with the name of the item it describes,\nyou can use the doc subcommand of the go tool and run the output\nthrough grep.\n\nSee https://golang.org/doc/effective_go.html#commentary for more\ninformation on how to write good documentation.",
			"TitleMarkdown": "The documentation of an exported type should start with type's name",
			"TextMarkdown": "Doc comments work best as complete sentences, which\nallow a wide variety of automated presentations. The first sentence\nshould be a one-sentence summary that starts with the name being\ndeclared.\n\nIf every doc comment begins with the name of the item it describes,\nyou can use the `doc` subcommand of the `go` tool and run the output\nthrough grep.\n\nSee https://golang.org/doc/effective_go.html#commentary for more\ninformation on how to write good documentation.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": true,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1022": {
			"Title": "The documentation of an exported variable or constant should start with variable's name",
			"Text": "Doc comments work best as complete sentences, which\nallow a wide variety of automated presentations. The first sentence\nshould be a one-sentence summary that starts with the name being\ndeclared.\n\nIf every doc comment begins with the name of the item it describes,\nyou can use the doc subcommand of the go tool and run the output\nthrough grep.\n\nSee https://golang.org/doc/effective_go.html#commentary for more\ninformation on how to write good documentation.",
			"TitleMarkdown": "The documentation of an exported variable or constant should start with variable's name",
			"TextMarkdown": "Doc comments work best as complete sentences, which\nallow a wide variety of automated presentations. The first sentence\nshould be a one-sentence summary that starts with the name being\ndeclared.\n\nIf every doc comment begins with the name of the item it describes,\nyou can use the `doc` subcommand of the `go` tool and run the output\nthrough grep.\n\nSee https://golang.org/doc/effective_go.html#commentary for more\ninformation on how to write good documentation.",
			"Before": "",
			"After": "",
			"Since": "2020.1",
			"NonDefault": true,
			"Options": null,
			"Severity": 0,
			"MergeIf": 0
		},
		"ST1023": {
			"Title": "Redundant type in variable declaration",
			"Text": "",
			"TitleMarkdown": "Redundant type in variable declaration",
			"TextMarkdown": "",
			"Before": "",
			"After": "",
			"Since": "2021.1",
			"NonDefault": true,
			"Options": null,
			"Severity": 0,
			"MergeIf": 1
		}
	},
	"ByCategory": {
		"QF1": [
			"QF1001",
			"QF1002",
			"QF1003",
			"QF1004",
			"QF1005",
			"QF1006",
			"QF1007",
			"QF1008",
			"QF1009",
			"QF1010",
			"QF1011",
			"QF1012"
		],
		"S1": [
			"S1000",
			"S1001",
			"S1002",
			"S1003",
			"S1004",
			"S1005",
			"S1006",
			"S1007",
			"S1008",
			"S1009",
			"S1010",
			"S1011",
			"S1012",
			"S1016",
			"S1017",
			"S1018",
			"S1019",
			"S1020",
			"S1021",
			"S1023",
			"S1024",
			"S1025",
			"S1028",
			"S1029",
			"S1030",
			"S1031",
			"S1032",
			"S1033",
			"S1034",
			"S1035",
			"S1036",
			"S1037",
			"S1038",
			"S1039",
			"S1040"
		],
		"SA1": [
			"SA1000",
			"SA1001",
			"SA1002",
			"SA1003",
			"SA1004",
			"SA1005",
			"SA1006",
			"SA1007",
			"SA1008",
			"SA1010",
			"SA1011",
			"SA1012",
			"SA1013",
			"SA1014",
			"SA1015",
			"SA1016",
			"SA1017",
			"SA1018",
			"SA1019",
			"SA1020",
			"SA1021",
			"SA1023",
			"SA1024",
			"SA1025",
			"SA1026",
			"SA1027",
			"SA1028",
			"SA1029",
			"SA1030"
		],
		"SA2": [
			"SA2000",
			"SA2001",
			"SA2002",
			"SA2003"
		],
		"SA3": [
			"SA3000",
			"SA3001"
		],
		"SA4": [
			"SA4000",
			"SA4001",
			"SA4003",
			"SA4004",
			"SA4005",
			"SA4006",
			"SA4008",
			"SA4009",
			"SA4010",
			"SA4011",
			"SA4012",
			"SA4013",
			"SA4014",
			"SA4015",
			"SA4016",
			"SA4017",
			"SA4018",
			"SA4019",
			"SA4020",
			"SA4021",
			"SA4022",
			"SA4023",
			"SA4024",
			"SA4025",
			"SA4026",
			"SA4027",
			"SA4028",
			"SA4029",
			"SA4030",
			"SA4031"
		],
		"SA5": [
			"SA5000",
			"SA5001",
			"SA5002",
			"SA5003",
			"SA5004",
			"SA5005",
			"SA5007",
			"SA5008",
			"SA5009",
			"SA5010",
			"SA5011",
			"SA5012"
		],
		"SA6": [
			"SA6000",
			"SA6001",
			"SA6002",
			"SA6003",
			"SA6005"
		],
		"SA9": [
			"SA9001",
			"SA9002",
			"SA9003",
			"SA9004",
			"SA9005",
			"SA9006",
			"SA9007",
			"SA9008"
		],
		"ST1": [
			"ST1000",
			"ST1001",
			"ST1003",
			"ST1005",
			"ST1006",
			"ST1008",
			"ST1011",
			"ST1012",
			"ST1013",
			"ST1015",
			"ST1016",
			"ST1017",
			"ST1018",
			"ST1019",
			"ST1020",
			"ST1021",
			"ST1022",
			"ST1023"
		]
	}
}
