Reputation: 228
I created a function that gets the last comment of a user on Pull Request. I am using "github.com/google/go-github/github" package. I would like to use it for []*github.IssueComment and []*github.PullRequestComment type. Is there a way for the type of the input parameter to be variable so I dont have to specify it in the function definition and function can be called using either of the type?
func getLastUserInteractionPR(comments_array *github.IssueComment OR *github.PullRequestComment)(*github.IssueComment OR *github.PullRequestComment) {
}
Using of generics:
func getLastUserInteractionPR(comments_array any)(any) {
}
is a emergency solution, since the whole project I am working on is written in Go 1.14 and this funcionality is available from GO 1.18
When I try to use empty interface{} as input type:
func getLastUserInteractionPRIssue(comments_array interface{})(*github.IssueComment) {
comments_array []*github.IssueComment(comments_array); err {
fmt.Println("success")
} else {
fmt.Println("failure")
}
}
Upvotes: 1
Views: 54
Reputation: 406
Do you care about the internal structure of e.g. an IssueComment
?
type IssueComment struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Body *string `json:"body,omitempty"`
User *User `json:"user,omitempty"`
Reactions *Reactions `json:"reactions,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
// AuthorAssociation is the comment author's relationship to the issue's repository.
// Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE".
AuthorAssociation *string `json:"author_association,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
IssueURL *string `json:"issue_url,omitempty"`
}
As in, do you care about extracting some specific field from that? PullRequestComment
is a larger struct (it has more fields), do you care about extracting some field from that?
Or do you just want a string representation of each? What you do very much depends on what you want to do with the passed value(s).
If you just want a string
representation of each, you could use the extreme (and, honestly, not very safe - I don't recommend this) example of having your function accept a slice of fmt.Stringer
objects:
func DoStuffWithStringifiedComments(cs []fmt.Stringer) {
// Both IssueComment and PullRequestComment provide String()
// methods and therefore implement fmt.Stringer
for _, comment := range cs {
DoSomethingWith(comment.String())
}
}
Your slice can now include objects of either type and nothing will blow up. Downside: it can also include a couple of bajillion other types, none of which you want. So you'd need to add a type assertion check:
switch t := comment.(type) {
case github.IssueComment:
// Do good stuff
case github.PullRequestComment:
// Do other good stuff
default:
// Yell and scream about the value of t
}
If there are fields you want to extract, you're going to have to combine a function taking something like []interface{}
(make it a slice of empty interfaces, not an empty interface standing in for the slice), iterate over it and do a type check on each element of the slice, and pull out whatever fields are meaningful as long as the element is of a type you expect:
func DoStuff(comments []interface{}) error {
for _, c : = range comments {
if ic, ok := c.(*github.IssueComment); ok { // Remove the deref if your slice contains values, not references
// Pull out fields and do IssueComment-specific things
ProcessIssueComment(ic)
} else if prc, ok := c.(*github.PullRequestComment); ok {
// Do PRComment-specific things
ProcessPullRequestComment(prc)
} else {
return(fmt.Errorf("I did not want something of type %s", t))
}
}
return nil
}
Also: lobby the project owner (if that isn't you) to move to a current version of go. 1.14 only came out in 2020, but that's an eternity in go releases.
Upvotes: 1