示例

下面每一段都是 examples/github 里的文件,按仓库内容原文贴出。

examples/github/api/api.go

手写的 interface。它嵌入 genapi.Interface,并声明了 Contributors 和 CreateIssue。

examples/github/api/api.goSource源文件
package api

import (
	"context"

	"github.com/lexcao/genapi"
)

//go:generate go run ../../../cmd/genapi/main.go -file $GOFILE

// @BaseURL("https://api.github.com")
// @Header("Accept", "application/vnd.github.v3+json")
type GitHub interface {
	genapi.Interface

	// @GET("/repos/{owner}/{repo}/contributors")
	Contributors(ctx context.Context, owner string, repo string) ([]Contributor, error)

	// @POST("/repos/{owner}/{repo}/issues")
	CreateIssue(ctx context.Context, issue Issue, owner string, repo string) error
}

type Contributor struct {
	Login         string `json:"login"`
	Contributions int    `json:"contributions"`
}

type Issue struct {
	Title     string   `json:"title"`
	Body      string   `json:"body"`
	Assignees []string `json:"assignees"`
	Milestone int      `json:"milestone"`
	Labels    []string `json:"labels"`
}

examples/github/api/api.gen.go

生成器写出的文件。第一行写明这是生成的,不要手改。

examples/github/api/api.gen.goSource源文件
// CODE GENERATED BY genapi. DO NOT EDIT.
package api

import (
	"context"
	"github.com/lexcao/genapi"
	"net/http"
)

type implGitHub struct {
	client genapi.HttpClient
}

// SetHttpClient implments genapi.Interface
func (i *implGitHub) SetHttpClient(client genapi.HttpClient) {
	i.client = client
}

func (i *implGitHub) Contributors(ctx context.Context, owner string, repo string) ([]Contributor, error) {
	resp, err := i.client.Do(&genapi.Request{
		Method: "GET",
		Path:   "/repos/{owner}/{repo}/contributors",
		PathParams: map[string]string{
			"owner": owner,
			"repo":  repo,
		},
		Context: ctx,
	})
	return genapi.HandleResponse[[]Contributor](resp, err)
}

func (i *implGitHub) CreateIssue(ctx context.Context, issue Issue, owner string, repo string) error {
	resp, err := i.client.Do(&genapi.Request{
		Method: "POST",
		Path:   "/repos/{owner}/{repo}/issues",
		PathParams: map[string]string{
			"owner": owner,
			"repo":  repo,
		},
		Context: ctx,
		Body:    issue,
	})
	return genapi.HandleResponse0(resp, err)
}

func init() {
	genapi.Register[GitHub, *implGitHub](
		genapi.Config{
			BaseURL: "https://api.github.com",
			Header: http.Header{
				"Accept": []string{
					"application/vnd.github.v3+json",
				},
			},
		},
	)
}

examples/github/main.go

调用 genapi.New 和 Contributors 的程序。出错时从 *genapi.Error 读取响应体。

examples/github/main.goSource源文件
package main

import (
	"context"
	"errors"
	"fmt"
	"io"

	"github.com/lexcao/genapi"
	"github.com/lexcao/genapi/examples/github/api"
)

func main() {
	client := genapi.New[api.GitHub]()

	contributors, err := client.Contributors(context.Background(), "lexcao", "genapi")
	if err != nil {
		fmt.Printf("failed to get contributors: %v\n", err)
		var apiErr *genapi.Error
		if errors.As(err, &apiErr) {
			body, _ := io.ReadAll(apiErr.Response.Body)
			fmt.Printf("API error: %v\n", string(body))
		}
		return
	}

	for _, contributor := range contributors {
		fmt.Printf("%s (%d)\n", contributor.Login, contributor.Contributions)
	}
}

examples/ 之外

可选 Resty 适配器的示例在 pkg/clients/resty/example/main.go,不在 examples/ 目录里。 pkg/clients/resty/example/main.go