简体   繁体   中英

Should I create pointers on struct field or on struct? Go

I'm wondering what's the best practice on pointers. Should I define them on the struct or on its fields. I though it makes sense to define a pointer to the struct itself but here is an example I find intriguing. If all the fields are pointers why shouldn't I use a pointer to the entire struct instead to get an address for each field?

type Tag struct {
    Tag     *string       `json:"tag,omitempty"`
    SHA     *string       `json:"sha,omitempty"`
    URL     *string       `json:"url,omitempty"`
    Message *string       `json:"message,omitempty"`
    Tagger  *CommitAuthor `json:"tagger,omitempty"`
    Object  *GitObject    `json:"object,omitempty"`
}

A sample of the struct content below

{
  "tag": "v0.0.1",
  "sha": "940bd336248efae0f9ee5bc7b2d5c985887b16ac",
  "url": "https://api.github.com/repos/octocat/Hello-World/git/tags/940bd336248efae0f9ee5bc7b2d5c985887b16ac",
  "message": "initial version\n",
  "tagger": {
    "name": "Scott Chacon",
    "email": "schacon@gmail.com",
    "date": "2011-06-17T14:53:35-07:00"
  },
  "object": {
    "type": "commit",
    "sha": "c3d0be41ecbe669545ee3e94d31ed9a4bc91ee3c",
    "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/c3d0be41ecbe669545ee3e94d31ed9a4bc91ee3c"
  }
}

It is more efficient to have non-pointer fields, but in this case they have an odd reason to use pointers, discussed at the blog post "Go, REST APIs, and Pointers" .

It looks like the struct you're talking about is defined here, in the go-github library . It makes every field a pointer so that it's trivial to pass nil for any subset of fields (just don't specify them). That way when you're constructing, say, a PATCH call to update something via the GitHub API, you can specify whether Description is just not relevant to your request (you're not updating the description) or whether you intend to set Description to "" . The key thing is that "" and nil have different meanings in PATCH calls to their API.

If you have a similar desire to distinguish a zero string/struct/etc. from "not applicable to this object", you can also use pointers. If you don't need that, though, it's better not to make every field a pointer, because that will tend to make your memory usage patterns worse--little more RAM taken up, more cache misses, more stuff the GC needs to trace through, etc. An approach that doesn't add that layer of pointer indirection (but looks a tiny bit more verbose when writing code) is sql.NullString , which is just a struct with a bool and a string.

In GitHub's case, any performance impact of it isn't a huge deal--the time GitHub takes to respond to the Web request is going to dwarf any CPU-bound work their library does anyway.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM