Generate accessors for structs with pointer fields #543

Open
wants to merge 2 commits into
from

Projects

None yet

3 participants

@gmlewis
Member
gmlewis commented Feb 3, 2017

Fixes #45.

Change-Id: Ib2b6cc5d713e2eb833ee3c7fcfbd804bfe8fa313

@shurcooL
Collaborator
shurcooL commented Feb 3, 2017

Thanks for working on this @gmlewis. Before I look at the details of the implementation, I'd like to discuss this change at a higher level. I have some concerns about the general direction and I'd like to see where others stand. Let's maybe do that in #45 itself, and leave this PR to discuss implementation details. I'll ping you there.

@shurcooL
Collaborator

As I posted in #45 (comment), my potential concerns are resolved and I have no objections to doing this. I'll leave some review comments on the implementation now.

@shurcooL
Collaborator
shurcooL commented Feb 14, 2017 edited

First, some high level questions/thoughts for @gmlewis, looking only at the final API after this PR.

  1. The "Get" prefix is slightly unfortunate, given Go style suggests to avoid "Get" prefix from getters (source: https://golang.org/doc/effective_go.html#Getters).

    However, I understand this is unavoidable because otherwise field name and method name would have same name, right? Also, this is the same solution that protobuf uses and is therefore consistent, right?

    Just mentioning this, I don't think we need to change it. Also, one way to justify the "Get" prefix is that it's not a simple getter, it has logic for returning zero value if the pointer is nil.

  2. The documentation text for methods seems to prioritize mentioning the nil case:

    // GetMessage returns the zero value if nil, otherwise the actual value.
    

    Is that the way to go? I'd expect the nil case to be the less common path, and the actual value being the primary path. So would it better to reflect that in the docs by swapping the order? Something that mentions the actual value first, nil case second, like:

    // GetMessage returns the Message field if it's non-nil, zero value otherwise.
    

    (That phrasing doesn't sound better, but perhaps it can be tweaked. Just want to get your thoughts.)

  3. This is actually somewhat implementation-related. Currently, this PR generates 56 "-accessors.go" files. Given they're all generated and most users/developers won't need to look at/modify the detailed contents of those files, maybe it'd be better to consolidate them all in a single generated .go file?

    That way, when working on this package, there are less files get in your way that you don't want to modify. Also smaller risk of accidentally modifying a generated file, because there are fewer of them.

    Compare the file list before and after this PR.

    Please don't change this yet, I just want to get your thoughts on this first. We should consider the trade-offs of both approaches.

@gmlewis
Member
gmlewis commented Feb 14, 2017

@shurcooL - addressing your questions/thoughts:

  1. Yes, "Get" is consistent with the proto2 implementation.
  2. I went through a few iterations on the comment, and am fine with changing it. Both versions seem clear to me, but am happy to emphasize as suggested.
  3. Sure, I'm happy to consolidate to a single file... I was originally thinking it would be nice to easily jump to just the accessors for a particular file, but with all the editor tooling we have these days, maybe a single file is better after all.
@willnorris
Member
github/github.go
+// go-github authors should run the following commands before
+// sending PRs to GitHub:
+//
+// cd github.com/go-github
@shurcooL
shurcooL Feb 15, 2017 Collaborator

cd github.com/go-github? That doesn't sound right.

github/github.go
+// cd github.com/go-github
+// go generate ./...
+// go test ./...
+// go vet ./...
@shurcooL
shurcooL Feb 15, 2017 edited Collaborator

How about deleting the cd step and making these commands use absolute import path patterns rather than relative? E.g.:

go generate github.com/google/go-github/...

Then the same command can be run from any directory, and it'll do the right thing.

github/github-accessors.go
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// github-accessors.go generated by gen-accessors; DO NOT EDIT
@shurcooL
shurcooL Feb 15, 2017 Collaborator

The standardized generated file disclaimer header format not official yet, but it seems to be on its way to become so. Let's start following that standard.

// Code generated by gen-accessors; DO NOT EDIT.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
@shurcooL
shurcooL Feb 15, 2017 edited Collaborator

I think you should consider adding:

// +build ignore

It won't affect go generate functionality since the .go file is being go run directly.

But it'll prevent a poorly named and unneccessary tools binary from being placed in users $GOPATH/bin directory if they install all packages in go-github repository. Thoughts?

In fact, is there an advantage in placing this file in a separate directory, instead of just inside github folder, the same folder as the github package where it's being used?

@gmlewis
gmlewis Feb 19, 2017 Member

We don't want gen-accessors.go in the same github directory because it is not in the github package and may cause confusion. It seems to be common practice to move command-line tools to a subdirectory called tools or cmd or tools/cmd or cmd/tools... I'm flexible with the directory name, but I think we want to keep it in a separate directory.

cmd/tools/gen-accessors.go
+// {{.Filename}} generated by gen-accessors; DO NOT EDIT
+
+package {{.Package}}
+{{if .Imports}}
@shurcooL
shurcooL Feb 15, 2017 Collaborator

It's possible to simplify the template in this instance by using {{with .Imports}} instead of {{if .Imports}}.

+ if err := sourceTmpl.Execute(&buf, t); err != nil {
+ return err
+ }
+ clean, err := format.Source(buf.Bytes())
@shurcooL
shurcooL Feb 15, 2017 Collaborator

Does gofmting the output from template have an effect, i.e., does it change something, or is it being done "just in case"?

If it changes something, what is it? Asking because I'm curious.

@gmlewis
gmlewis Feb 15, 2017 Member

Yes, it correctly converts spaces to tabs. I worked on this project:
https://godoc.org/google.golang.org/api
and calling gofmt is standard operating procedure when generating Go code.

@ojongerius ojongerius referenced this pull request in zorkian/go-datadog-api Feb 16, 2017
Merged

WIP GH-56 Refactor to use pointers for all fields. #83

gmlewis added some commits Feb 3, 2017
@gmlewis gmlewis Generate accessors for structs with pointer fields
Fixes #45.

Change-Id: Ib2b6cc5d713e2eb833ee3c7fcfbd804bfe8fa313
6c6979c
@gmlewis gmlewis Addressed review comments
Change-Id: I72138458e1a82159c113e5762e0d8113a4bcc722
88853c7
@gmlewis
Member
gmlewis commented Feb 19, 2017

I believe I've addressed the review comments from @shurcooL.
PTAL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment