Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

exported field in unexported struct

Tags:

struct

go

Example:

type myType struct {
    foo    []float64
    Name   string
}

myType is not exported, but Name field in it is exported.

Does this make sense to do this? Is that considered a bad practice?

I have something like this, and it compiles fine. I can access the Name field if I create an exported array of myType:

var MyArray []myType = {... some initialization }

fmt.Println(MyArray[0].Name) // Name is visible and it compiles
like image 255
leopoodle Avatar asked Oct 17 '17 07:10

leopoodle


Video Answer


1 Answers

It is perfectly valid to have unexported structs with exported fields. If the type is declared in another package, the declaration var MyArray []myType would be a compile-time error.

While it is perfectly valid to have an exported function with an unexported return type, it is usually annoying to use. The golint tool also gives a warning for such cases:

exported func XXX returns unexported type pname.tname, which can be annoying to use

In such cases it's better to also export the type; or if you can't or don't want to do that, then create an exported interface and the exported function should have a return type of that interface, and so the implementing type may remain unexported. Since interfaces cannot have fields (only methods), this may require you to add some getter methods.

Also note that in some cases this is exactly what you want: unexported struct with exported fields. Sometimes you want to pass the struct value to some other package for processing, and in order for the other package to be able to access the fields, they must be exported (but not the struct type itself).

Good example is when you want to generate a JSON response. You may create an unexported struct, and to be able to use the encoding/json package, the fields must be exported. For example:

type response struct {
    Success bool   `json:"success"`
    Message string `json:"message"`
    Data    string `json:"data"`
}

func myHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json;charset=UTF-8")
    resp := &response{
        Success: true,
        Message: "OK",
        Data:    "some data",
    }
    if err := json.NewEncoder(w).Encode(resp); err != nil {
        // Handle err
    }
}
like image 85
icza Avatar answered Oct 25 '22 14:10

icza