在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):shurcooL/githubv4开源软件地址(OpenSource Url):https://github.com/shurcooL/githubv4开源编程语言(OpenSource Language):Go 100.0%开源软件介绍(OpenSource Introduction):githubv4Package If you're looking for a client library for GitHub REST API v3, the recommended package is Focus
Installation
go get -u github.com/shurcooL/githubv4 UsageAuthenticationGitHub GraphQL API v4 requires authentication. The import "golang.org/x/oauth2"
func main() {
src := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")},
)
httpClient := oauth2.NewClient(context.Background(), src)
client := githubv4.NewClient(httpClient)
// Use client...
} If you are using GitHub Enterprise, use client := githubv4.NewEnterpriseClient(os.Getenv("GITHUB_ENDPOINT"), httpClient)
// Use client... Simple QueryTo make a query, you need to define a Go type that corresponds to the GitHub GraphQL schema, and contains the fields you're interested in querying. You can look up the GitHub GraphQL schema at https://docs.github.com/en/graphql/reference/queries. For example, to make the following GraphQL query: query {
viewer {
login
createdAt
}
} You can define this variable: var query struct {
Viewer struct {
Login githubv4.String
CreatedAt githubv4.DateTime
}
} Then call err := client.Query(context.Background(), &query, nil)
if err != nil {
// Handle error.
}
fmt.Println(" Login:", query.Viewer.Login)
fmt.Println("CreatedAt:", query.Viewer.CreatedAt)
// Output:
// Login: gopher
// CreatedAt: 2017-05-26 21:17:14 +0000 UTC Scalar TypesFor each scalar in the GitHub GraphQL schema listed at https://docs.github.com/en/graphql/reference/scalars, there is a corresponding Go type in package You can use these types when writing queries: var query struct {
Viewer struct {
Login githubv4.String
CreatedAt githubv4.DateTime
IsBountyHunter githubv4.Boolean
BioHTML githubv4.HTML
WebsiteURL githubv4.URI
}
}
// Call client.Query() and use results in query... However, depending on how you're planning to use the results of your query, it's often more convenient to use other Go types. The That means you can simplify the earlier query by using predeclared Go types: // import "time"
var query struct {
Viewer struct {
Login string // E.g., "gopher".
CreatedAt time.Time // E.g., time.Date(2017, 5, 26, 21, 17, 14, 0, time.UTC).
IsBountyHunter bool // E.g., true.
BioHTML string // E.g., `I am learning <a href="https://graphql.org">GraphQL</a>!`.
WebsiteURL string // E.g., "https://golang.org".
}
}
// Call client.Query() and use results in query... The // import "html/template"
type MyBoolean bool
var query struct {
Viewer struct {
Login string // E.g., "gopher".
CreatedAt string // E.g., "2017-05-26T21:17:14Z".
IsBountyHunter MyBoolean // E.g., MyBoolean(true).
BioHTML template.HTML // E.g., template.HTML(`I am learning <a href="https://graphql.org">GraphQL</a>!`).
WebsiteURL template.URL // E.g., template.URL("https://golang.org").
}
}
// Call client.Query() and use results in query... Arguments and VariablesOften, you'll want to specify arguments on some fields. You can use the For example, to make the following GraphQL query: {
repository(owner: "octocat", name: "Hello-World") {
description
}
} You can define this variable: var q struct {
Repository struct {
Description string
} `graphql:"repository(owner: \"octocat\", name: \"Hello-World\")"`
} Then call err := client.Query(context.Background(), &q, nil)
if err != nil {
// Handle error.
}
fmt.Println(q.Repository.Description)
// Output:
// My first repository on GitHub! However, that'll only work if the arguments are constant and known in advance. Otherwise, you will need to make use of variables. Replace the constants in the struct field tag with variable names: // fetchRepoDescription fetches description of repo with owner and name.
func fetchRepoDescription(ctx context.Context, owner, name string) (string, error) {
var q struct {
Repository struct {
Description string
} `graphql:"repository(owner: $owner, name: $name)"`
} When sending variables to GraphQL, you need to use exact types that match GraphQL scalar types, otherwise the GraphQL server will return an error. So, define a variables := map[string]interface{}{
"owner": githubv4.String(owner),
"name": githubv4.String(name),
} Finally, call err := client.Query(ctx, &q, variables)
return q.Repository.Description, err
} Inline FragmentsSome GraphQL queries contain inline fragments. You can use the For example, to make the following GraphQL query: {
repositoryOwner(login: "github") {
login
... on Organization {
description
}
... on User {
bio
}
}
} You can define this variable: var q struct {
RepositoryOwner struct {
Login string
Organization struct {
Description string
} `graphql:"... on Organization"`
User struct {
Bio string
} `graphql:"... on User"`
} `graphql:"repositoryOwner(login: \"github\")"`
} Alternatively, you can define the struct types corresponding to inline fragments, and use them as embedded fields in your query: type (
OrganizationFragment struct {
Description string
}
UserFragment struct {
Bio string
}
)
var q struct {
RepositoryOwner struct {
Login string
OrganizationFragment `graphql:"... on Organization"`
UserFragment `graphql:"... on User"`
} `graphql:"repositoryOwner(login: \"github\")"`
} Then call err := client.Query(context.Background(), &q, nil)
if err != nil {
// Handle error.
}
fmt.Println(q.RepositoryOwner.Login)
fmt.Println(q.RepositoryOwner.Description)
fmt.Println(q.RepositoryOwner.Bio)
// Output:
// github
// How people build software.
// PaginationImagine you wanted to get a complete list of comments in an issue, and not just the first 10 or so. To do that, you'll need to perform multiple queries and use pagination information. For example: type comment struct {
Body string
Author struct {
Login string
AvatarURL string `graphql:"avatarUrl(size: 72)"`
}
ViewerCanReact bool
}
var q struct {
Repository struct {
Issue struct {
Comments struct {
Nodes []comment
PageInfo struct {
EndCursor githubv4.String
HasNextPage bool
}
} `graphql:"comments(first: 100, after: $commentsCursor)"` // 100 per page.
} `graphql:"issue(number: $issueNumber)"`
} `graphql:"repository(owner: $repositoryOwner, name: $repositoryName)"`
}
variables := map[string]interface{}{
"repositoryOwner": githubv4.String(owner),
"repositoryName": githubv4.String(name),
"issueNumber": githubv4.Int(issue),
"commentsCursor": (*githubv4.String)(nil), // Null after argument to get first page.
}
// Get comments from all pages.
var allComments []comment
for {
err := client.Query(ctx, &q, variables)
if err != nil {
return err
}
allComments = append(allComments, q.Repository.Issue.Comments.Nodes...)
if !q.Repository.Issue.Comments.PageInfo.HasNextPage {
break
}
variables["commentsCursor"] = githubv4.NewString(q.Repository.Issue.Comments.PageInfo.EndCursor)
} There is more than one way to perform pagination. Consider additional fields inside MutationsMutations often require information that you can only find out by performing a query first. Let's suppose you've already done that. For example, to make the following GraphQL mutation: mutation($input: AddReactionInput!) {
addReaction(input: $input) {
reaction {
content
}
subject {
id
}
}
}
variables {
"input": {
"subjectId": "MDU6SXNzdWUyMTc5NTQ0OTc=",
"content": "HOORAY"
}
} You can define: var m struct {
AddReaction struct {
Reaction struct {
Content githubv4.ReactionContent
}
Subject struct {
ID githubv4.ID
}
} `graphql:"addReaction(input: $input)"`
}
input := githubv4.AddReactionInput{
SubjectID: targetIssue.ID, // ID of the target issue from a previous query.
Content: githubv4.ReactionContentHooray,
} Then call err := client.Mutate(context.Background(), &m, input, nil)
if err != nil {
// Handle error.
}
fmt.Printf("Added a %v reaction to subject with ID %#v!\n", m.AddReaction.Reaction.Content, m.AddReaction.Subject.ID)
// Output:
// Added a HOORAY reaction to subject with ID "MDU6SXNzdWUyMTc5NTQ0OTc="! Directories
License |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论