Skip to content

chenfeining/go-npecheck

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

npecheck

pkg.go.dev

npecheck Check for potential nil pointer reference exceptions to compensate for go linter's shortcomings in this area. This linter is supposed to be the most rigorous and complete NPE solution.

How to use

$ go install github.com/chenfeining/go-npecheck/cmd/npecheck@latest
$ npecheck ./...

Test case

The full use case can be found at testdata. Some examples are posted here

  1. npecheck Function parameter is pointer, and its variable is directly referenced without validation
func np1Example(d *DataInfo) {
    fmt.Println(d.A) // want "potential nil pointer reference"

    // d may be is a nil pointer, you had better to check it before reference.
    // such as :
    // if d != nil {
    //	  fmt.Println(d.A)
    // }
    
    // Or:
    // if d == nil {
    //	  return
    // }
    // fmt.Println(d.A)
    
    // Otherwise it is potential nil pointer reference, sometimes it's unexpected disaster
}
  1. npecheck Function parameter is pointer, and its variables are directly referenced in a chain without validation
func np2Example(d *DataInfo) {
	fmt.Println(d.A.B) // want "potential nil pointer reference" "potential nil pointer reference"

	// d is a potential nil pointer
	// d.A is also a potential nil pointer
	// You can follow the writing below, and will be more safe:

	// if d != nil && d.A != nil {
	//     fmt.Println(d.A.B)
	//}

	// Or:
	// if d == nil {
	//	 return
	// }
	//
	// if d.A == nil {
	//	 return
	// }
	//
	// fmt.Println(d.A.B)
}
  1. npecheck A pointer variable obtained by calling an external function, unverified, directly referenced
func np3Example() {
	d := GetDataInfo() // d is a pointer obtained by calling an external function
	fmt.Println(d.A)   // want "potential nil pointer reference"

	// d may be is a nil pointer, you had better to check it before reference.
	// such as :
	// if d != nil {
	//	fmt.Println(d.A)
	// }

	// Or:
	// if d == nil {
	//	return
	// }
	// fmt.Println(d.A)

	// Otherwise it is potential nil pointer reference, sometimes it's unexpected disaster
}
  1. npecheck A pointer variable obtained by calling an external function, unverified, directly chain referenced
func np4Example() {
	d := GetDataInfo()
	fmt.Println(d.A.B) // want "potential nil pointer reference" "potential nil pointer reference"

	// d is a potential nil pointer
	// d.A is also a potential nil pointer
	// You can follow the writing below, and will be more safe:

	// if d != nil && d.A != nil {
	//     fmt.Println(d.A.B)
	//}

	// Or:
	// if d == nil {
	//	 return
	// }
	//
	// if d.A == nil {
	//	 return
	// }
	//
	// fmt.Println(d.A.B)
}
  1. npecheck Function input parameter is slice including pointer, and their elements are directly referenced without validation
func np5Example(infoList []*Node) {
	for _, info := range infoList {
		fmt.Println(info.A) // want "potential nil pointer reference"
		// info is a potential nil pointer
		// It can be written as follows, and will be more safe.

		// if info != nil {
		// 	fmt.Println(info.A)
		// }

		// Or:
		// if info == nil {
		// 	  continue
		// }
		// fmt.Println(info.A)
	}
}
  1. npecheck An slice including pointers obtained by a function, whose pointer elements are not checked and are directly referenced
func np6Example() {
	infoList := GetDataInfoList()
	for _, info := range infoList {
		fmt.Println(info.A) // want "potential nil pointer reference"

		// info is a potential nil pointer
		// It can be written as follows, and will be more safe.

		// if info != nil {
		// 	fmt.Println(info.A)
		// }

		// Or:
		// if info == nil {
		// 	  continue
		// }
		// 	fmt.Println(info.A)
	}
}
  1. npecheck Function parameter is pointer, and its method is directly referenced without validation
func np7Example1(d *DataInfo) {
	d.printDataInfo() // want "potential nil pointer reference"

	// d is a potential nil pointer
	// It can be written as follows, and will be more safe.
	// if d != nil {
	// 	d.printDataInfo()
	// }

	// Or:
	// if d == nil {
	// 	 return
	// }
	// d.printDataInfo()
}
  1. npecheck Function parameter is pointer, and its method is directly referenced in chain without validation
func np8Example(d *DataInfo) {
	_ = d.GetChildNodePtr().PrintScore() // want "potential nil pointer reference" "potential nil pointer reference"

	// d is a potential nil pointer reference
	// d.GetChildNodePtr() is also a potential nil pointer

	// It can be written as follows, and will be more safe.
	// if d != nil && d.GetChildNodePtr() != nil {
	// 	_ = d.GetChildNodePtr().PrintScore()
	// }

	// Or:
	// if d == nil {
	// 	 return
	// }
	//
	// if d.GetChildNodePtr() == nil {
	//	 return
	// }
	//
	// _ = d.GetChildNodePtr().PrintScore()
}
  1. npecheck A pointer variable obtained by calling an external function, and its method is directly referenced in chain without validation
func np9Example() {
	d := GetDataInfo()
	_ = d.GetChildNodePtr().PrintScore() // want "potential nil pointer reference" "potential nil pointer reference"

	// d is a potential nil pointer reference
	// d.GetChildNodePtr() is also a potential nil pointer

	// It can be written as follows, and will be more safe.
	// if d != nil && d.GetChildNodePtr() != nil {
	// 	_ = d.GetChildNodePtr().PrintScore()
	// }

	// Or:
	// if d == nil {
	// 	 return
	// }
	//
	// if d.GetChildNodePtr() == nil {
	//	 return
	// }
	//
	// _ = d.GetChildNodePtr().PrintScore()
}
  1. npecheck Function parameter is pointer, and its child-node method is directly referenced in chain without validation
func np10Example(d *DataInfo) {
	age := d.GetChildNodeNonPtr().GetGrandsonNodePtr().Age // want "potential nil pointer reference" "potential nil pointer reference"
	fmt.Println(age)
	// d is a potential nil pointer
	// d.GetChildNodeNonPtr() is not a pointer, just a struct variable
	// d.GetChildNodeNonPtr().GetGrandsonNodePtr() is a potential nil pointer

	// It can be written as follows, and will be more safe.
	// if d == nil {
	// 	 return
	// }
	//
	// if d.GetChildNodeNonPtr().GetGrandsonNodePtr() != nil {
	//	 age := d.GetChildNodeNonPtr().GetGrandsonNodePtr().Age
	//	 fmt.Println(age)
	// }

	// Or:
	// if d != nil && d.GetChildNodeNonPtr().GetGrandsonNodePtr() != nil {
	//	 age := d.GetChildNodeNonPtr().GetGrandsonNodePtr().Age
	//	 fmt.Println(age)
	// }
}
  1. npecheck A pointer variable obtained by calling an external function, and its child-node method is directly referenced in chain without validation
func np11Example() {
	d := GetDataInfo()
	age := d.GetChildNodeNonPtr().GetGrandsonNodePtr().Age // want "potential nil pointer reference" "potential nil pointer reference"
	fmt.Println(age)

	// d is a potential nil pointer
	// d.GetChildNodeNonPtr() is not a pointer, just a struct variable
	// d.GetChildNodeNonPtr().GetGrandsonNodePtr() is a potential nil pointer

	// It can be written as follows, and will be more safe.
	// if d == nil {
	// 	 return
	// }
	//
	// if d.GetChildNodeNonPtr().GetGrandsonNodePtr() != nil {
	//	 age := d.GetChildNodeNonPtr().GetGrandsonNodePtr().Age
	//	 fmt.Println(age)
	// }

	// Or:
	// if d != nil && d.GetChildNodeNonPtr().GetGrandsonNodePtr() != nil {
	//	 age := d.GetChildNodeNonPtr().GetGrandsonNodePtr().Age
	//	 fmt.Println(age)
	// }
}
  1. npecheck Skip the parent node pointer check and directly verify the child node.
func np12Example(d *DataInfo) {
	if d.A != nil { // want "potential nil pointer reference"
		fmt.Println(d.A.B) // want "potential nil pointer reference" "potential nil pointer reference"
	}

	// d is a potential nil pointer. It should valid d first.
	// It can be written as follows, and will be more safe.

	// if d != nil && d.A != nil {
	//	 fmt.Println(d.A.B)
	// }

	// Or:
	// if d == nil {
	//	 return
	// }
	//
	// if d.A != nil {
	//	 fmt.Println(d.A.B)
	//}

	// Or:
	// if d == nil {
	//	 return
	// }
	// if d.A == nil {
	//	 return
	// }
	// fmt.Println(d.A.B)
}

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages