Please read this related question: Draw a rectangle in Golang?
To sum it up: the standard Go library does not provide primitive drawing or painting capabilities.
So yes, either you have to use a 3rd party library to draw a circle (such as github.com/llgcode/draw2d), or you have to do it yourself. Don't worry, it's not hard at all.
Drawing a single circle
First pick a circle drawing algorithm which is simple and efficient. I recommend the Midpoint circle algorithm.
You will find the algorithm on the linked Wikipedia page. Note: you do not have to understand it if you want to use it.
But we do need to implement the algorithm in Go. Which is rather simple:
func drawCircle(img draw.Image, x0, y0, r int, c color.Color) {
x, y, dx, dy := r-1, 0, 1, 1
err := dx - (r * 2)
for x > y {
img.Set(x0+x, y0+y, c)
img.Set(x0+y, y0+x, c)
img.Set(x0-y, y0+x, c)
img.Set(x0-x, y0+y, c)
img.Set(x0-x, y0-y, c)
img.Set(x0-y, y0-x, c)
img.Set(x0+y, y0-x, c)
img.Set(x0+x, y0-y, c)
if err <= 0 {
y++
err += dy
dy += 2
}
if err > 0 {
x--
dx += 2
err += dx - (r * 2)
}
}
}
That's all it takes. Just pass a draw.Image
you want to draw on, and the parameters of the circle you want to draw (center point, radius and the color).
Let's see it in action. Let's create an image, draw a circle on it, and save the image to a file. This is all it takes:
img := image.NewRGBA(image.Rect(0, 0, 100, 100))
drawCircle(img, 40, 40, 30, color.RGBA{255, 0, 0, 255})
buf := &bytes.Buffer{}
if err := png.Encode(buf, img); err != nil {
panic(err)
}
if err := ioutil.WriteFile("circle.png", buf.Bytes(), 0666); err != nil {
panic(err)
}
Note: you could also encode the image directly to an os.File
and "skip" the in-memory buffer. This is just for demonstration, and to verify our implementation works.
Drawing a ring (filling space between 2 circles)
This one isn't that trivial if you want to implement it yourself, but using a 3rd party lib here could really come handy.
Although most of them don't contain ring-painting support, they do have circle drawing support, and you can set the width of the line used to draw the circle.
So, set the line width to the value that is the difference of the 2 radius of your circles. And draw a circle with a new radius that is the arithmetic center of the 2 original radius.
Here's the algorithm (this is not runnable code):
// Helper functions abstracting the library you choose:
func setColor(c color.Color) {}
func setLineWidth(width float64) {}
func drawCircle(r, x, y float64) {}
// fillRing draws a ring, where r1 and r2 are 2 concentric circles,
// the boundaries of the ring, (x, y) being the center point.
func fillRing(r1, r2, x, y float64, c color.color) {
// Set drawing color:
setColor(c)
// Set line width:
width := r2 - r1
if width < 0 {
width = -width
}
setLineWidth(width)
// And finally draw a circle which will be a ring:
r := (r2 + r1) / 2
drawCircle(r, x, y)
}