DEV Community

Ball Weera Kasetsin
Ball Weera Kasetsin

Posted on

1 1

Refactor Go Package by Using gomvpkg

#go

Gopher

https://blog.golang.org/gopher

Go provides a lot of tools to help Go developers. They help Go developers to be productive when they are trying to solve their problems with Go. You can see the list of tools at https://godoc.org/golang.org/x/tools


I've seen many developers that moved from other technology stacks (Java Spring, Ruby on Rails, etc.) use the previous project structure from those to Go project. Layer-based is the one example (controller, model, service, common, util, repository, etc.). In Go, mostly, we will not do that. When we design a Go package (structure), we think about what it provides, not what it contains. And how we use them. You can read my blog about Go Package (Structure) Design

As you may know, it is painful when you are trying to refactor legacy Go package. Especially, packages like common, util, base. Because it has been used around the project (other packages use them by importing). If you refactor those packages, you need to put a lot of effort to change the import path in every derived package.

Actually, there is a Go tool for this situation. It is gomvpkg.https://godoc.org/golang.org/x/tools/cmd/gomvpkg

I'm going to show you how to refactor legacy Go package by using gomvpkg. We have the package common/consumer.

package event
import "github.com/ballweera/play-gomvpkg/common/consumer"
func Process() {
consumer.Consume()
}
view raw event.go hosted with ❤ by GitHub
package main
import (
"github.com/ballweera/play-gomvpkg/common/consumer"
"github.com/ballweera/play-gomvpkg/event"
)
func main() {
consumer.Consume()
event.Process()
}
view raw main.go hosted with ❤ by GitHub

You can see that github.com/ballweera/play-gomvpkg/common/consumer has been used in only two places (event.go and main.go). But in a large program, it may be used more than 10 or 20 times. So it is a bit difficult to refactor and take time to refactor them.

By using gomvpkg, we can execute only one command to change from github.com/ballweera/play-gomvpkg/common/consumer to github.com/ballweera/play-gomvpkg/kafka

gomvpkg -from github.com/ballweera/play-gomvpkg/common/consumer -to github.com/ballweera/play-gomvpkg/kafka
view raw gomvpkg hosted with ❤ by GitHub

After executing gomvpkg, you would see the result like this

package event
import "github.com/ballweera/play-gomvpkg/kafka"
func Process() {
kafka.Consume()
}
view raw event.go hosted with ❤ by GitHub
package main
import (
"github.com/ballweera/play-gomvpkg/event"
"github.com/ballweera/play-gomvpkg/kafka"
)
func main() {
kafka.Consume()
event.Process()
}
view raw main.go hosted with ❤ by GitHub

Now, in event.go and main.go, the import path is changed to github.com/ballweera/play-gomvpkg/kafka.

One thing you need to know about gomvpkg. It could not be run outside GOPATH. So you need to move your Go project to GOPATH before using it. And if you use Go Module (go.mod), you also need to set GO111MODULE=auto.

I already created the repo to play the gomvpkg https://github.com/ballweera/play-gomvpkg.

Have fun!!

Image of Datadog

Master Mobile Monitoring for iOS Apps

Monitor your app’s health with real-time insights into crash-free rates, start times, and more. Optimize performance and prevent user churn by addressing critical issues like app hangs, and ANRs. Learn how to keep your iOS app running smoothly across all devices by downloading this eBook.

Get The eBook

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay