Unable check nil pointer


(zheng ji) #1

Hello, everyone!
I just got into programming.Now i can not check nil pointer and can not figure out why, plz help to take a look, thanks.

		//List instance tags
		for _, tag := range inst.Tags {
			v := "Null"
			if tag.Value == nil {
				fmt.Printf("%s is nil", *tag.Key)
				continue
			}
			if reflect.ValueOf(&tag.Value).IsNil() {
				fmt.Println("Nil")
			}

			if tag.Value != nil {
				v = *tag.Value
			}
			k := *tag.Key
			fmt.Println(k, v)
			switch k {
			case "Name":
				data.Name = &v
			case "Environment":
				data.Env = &v
			case "Service":
				data.Service = &v
			case "Role":
				data.Role = &v
			}

Output:
Name dev-jixxx
Environment DEV
IPv4 私有IP 172.31.23.xx
Dev
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x13778b4]

goroutine 1 [running]:
main.writeInstances()
/Users/jizheng/outsidegopath/aws_inventory/list_inventory.go:113 +0x6a4
main.main()
/Users/jizheng/outsidegopath/aws_inventory/list_inventory.go:169 +0x27
exit status 2


( Kvaz1r) #2

Hello. Can you provide minimal code for reproducing the behaviour?
Also on which exactly line of the code above you getting panic?

From documentation to IsNil/0:

IsNil reports whether its argument v is nil. The argument must be a chan, func, interface, map, pointer, or slice value; if it is not, IsNil panics. Note that IsNil is not always equivalent to a regular comparison with nil in Go. For example, if v was created by calling ValueOf with an uninitialized interface variable i, i==nil will be true but v.IsNil will panic as v will be the zero Value.


(zheng ji) #3

Hi! Here is the complete code below. Forgive me that i don’t know how to compose type. :joy:
Some "*tag.Value"s are nil.

package main

import (
	"database/sql"
	"fmt"
	"log"
	"reflect"

	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	_ "github.com/go-sql-driver/mysql" //_ stands for only importing init func in the package
)

var region = "us-west-2"

type ec2Resources struct {
	Name         *string
	Env          *string
	Service      *string
	Role         *string
	InstanceType *string
}

func writeInstances() {
	//Create a new session
	sess := session.Must(session.NewSession())
	svc := ec2.New(sess)

	//Describe all instances
	result, err := svc.DescribeInstances(nil)
	if err != nil {
		panic(err)
	}

	var data ec2Resources

	for idx, _ := range result.Reservations {
		for _, inst := range result.Reservations[idx].Instances {

			data.InstanceType = inst.InstanceType

			//List instance tags
			for _, tag := range inst.Tags {
				v := "Null"
				if tag.Value == nil {
					fmt.Printf("%s is nil", *tag.Key)
					continue
				}
				if reflect.ValueOf(&tag.Value).IsNil() {
					fmt.Println("Nil")
				}

				if tag.Value != nil {
					v = *tag.Value
				}
				k := *tag.Key
				fmt.Println(k, v)
				switch k {
				case "Name":
					data.Name = &v
				case "Environment":
					data.Env = &v
				case "Service":
					data.Service = &v
				case "Role":
					data.Role = &v
				}

				// fmt.Println(reflect.TypeOf(*tag))
				// if *tag.Key == "Name" {
				// 	//fmt.Printf("Env is %s\n", *tag.Value)
				// 	if tag.Value != nil {
				// 		data.Name = tag.Value
				// 		fmt.Println("Name")
				// 	} else {
				// 		*data.Name = "Null"
				// 	}
				// } else if *tag.Key == "Environment" {
				// 	if tag.Value != nil {
				// 		data.Env = tag.Value
				// 		fmt.Println("Env")
				// 	} else {
				// 		*data.Env = "Null"
				// 	}
				// } else if *tag.Key == "Service" {
				// 	if tag.Value != nil {
				// 		data.Service = tag.Value
				// 	} else {
				// 		panic("errrrrrror")
				// 		*data.Service = "Null"
				// 	}
				// } else if *tag.Key == "Role" {
				// 	if tag.Value != nil {
				// 		data.Role = tag.Value
				// 	} else {
				// 		*data.Role = "Null"
				// 		fmt.Println("Role")
				// 		panic("NULL")
				// 	}
				// }
			}
			//Update first, if not exist, then try to insert.
			fmt.Println(reflect.TypeOf(*data.Role))
			sql := fmt.Sprintf(
				"UPDATE ec2 SET Environment = %s, Service = %s, Role = %s, InstanceType = %s",
				*data.Env,
				*data.Service,
				*data.Role,
				*data.InstanceType,
			)
			fmt.Println("update finish")
			log.Println("sql:", sql)
			result, err := db.Exec(sql)
			if err != nil {
				log.Println("Exec failed:", err, ";SQL:", sql)
				return
			}
			//c is number of affected rows.
			c, err := result.RowsAffected()
			if err != nil {
				log.Println("Rows affected failed:", err)
				return
			}
			//If affected rows num is 0, then INSERT.
			if c == 0 {
				sql := fmt.Sprintf(
					"INSERT INTO ec2(Name, Environment, Service, Role, InstanceType) VALUES ('%s', '%s', '%s', '%s', '%s')",
					*data.Name,
					*data.Env,
					*data.Service,
					*data.Role,
					*data.InstanceType,
				)
				log.Println("Not exist, try to insert.")
				_, err := db.Exec(sql)
				if err != nil {
					log.Println("Exec Failed", err, ";SQL:", sql)
				}

			}
		}
	}
}

var db *sql.DB
var err error

func connectDatabase() {
	db, err = sql.Open("mysql", "jizheng/password@xxx/mysql")
	//log.Fatal will terminate process immediately but panic will do until defer func finish.
	if err != nil {
		log.Fatal("Database connected failed!")
	}
	fmt.Println("Database connected.")
}

func main() {
	connectDatabase()
	writeInstances()
	db.Close()
}

(zheng ji) #4

Sorry i can not manage to provide minimal code to reproduce the error, so i put entire code in here. I will sincerely appreciate it if you can give me some advice!


(Norbert Melzer) #5

This can never be nil, as tag.Value always has an address where it is stored.


(zheng ji) #6

Oh, but tag.Value can be nil, right ?


(Johan Dahl) #7

You get a panic on line 113 but what is

result, err := db.Exec(sql)

So I guess you have changed your program after you posted the listing. Which line is the panic on now?


(zheng ji) #8

Sorry, now it is 103
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x13778b4]

goroutine 1 [running]:
main.writeInstances()
/Users/jizheng/outsidegopath/aws_inventory/list_inventory.go:103 +0x6a4
main.main()
/Users/jizheng/outsidegopath/aws_inventory/list_inventory.go:159 +0x27
exit status 2


(Johan Dahl) #9

Could you put this line before line 103? It prints the value of data with types etc:

fmt.Printf("%#v\n", data)

And post here what it prints


(zheng ji) #10

Sorry man, my focus was completely wrong. At first i thought all ec2 have all the tag.Keys but not every key has a value. The panic is not because of the tag.Value but the tag.Key. Because some ec2 instances don’t have all the keys i specified, like an ec2 doesn’t have tag “Role”, so data.Role is nil. Thanks for you guys’ help!


(system) closed #11

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.