Go Crazy: A Fun Projects-based Approach to Golang Programming 1st Edition Nicolas Modrzyk download
Go Crazy: A Fun Projects-based Approach to Golang Programming 1st Edition Nicolas Modrzyk download
https://ebookmeta.com/product/go-crazy-a-fun-projects-based-
approach-to-golang-programming-1st-edition-nicolas-modrzyk/
https://ebookmeta.com/product/pro-go-the-complete-guide-to-
programming-reliable-and-efficient-software-using-golang-1st-
edition-adam-freeman/
https://ebookmeta.com/product/learning-go-an-idiomatic-approach-
to-real-world-go-programming-2nd-edition-jon-bodner/
https://ebookmeta.com/product/software-development-with-go-cloud-
native-programming-using-golang-with-linux-and-docker-nanik-
tolaram/
https://ebookmeta.com/product/a-touch-of-pride-vices-virtues-1st-
edition-krysta-fox/
Winning the Board A Guide to Success on NCO Boards E4
E5 E6 Soldier of the Month 16th Edition Gregory S.
Skinner
https://ebookmeta.com/product/winning-the-board-a-guide-to-
success-on-nco-boards-e4-e5-e6-soldier-of-the-month-16th-edition-
gregory-s-skinner/
https://ebookmeta.com/product/perilous-arrangements-a-flower-
shop-cozy-mystery-the-flower-shop-mystery-series-book-6-1st-
edition-annie-adams/
https://ebookmeta.com/product/foundations-of-optical-system-
analysis-and-design-1st-edition-lakshminarayan-hazra/
https://ebookmeta.com/product/captive-on-the-high-seas-love-
inspired-historical-christina-rich/
https://ebookmeta.com/product/windows-security-internals-with-
powershell-early-access-james-forshaw/
Sous Vide Cookbook Williams Sonoma Test Kitchen
https://ebookmeta.com/product/sous-vide-cookbook-williams-sonoma-
test-kitchen/
Go Crazy
A Fun Projects-based Approach
to Golang Programming
Nicolas Modrzyk
Contributed by David Li, Jun Akiyama and
Tony Broyez
Go Crazy: A Fun Projects-based Approach to Golang Programming
Nicolas Modrzyk
tokyo-to suginami-ku, Japan
Introduction�����������������������������������������������������������������������������������������������������������xvii
v
Table of Contents
vi
Table of Contents
vii
Table of Contents
viii
Table of Contents
Index��������������������������������������������������������������������������������������������������������������������� 359
ix
About the Author
Nicolas Modrzyk acts as the CTO of Karabiner Software, a
successful consulting company located in the never-asleep
Tokyo, with its mix of ancestral culture and eco-friendly,
future-oriented dynamic.
He is an active contributor to the open-source
community in various domains, including imaging, ML, AI,
and cloud computing. As an engineer and a leader, Nico
has been involved in designing large-scale applications,
managing mammoth-sized clusters of servers, sometimes
using handwritten software, and enabling world-class
leaders by pushing international boundaries.
Nico ardently focuses on making life simple. (And we all
know how difficult that is!)
He loves pushing people to challenge themselves and go beyond their comfort zones.
To learn other cultures and explore different world views, he has been living around
the planet in various countries, including France, Ireland, Japan, China, Korea, India,
and the United States. You can talk to Nico in French, English, and Japanese, and you can
get along with him in Spanish and Chinese.
Nico is the author of a few programming books, available on Amazon. He recently
picked up the saxophone to honor his grandfather and his uncle, in the hope to match
their skill with a brass instrument.
He will be ready for a jazzy jam session whenever you are.
xi
About the Technical Reviewer
David Li is the executive director of Shenzhen Open
Innovation Lab, which facilitates the collaboration between
global smart hardware entrepreneurs and the Shenzhen
Open Innovation ecosystem. Before SZOIL, he co-founded
XinCheJian, the first hackerspace in China to promote
the hacker/maker culture and open-source hardware. He
co-founded Hacked Matter, a research hub on the maker
movement and open innovation. He also co-founded Maker
Collier, an AI company focusing on motion and sports
recognition and analysis.
xiii
Acknowledgments
All the involved authors—Jun, Tony, David—as well as the technical reviewers, Mathieu
and David, of this book have gone the extra mile to match the deadlines and bring the
writing and code samples to a top-class level.
My two strong daughters, Mei and Manon—you always keep me focused and in line
with my goals.
Psy Mom, French Chef Dad, Little Bro, Artful Sis—I thank you for your love every day,
your support, and all the ideas we share together.
My partner at Karabiner, Chris Mitchell—we’ve been working together for ten years,
and I think we both made tremendous efforts to make the planet a better place. Also,
the whole Karabiner people, at work now or busy making babies, we make a pretty
impressive world team.
Abe-san—who did not participate directly in the making of this book, but we wrote
our first computer book together, and without a first one, and without his trust, I would
not be here to even talk about it.
Kanaru-san—without your Iranian lifestyle and your life changing vision, I would
probably be a monk.
Marshall—without your world encompassing vision, I could have been focusing on
the bigger picture.
Ogier—without your summertime raclette and life-long friendship, I would probably
have been 5 kilos skinnier.
Jumpei—without your strong focus on music, I could not have played in all those
beautiful Tokyo live stages. And welcome Rei-chan!
Gryffin and Melissa—I could not have survived this without your hard work
and trust.
And of course, Marcel le chat—my open-source project on imaging would not be the
same without your feline cuteness.
xv
Introduction
On a sunny drive on the busy roads of Tokyo, over the rainbow bridge and facing the
ocean, my daughter Mei and I are having one of these philosophical talks.
Among the slur of questions she had ready for me, like “what is work for?,” she was
telling me about her need to have someone monitor her and give her deadlines. While
at the time of this writing, she’s barely 20 and hasn’t started a full-blown professional
career yet, she is right in the sense that the need to have deadlines and a purpose is at the
core of many adults’ professional lives.
At the very root of a school system, you are being told what to complete, and by what
date. You do not have input regarding the what or the when. A regular office worker is
told to finish their tasks by the fifth of next month, for example, and some authors are
told to finish three chapters by the end of the month.
That de facto need of what to do and by when happens very early in your career.
I am in favor of looking at things from a different angle. You should set your own
deadlines, and you should be in control of those deadlines. You have a goal, you set
milestones to achieve that goal, and you work on walking that path to that goal.
You want to live your own life and reach your own goals, not someone else’s.
Although I am critical about many of his actions, Elon Musk does not have someone
telling him when to land a rocket on Mars. He has his own schedule. He owns his
schedule. He owns his life.
This is a book on how to own your life again. More precisely, how Go, the
programming language, can help you get your time back, manage it along your dreams,
and own your life again.
I discovered the Go programming language a few years back. At that time, to be
honest, I was more of a Clojure-loving propaganda evangelist. Anything I developed or
touched had to be in Clojure. A deployment script, a web app, a dynamically generated
API around some custom datasets, image and video processing, or applying the latest
Computer Vision algorithm in real time—it did not matter. It greatly helped my career. I
would go even further and say, my life.
xvii
Introduction
How can a programming language help make your life better, you might ask? A
programming language is at first a language, and as such its first goal is to communicate.
We tend to think that a programming language’s only goal is to deal with a computer, but
we deal with computers because we want to communicate something to other people.
Take a simple email, for example. You use a computer to write an email because it
takes less time to reach its recipient, but the goal of an email is still to convey a message
to another person.
Now let’s say you have a lot to communicate, or you want to communicate something
to many people, but with that simple personal touch that makes all the difference
between your email being ignored and it being read and acted upon.
You don’t have much time. In life in general, but also to realize a task. You can use a
computer to help you with that task and save time.
Nowadays one of the best programming languages to put in your toolbox is GoLang.
It includes all the important concepts of Clojure, and that I love in a programming
language, but it’s also in the top ten of the TIOBE index, meaning you can find a few
more programmers to help you do your job.
Don’t get me wrong, there are other great languages, but there are many things that
GoLang gets absolutely right:
–– It is simple
–– It is concise
–– It’s easy to reuse bits of code from one project to the other
–– It is cloud-ready
xviii
Introduction
This programming book will take you on the path to Ikigai, finding joy in life through
purpose.
xix
CHAPTER 1
Go to the Basics
The goal of this first chapter is to write a ChatGPT client in Go. You’ve probably heard
about ChatGPT. It is an AI-trained chatbot that generates text according to questions
you ask it.
To get to this point, you will run basic Go programs and get used to the language.
Then you will put things together into a ChatGPT client.
But you first need to set up your code editor.
1
© Nicolas Modrzyk 2023
N. Modrzyk, Go Crazy, https://doi.org/10.1007/978-1-4842-9666-0_1
Chapter 1 Go to the Basics
First Steps
As with any new skill, you need a basic setup where you feel comfortable practicing
and trying new things. While Go, the language, makes writing code easier, GoLand, the
editor, makes writing Go easier.
To kick-start this chapter, you learn how to use GoLand as your editor for writing Go.
2
Chapter 1 Go to the Basics
Once you have created a new project, a blank project window will be available.
The left side of the window shows your project file, and the right side shows your
code editor (which, at this stage, is empty). See Figure 1-2.
3
Chapter 1 Go to the Basics
You can right-click in the Project Files tab and create a new Go file, as shown in
Figure 1-3.
4
Chapter 1 Go to the Basics
5
Chapter 1 Go to the Basics
1. The green arrow allows you to simply click and run your code. You
also get an arrow when you have test cases. You will learn about
that in a few pages.
2. Try copying and pasting this line into the main() function:
5. You can click most of your code and navigate to the corresponding
section in the Go packages, whether it’s part of the core language
or an external library.
6
Chapter 1 Go to the Basics
Your first code snippet will do just that—display the Go version of your current
installation. See Listing 1-1.
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Printf("Go version: %s\n", runtime.Version())
}
7
Chapter 1 Go to the Basics
5. The one and only function is called main, and that is the entry
function. It is called first when running the program.
8
Chapter 1 Go to the Basics
You can also ask the execution to not suspend when reaching a specific breakpoint
(see Figure 1-8) and just log the variables that are accessible to the debugger.
9
Chapter 1 Go to the Basics
While writing code, I recommend using GoLand debugging mode most, if not all, the
time. That way, you avoid unnecessary logging statements in the program and can focus
on the business logic that really matters, not the logging mess.
You now know the basics to run/debug a program, so next you review basic Go
concepts that you will use to write a ChatGPT client.
10
Chapter 1 Go to the Basics
11
Chapter 1 Go to the Basics
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
for true {
fmt.Print("What is your name ? > ")
reader := bufio.NewReader(os.Stdin)
12
Chapter 1 Go to the Basics
The for loop uses true as the condition of the loop continuity check. I put it there to
make it obvious what the condition is, but it can be removed altogether.
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, _ := os.OpenFile("hello.txt", os.O_RDONLY, 0666)
defer file.Close()
reader := bufio.NewReader(file)
for {
line, err := reader.ReadString('\n')
fmt.Printf("> %s", line)
if err != nil {
return
}
}
}
13
Chapter 1 Go to the Basics
package main
import (
"fmt"
)
func main() {
h := Message{Hello: "world"}
fmt.Printf("%s\n", h)
}
; { world}
The output could be slightly more useful if you could print out the fields as well as
the actual data. There are two ways to do this.
One way is to use +v in the formatting part of the fmt.Printf formatting and print
call. All the fields in the struct will then be printed, as shown in Listing 1-5.
14
Chapter 1 Go to the Basics
package main
import (
"fmt"
)
func main() {
h := Message{Hello: "world"}
fmt.Printf("%+v\n", h)
}
{Hello:world}
Another way, and one that is often used to send and receive custom-defined structs
via HTTP, is to marshal the object to the universal JSON format.
This is a very custom way to print or parse data. Golang makes it very easy to achieve
this, using the encoding/json package included in the core libraries.
The use of this core library is shown in Listing 1-6.
import (
"encoding/json"
"fmt"
)
15
Chapter 1 Go to the Basics
func main() {
h := Message{Hello: "world"}
AsString, _ := json.Marshal(h)
fmt.Printf("%s\n", AsString)
}
This code will print a more detailed version of the custom data:
{"Hello":"world"}
Note the quotes around “Message” and “world”, which were not present when using
simple standard formatting to string.
Important Note If a field name in your custom struct does not start with a
capital letter, the field will not be marshalled and thus not printed. This happens
both when using the standard toString marshalling and the other marshalling
techniques. Starting a field with a lowercase character indicates that the field is
not to be exported.
While the struct contains the ignored field, that field will not be exported when using
JSON marshaling because it starts with a lowercase letter.
In Golang, you can also specify metadata on fields of structs using what is called a
tag line.
This tag line is used for different things. One common use is to format the output
of the fields in JSON. That tag line can also be used to format data for persistence to
database, for example.
You write a tag line by adding a specific directive after the field’s type, using
backquotes, as shown in Listing 1-7.
16
Chapter 1 Go to the Basics
package main
import (
"encoding/json"
"fmt"
)
func main() {
h := Hello{Message: "world"}
b, _ := json.Marshal(h)
fmt.Printf("%s\n", string(b))
}
{"hellooo":"world"}
package main
import (
"encoding/json"
"io/ioutil"
)
17
Chapter 1 Go to the Basics
func main() {
data := Employee{
FirstName: "Nicolas",
LastName: "Modrzyk",
Email: "hellonico at gmail.com",
Age: 43,
MonthlySalary: []Salary{{Basic: 15000.00}, {Basic: 16000.00},
{Basic: 17000.00}},
}
{
"FirstName": "Nicolas",
"LastName": "Modrzyk",
"Email": "hellonico at gmail.com",
"Age": 43,
"MonthlySalary": [
{
"Basic": 15000
},
18
Chapter 1 Go to the Basics
{
"Basic": 16000
},
{
"Basic": 17000
}
]
}
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
19
Chapter 1 Go to the Basics
func main() {
jsonFile, _ := os.Open("my_salary.json")
byteValue, _ := ioutil.ReadAll(jsonFile)
var employee Employee
_ = json.Unmarshal(byteValue, &employee)
fmt.Printf("%+v", employee)
}
Remember that you can pretty-print the content by reverting to JSON, as shown in
Listing 1-11.
func main() {
jsonFile, _ := os.Open("my_salary.json")
byteValue, _ := ioutil.ReadAll(jsonFile)
var employee Employee
_ = json.Unmarshal(byteValue, &employee)
//fmt.Printf("%+v", employee)
json, _ := json.MarshalIndent(employee, "", " ")
fmt.Println(string(json))
}
20
Chapter 1 Go to the Basics
package main
import (
"fmt"
"os"
)
func main() {
programName, questions := os.Args[0], os.Args[1:]
fmt.Printf("Starting:%s", programName)
if len(questions) == 0 {
fmt.Printf("Usage:%s <question1> <question2> ...", programName)
} else {
for i, question := range questions {
fmt.Printf("Question [%d] > %s\n", i, question)
}
}
}
For more advanced parsing, you use flag (https://pkg.go.dev/flag), but I won’t
review this now.
21
Chapter 1 Go to the Basics
Figure 1-11. The place to go when looking for libraries: the pkg.go.dev website
Then enter dotenv, the library you need for this example (see Figure 1-12).
22
Chapter 1 Go to the Basics
The code that uses the godotenv library, the first one in the list, is shown in
Listing 1-13.
package main
import (
"fmt"
"github.com/joho/godotenv"
"os"
)
func main() {
godotenv.Load()
s3Bucket := os.Getenv("S3_BUCKET")
secretKey := os.Getenv("SECRET_KEY")
S3_BUCKET: s3prod
SECRET_KEY: secretprod
When you write, copy, or open Listing 1-13 in GoLand, the library will not be found
because it has not been downloaded yet (see Figure 1-13).
23
Chapter 1 Go to the Basics
In the editor, the import statement at the top of the file will be highlighted in red, and
you can right-click or press Option+Enter to get GoLand to retrieve the library for you.
The go.mod file will then be filled in with the necessary information, as shown in
Listing 1-14.
module listing-14
go 1.18
Note that you can of course add the library manually in the go.mod file.
Once the library is correctly downloaded and added to the project, running Listing 1-13
will give the following output:
This code is loading fake keys to access S3 buckets, but some very similar code will
be used for loading the API key for ChatGPT.
24
Chapter 1 Go to the Basics
package main
import (
"fmt"
"time"
)
func printNumbers() {
for i := 0; i < 10; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Printf("%d", i)
}
}
func main() {
go printNumbers()
printNumbers()
}
25
Chapter 1 Go to the Basics
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
go printNumbers(c)
Listing 1-16 uses a Go channel to convey data between the main function and the Go
routine.
A Go channel is a mechanism for communication between Go routines. It is a typed
conduit that allows Go routines to send and receive values of a specified type, safely and
concurrently. Channels provide a way for Go routines to communicate and synchronize
their execution, without the need for locks or other synchronization mechanisms.
A channel is created using the make function and can be passed as an argument to
Go routines, allowing multiple routines to communicate. Channels can be unbuffered or
buffered. Unbuffered channels allow a single value to be sent at a time, whereas buffered
channels allow multiple values to be stored in a buffer. The same <- operator sends and
receives values to and from a channel.
26
Chapter 1 Go to the Basics
Channels are an important tool for concurrent programming in Go, and they provide
a way to structure and coordinate the behavior of Go routines, making it easier to build
concurrent systems that are correct and efficient.
The for loop in the main thread reads values passed via the channel until the Go
routines close the channel and there is nothing more to read.
Note that you can tweak the values as they are being read out of the channel, using a
switch block (see Listing 1-17).
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
go printNumbers(c)
27
Chapter 1 Go to the Basics
default:
fmt.Println("Received other value")
}
}
}
Note that you can also apply computations on values before the cases. For example,
Listing 1-18 determines whether the value from the channel is even or odd.
func main() {
c := make(chan int)
go printNumbers(c)
28
Chapter 1 Go to the Basics
package main
import (
"fmt"
"os"
"time"
)
func main() {
ch := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch <- fmt.Sprintf("hello")
}()
go func() {
time.Sleep(2 * time.Second)
ch <- fmt.Sprintf("world")
}()
for {
select {
case v := <-ch:
fmt.Printf("%s\n", v)
case <-time.After(3 * time.Second):
fmt.Println("waited 3 seconds")
os.Exit(0)
}
}
Helloworld
waited 3 seconds
29
Chapter 1 Go to the Basics
Try to change one of the two Go routines’ sleep time to a value greater than 3
seconds. That Go routine will not have time to send its message to the channel before the
time.After case kicks in, and the select blocks will then go into the os.Exit branch,
which will call to exit the program.
Using Go Contexts
Go routines are typically used in conjunction with another Go feature: contexts. A
context in Go is an interface used to carry deadlines, cancellations, and other request-
scoped values across API boundaries and between processes. They helps manage the
flow of data, metadata, and control signals between independent parts of a distributed
application, ensuring that they all share a common understanding of the request they
are serving.
Contexts are used to store and propagate request-scoped values, such as
authentication credentials, and to propagate information about the lifetime of a request
to the parts of the system that need to know about it.
Contexts are created using the context.WithCancel, context.WithDeadline, and
context.WithTimeout functions, and they are typically passed as the first argument to
various function calls, including for example HTTP handlers.
Listing 1-20 shows the use of contexts.
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
go func() {
time.Sleep(2 * time.Second)
fmt.Println("Task finished")
}()
30
Random documents with unrelated
content Scribd suggests to you:
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back