New vs named return as pointer in go

ghz 8months ago ⋅ 90 views

My function is working file with this signature

func GetFileMetadata(f *multipart.FileHeader) *FileMetadata {
    d := new(FileMetadata)

    // ...

    if typ, err := GetFileRealType(f); err == nil {
        d.Type = typ.MIME.Value
        fileExt = "." + typ.Extension
    } else {
        d.Type = "unknown"
    }

    return d
}

With following signature it doesn't.

func GetFileMetadata(f *multipart.FileHeader) (d *FileMetadata) {

    // ...

    if typ, err := GetFileRealType(f); err == nil {
        d.Type = typ.MIME.Value
        fileExt = "." + typ.Extension
    } else {
        d.Type = "unknown"
    }

    return
}

Getting nil pointer dereference err. What is the reason?

Answers

The reason for the nil pointer dereference error in the second function signature is that the FileMetadata pointer d is not initialized before assigning values to its fields. In the first function signature, d is initialized explicitly using new(FileMetadata), which allocates memory for a new FileMetadata struct and returns a pointer to it.

However, in the second function signature, the variable d is declared with the function signature, but it is not initialized explicitly. Therefore, it has a nil value by default. When you try to access d.Type or d.Extension without initializing d first, you encounter a nil pointer dereference error.

To fix this issue, you need to initialize d before assigning values to its fields. You can do this by using the new function or by creating a new instance of FileMetadata using a composite literal. Here's how you can modify your second function to avoid the nil pointer dereference error:

func GetFileMetadata(f *multipart.FileHeader) (d *FileMetadata) {
    // Initialize d
    d = new(FileMetadata)  // or d = &FileMetadata{}

    // ...

    if typ, err := GetFileRealType(f); err == nil {
        d.Type = typ.MIME.Value
        fileExt = "." + typ.Extension
    } else {
        d.Type = "unknown"
    }

    return
}

By initializing d before using it, you ensure that it points to a valid memory address, and you can safely assign values to its fields without encountering a nil pointer dereference error.