Go의 구조 정의에 따라 Functional Options Pattern 코드를 자동으로 생성하는 CLI 도구를 제작했습니다.
이 문제를 해결하기 위해 Functional Options Pattern을 구현하는 코드를 자동으로 생성하는 CLI 도구'foggo'를 제작했다.
이른바 Functional options Pattern
Go는 간단한 언어 규범에서 선택할 수 있는 파라미터를 제공하지 않았다.
옵션 매개 변수는 기본 매개 변수 또는 옵션 매개 변수라고도 하는데 파이톤은 가변 길이 매개 변수
*args
또는*kargs
를 가리킨다.일반적인 함수라면 문제없지만 구조체 초기화에 사용되는 함수와 프로그램 라이브러리를 제공할 때 생략할 수 있는 인자를 원할 때가 있습니다.
이 생략 가능한 매개변수를 구현하기 위해 Functional Options Pattern(FOP)이 사용됩니다.
FOP는 우버의 Go Style Guide와 go-patterns에도 소개됐다.
다음은 go-patterns가 제시한 FOP의 예입니다.
FOP는 옵션 매개변수에 값을 대입하는 함수를 정의하는 고급 함수와 가변 길이 매개변수로 고급 함수를 초기화하는 함수를 정의하는 옵션 구조를 정의합니다.
사용자는 매개 변수에서 초기화에 사용할 함수를 선택할 수 있는 함수로 지정합니다.
// Options
package file
type Options struct {
UID int
GID int
Flags int
Contents string
Permissions os.FileMode
}
type Option func(*Options)
func UID(userID int) Option {
return func(args *Options) {
args.UID = userID
}
}
func GID(groupID int) Option {
return func(args *Options) {
args.GID = groupID
}
}
// Contents, Permissions については省略
// Constructor
func New(filepath string, setters ...Option) error {
// Default Options
args := &Options{
UID: os.Getuid(),
GID: os.Getgid(),
Contents: "",
Permissions: 0666,
Flags: os.O_CREATE | os.O_EXCL | os.O_WRONLY,
}
for _, setter := range setters {
setter(args)
}
f, err := os.OpenFile(filepath, args.Flags, args.Permissions)
if err != nil {
return err
} else {
defer f.Close()
}
if _, err := f.WriteString(args.Contents); err != nil {
return err
}
return f.Chown(args.UID, args.GID)
}
// Usage
// emptyFile, err := file.New("/tmp/empty.txt")
// fillerFile, err := file.New("/tmp/file.txt", file.UID(1000), file.Contents("Lorem Ipsum Dolor Amet"))
또한 상기 FOP의 실현 방법에서 함수로 선택할 수 있는 매개 변수를 정의했기 때문에 모듈을 사용하여 테스트할 수 없는 문제가 존재한다.다음 기사에서도 이 문제를 해결할 FOP 모델을 제시했다.
(질문은 다음 기사를 참조하십시오.)
이 글은 선택할 수 있는 매개 변수를'선택할 수 있는 매개 변수와
apply
함수를 가진 구조'로 정의하는 방법을 소개했다.package file
type Options struct {
UID int
GID int
Flags int
Contents string
Permissions os.FileMode
}
type Option interface {
apply(*Options)
}
type UIDOption struct {
UID int
}
func (o UIDOption) apply(s *Options) {
s.UID = o.UID
}
type GIDOption struct {
GID int
}
func (o GIDOption) apply(s *Options) {
s.GID = o.GID
}
// (Contents, Permissions については省略)
func New(filepath string, setters ...Option) error {
// 重複箇所については省略
...
for _, setter := range setters {
setter.apply(args)
}
...
return f.Chown(args.UID, args.GID)
}
Function Options Pattern 설치 관련 질문
FOP는 옵션의 수량에만'대입 매개 변수의 고급 함수'와'옵션용 구조체 +
apply
함수'를 설치해야 하기 때문에 옵션이 많으면 그에 상응하는 설치도 팽창한다.또한 선택할 수 있는 매개 변수는 고급 함수나 구조체의 매개 변수를 함수 매개 변수에 대입하는 함수
apply
로 정의되어 있어 처음 보면 이해하기 어렵다.이해하기 전에 도입을 망설일 수도 있습니다.
이러한 이중화, 가져오기 전의 장애를 제거하기 위해 FOP를 자동으로 생성하는 CLI 도구를 만들었습니다.
foggo의 소개
foggo Go의 구조 정의에 따라 FOP가 자동으로 생성됩니다.
go install
다음과 같이 가져옵니다.# foggo では自動生成したコードの整形に goimports を利用するため、先にインストールしてください
$ go install golang.org/x/tools/cmd/goimports@latest
$ go install github.com/s14t284/foggo@latest
foggo는 fop과 afop 두 개의 하위 명령을 제공합니다.fop은 FOP의 소개를 통해 최초로 접촉한 모드의 코드를 자동으로 생성할 수 있다.
afop은 함수
apply
를 구현하는 FOP 코드를 자동으로 생성할 수 있습니다.여기 기사.에서 실현 함수의 FOP를 Applicable Function Optional Pattern으로 명명하여 afop이라고 약칭한다.사용법
foggo에서는 명령선을 통해 FOP를 자동으로 생성하는 것과
apply
를 통해 두 가지를 자동으로 생성하는 것을 지원한다.여기에는
go:generate
에 따라 FOP가 자동으로 생성되는 방법이 소개되어 있습니다.우선 선택할 수 있는 매개 변수의 구조를 다음과 같이 준비해야 한다.
구조를 자동으로 생성하려는 함수를 정의한 파일에 기술하십시오
go:generate
.file/options.go
package file
//go:generate foggo fop --struct Options
type Options struct {
UID int
GID int
// オプションを作成したくないパラメータには `foggo:"-"` タグを付与してください
Flags int `foggo:"-"`
Contents string
Permissions os.FileMode
}
그런 다음 go:generate foggo fop --struct {構造体名}
명령을 실행합니다.$ go generate ./...
를 실행하면 go generate
아래 코드가 자동으로 생성됩니다.file/options_gen.go
// Code generated by foggo; DO NOT EDIT.
package file
import "os"
type OptionsOption func(*Options)
func NewOptions(options ...OptionsOption) *Options {
s := &Options{}
for _, option := range options {
option(s)
}
return s
}
func WithUID(UID int) OptionsOption {
return func(args *Options) {
args.UID = UID
}
}
func WithGID(GID int) OptionsOption {
return func(args *Options) {
args.GID = GID
}
}
func WithPermissions(Permissions os.FileMode) OptionsOption {
return func(args *Options) {
args.Permissions = Permissions
}
}
그리고 필요에 따라 자동으로 생성된 초기화 함수와 옵션을 사용하십시오.goo-patterns FOP의 실시 예시를 재현하려면 옵션 초기화에 사용되는 함수를 제외하고 파일 열기/쓰기 함수를 위한 옵션을 사용해야 한다.
package file
func NewFile(filepath string, options *Options) error {
flags := os.O_CREATE | os.O_EXCL | os.O_WRONLY
f, err := os.OpenFile(filepath, flags, options.Permissions)
if err != nil {
return err
} else {
defer f.Close()
}
if _, err := f.WriteString(options.Contents); err != nil {
return err
}
return f.Chown(options.UID, options.GID)
}
// 以下のように必要に応じてオプションを絞って構造体を初期化する関数を用意すると良い
func NewFileWithContentAndPermissions(filepath, content string, permissions os.FileMode) error {
options := NewOptions(
WithUID(os.Getuid()),
WithGID(os.Getgid()),
WithContents(content),
WithPermissions(permissions),
)
return NewFile(filepath, options)
}
file/options_gen.go
명령의 집행례를 확인하십시오README.주의점
코드가 자동으로 생성되는 상황에 따라 다음과 같은 문제가 있습니다.
해결책이 있다면 의견을 얻었으면 좋겠어요.
끝맺다
FOP를 자동으로 생성하는 CLI 도구 foggo에 대한 설명입니다!
foggo를 사용하여 FOP를 실현하는 간단한 조작에서 한 사람이 해방되면 좋겠다.
개선 방안이 있다면 반드시 이슈를 홍보해 주십시오.
참고 자료
전문가들의 Go 언어.(이 책을 통해 FOP와 코드의 자동 생성을 알 수 있음)
gonstructor(자동 생성 구조기의 CLI. 이 CLI 도구로foggo의 구상을 얻었다)
Reference
이 문제에 관하여(Go의 구조 정의에 따라 Functional Options Pattern 코드를 자동으로 생성하는 CLI 도구를 제작했습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/ikechan0829/articles/foggo_generate_fop_cli텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)