Golang Wire Tutorial

jeonghyeon·2022년 1월 12일
0

golang wire

목록 보기
1/2

Wire?

Wire는 DI(dependency injection)툴로 code generation을 통해 컴포넌트를 연결합니다.

각 컴포넌트의 의존성은 함수의 인자로 표현됩니다.

설치

go install github.com/google/wire/cmd/wire@latest

Tutorial 따라하기

DI 없이 작성된 코드

Event → Greeter → Message 에 각각 의존하는 기본 코드입니다.

package main

import "fmt"

type Message string

type Greeter struct { 
	Message Message 
}

type Event struct {
	Greeter Greeter
}

func NewMessage() Message {
	return Message("Hi there!")
}

func NewGreeter(m Message) Greeter {
	return Greeter{Message: m}
}

func (g Greeter) Greet() Message {
	return g.Message
}

func NewEvent(g Greeter) Event {
	return Event{Greeter: g}
}

func (e Event) Start() {
	msg := e.Greeter.Greet()
	fmt.Println(msg)
}

func main() {
	message := NewMessage()
	greeter := NewGreeter(message)
	event := NewEvent(greeter)

	event.Start()
}

DI를 적용한 코드

package main

import "fmt"

/*
		...
*/

func main() {
	event := InitializeEvent()

	event.Start()
}
//+build wireinject

// wire.go 파일
package main

import (
	"github.com/google/wire"
)

// wire.go
func InitializeEvent() Event {
	wire.Build(NewEvent, NewGreeter, NewMessage)
	return Event{}
}

Message, Greeter, Event를 각각 만들지 않고 wire.Build에 initialilzer를 전달합니다.

wire에서는 initializer를 providers(특정 타입을 반환하는 함수)라고 합니다.

InitializeEvent의 반화 값으로는 컴파일러 오류를 막기 위해 Event 타입을 반환합니다.

wire.go 파일이 새성된 위치로 이동해 wire명령을 실행하면 wire_gen.go파일이 생성됩니다.

// Code generated by Wire. DO NOT EDIT.

//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package main

// Injectors from wire.go:

func InitializeEvent() Event {
        message := NewMessage()
        greeter := NewGreeter(message)
        event := NewEvent(greeter)
        return event
}

다음 명령으로 빌드 후 실행해보면 처음 파일과 동일한 실행 결과가 나타납니다.

go build -o test .
./test
Hi there!

Making Changes with Wire

package main

import (
        "os"
        "fmt"
        "time"
        "errors"
)

type Message string

type Greeter struct {
        Message Message
        Grumpy bool
}

type Event struct {
        Greeter Greeter
}

func NewMessage() Message {
        return Message("Hi there!")
}

func NewGreeter(m Message) Greeter {
        var grumpy bool
        if time.Now().Unix()%2 == 0 {
                grumpy = true
        }
        return Greeter{Message: m, Grumpy: grumpy}
}

func (g Greeter) Greet() Message {
        if g.Grumpy {
                return Message("Go away!")
        }
        return g.Message
}

func NewEvent(g Greeter) (Event, error) {
        if g.Grumpy {
                return Event{}, errors.New("could not create event: event greeter is grumpy")
        }
        return Event{Greeter: g}, nil
}

func (e Event) Start() {
        msg := e.Greeter.Greet()
        fmt.Println(msg)
}

func main() {
        event, err := InitializeEvent()
        if err != nil {
                fmt.Printf("failed to create event: %s\n", err)
                os.Exit(2)
        }

        event.Start()
}

NewEvent provider에서 error를 반환할 수 있도록 수정했습니다.

wire.go 파일에서 InitializeEvent()함수의 반환 값도 NewEvent()에 맞춰 변경합니다.

//go:build wireinject
// +build wireinject

package main

import (
        "github.com/google/wire"
)

func InitializeEvent() (Event, error){
        wire.Build(NewEvent, NewGreeter, NewMessage)
        return Event{}, nil
}

다시 wire_gen.go 파일을 생성하면 NewEvent()에서 반환하는 error를 처리하고 있는 것을 볼 수 있습니다.

// Code generated by Wire. DO NOT EDIT.

//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package main

// Injectors from wire.go:

func InitializeEvent() (Event, error) {
        message := NewMessage()
        greeter := NewGreeter(message)
        event, err := NewEvent(greeter)
        if err != nil {
                return Event{}, err
        }
        return event, nil
}

Changing the Injector Signature

func InitializeEvent(phrase strting) (Event, error) {
	wire.Build(NewEvent, NewGreeter, NewMessage)
	return Event{}, nil
}

이제 InitializeEvent()에 환영 문구를 인자로 전달할 수 있습니다.

func NewMessage(phrase string) Message {
	return Message(phrase)
}
// Code generated by Wire. DO NOT EDIT.

//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package main

// Injectors from wire.go:

func InitializeEvent(phrase string) (Event, error) {
        message := NewMessage(phrase)
        greeter := NewGreeter(message)
        event, err := NewEvent(greeter)
        if err != nil {
                return Event{}, err
        }
        return event, nil
}

0개의 댓글