Make Go Packages with No Sweat

Joe Bologna
2 min readAug 18, 2022

--

I recently wrote a lot of Go code and decided it needed to be refactored. While exploring options, I discovered some features in VSCode that makes creating new packages much easier.

A package should have a specific purpose. It should be easy to extend and maintain. Let’s start by defining an interface and the structs it requires. This “specification first” approach helps focus your design and implementation. It also helps you write DRY code. I recommend doing a little research on DRY (Don’t Repeat Yourself) if you are a newbie to programming.

Starting with an interface gives VSCode enough information to generate a lot of boilerplate code that leverages the Go typing system properly. This helps us write DRY code.

I’m writing code to draw on an e-Ink display, so let’s create an eink package.

The EInkImage interface defines the methods required. A New() method is provided to allow doing some processing when the EInkImageInfo is initially populated.

Create the module:

go mod init eink
go mod tidy
mkdir cli

Create eInkImage.go with this content

package einktype EInkImageInfo struct {
Filename string
}
type EInkImage interface {
New(string) *EInkImageInfo
Upload()
Download()
Display()
Info()
}

Create cli/main.go with this content:

package mainimport "eink"func main() {
img := eink.EInkImage.New(&eink.EInkImageInfo{}, "text.txt")
img.Info()
}

EInkImage.New is not implemented at this point. Let’s use the VSCode “Implement EInkImageInfo” function. Just put the cursor over the New function and click on the 💡. The eInkImage.go file will be populated with all the methods defined in the interface. The default implementation is to panic, which is fine.

Modify the New method as follows:

func (*EInkImageInfo) New(Filename string) *EInkImageInfo {
fmt.Println("do some work here")
return &EInkImageInfo{Filename}
}

Modify the Info method as follows:

func (e *EInkImageInfo) Info() {
j, _ := json.Marshal(e)
fmt.Println(string(j))
}

Finally, use Info() to display the filename. Update main.go as follows:

package mainimport "eink"func main() {
img := eink.EInkImage.New(&eink.EInkImageInfo{}, "text.txt")
img.Info()
}

Let’s setup debugging for Go while we’re at it. Click on the Debugger button to put VSCode in debugger mode. Click on create a launch.json file. Select “Go”, “Launch Package”. Save the launch.json file.

Select the main.go tab, press F5.

Use ^J to open a terminal window. Select the DEBUG CONSOLE tab. The output of the debugger will be shown along with a prompt to evaluate expressions.

That’s all!

You are now free to extend interfaces and VSCode will help you create stub implementations. If you try to use an unimplemented method, you’ll get a panic indicating the method isn’t implemented.

For my next project, I intend to use the interface method with RPC, with the help of frodo. This takes leveraging Go interfaces to a whole new level.

--

--