An example package

October 31, 2024

Today we have something a bit different. Just a sample package.

An example package

Here is a complete Go package that implements a concurrent prime sieve.

package main

import "fmt"

// Send the sequence 2, 3, 4, … to channel 'ch'.
func generate(ch chan<- int) {
	for i := 2; ; i++ {
		ch <- i  // Send 'i' to channel 'ch'.
	}
}

// Copy the values from channel 'src' to channel 'dst',
// removing those divisible by 'prime'.
func filter(src <-chan int, dst chan<- int, prime int) {
	for i := range src {  // Loop over values received from 'src'.
		if i%prime != 0 {
			dst <- i  // Send 'i' to channel 'dst'.
		}
	}
}

// The prime sieve: Daisy-chain filter processes together.
func sieve() {
	ch := make(chan int)  // Create a new channel.
	go generate(ch)       // Start generate() as a subprocess.
	for {
		prime := <-ch
		fmt.Print(prime, "\n")
		ch1 := make(chan int)
		go filter(ch, ch1, prime)
		ch = ch1
	}
}

func main() {
	sieve()
}

This particular package is a complete program, my virtue of being in package main, containing a main() function.

I’m not going to go through the program line by line. Instead, since this is in the section of the spec about packages, let’s just take a closer look at the main components, and how they relate to a Go package, as review.

  1. The package clause, tells us we’re in the main package, the entry point for all Go programs.
package main
  1. The import declaration(s), define which external packages we’re importing into this file.
import "fmt"
  1. Function declarations
// Send the sequence 2, 3, 4, … to channel 'ch'.
func generate(ch chan<- int) {

The final function in the example is main(), which of course is the function executed by the runtime to begin running the program.

This is a very simple package, with many possible elements ommited, such as package variables, constants, init functions, etc.


Quotes from The Go Programming Language Specification Language version go1.23 (June 13, 2024)


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Program execution

Program execution A complete program is created by linking a single, unimported package called the main package with all the packages it imports, transitively. The main package must have package name main and declare a function main that takes no arguments and returns no value. func main() { … } Program execution begins by initializing the program and then invoking the function main in package main. When that function invocation returns, the program exits.


Blank imports & import side effects

Yesterday I promised to teach you the one dirty trick they don’t want you to know about, to get around Go’s restriction on circular imports. It’s explained in this sentence, the last from the spec on the topic of imports. Import declarations … To import a package solely for its side-effects (initialization), use the blank identifier as explicit package name: import _ "lib/math" Did you catch it? It’s very subtle.


Import cycles

First off, the spec provides an example of how to reference a symbol in an imported package, using different import alias options. I’ve already provided my own examples earlier, and it’s pretty straight forward, so we’ll just breeze through this part. Import declarations … Consider a compiled a package containing the package clause package math, which exports function Sin, and installed the compiled package in the file identified by "lib/math". This table illustrates how Sin is accessed in files that import the package after the various types of import declaration.

Get daily content like this in your inbox!

Subscribe