100% found this document useful (1 vote)
8 views

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 by Nicolas Modrzyk offers a hands-on learning experience for programming in Go through various projects. The book covers essential topics such as creating APIs, game development, and blockchain trading, while also providing practical examples and code snippets. It is designed for readers looking to enhance their Golang skills in a fun and engaging way.

Uploaded by

noguemmimran
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
8 views

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 by Nicolas Modrzyk offers a hands-on learning experience for programming in Go through various projects. The book covers essential topics such as creating APIs, game development, and blockchain trading, while also providing practical examples and code snippets. It is designed for readers looking to enhance their Golang skills in a fun and engaging way.

Uploaded by

noguemmimran
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 74

Go Crazy: A Fun Projects-based Approach to

Golang Programming 1st Edition Nicolas Modrzyk


install download

https://ebookmeta.com/product/go-crazy-a-fun-projects-based-
approach-to-golang-programming-1st-edition-nicolas-modrzyk/

Download more ebook from https://ebookmeta.com


We believe these products will be a great fit for you. Click
the link to download now, or visit ebookmeta.com
to discover even more!

Pro Go: The Complete Guide to Programming Reliable and


Efficient Software Using Golang 1st Edition Adam
Freeman

https://ebookmeta.com/product/pro-go-the-complete-guide-to-
programming-reliable-and-efficient-software-using-golang-1st-
edition-adam-freeman/

Learning Go: An Idiomatic Approach to Real-world Go


Programming, 2nd Edition Jon Bodner

https://ebookmeta.com/product/learning-go-an-idiomatic-approach-
to-real-world-go-programming-2nd-edition-jon-bodner/

Software Development with Go: Cloud-Native Programming


using Golang with Linux and Docker Nanik Tolaram

https://ebookmeta.com/product/software-development-with-go-cloud-
native-programming-using-golang-with-linux-and-docker-nanik-
tolaram/

A Touch of Pride Vices Virtues 1st Edition Krysta Fox

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/

Perilous Arrangements A Flower Shop Cozy Mystery The


Flower Shop Mystery Series Book 6 1st Edition Annie
Adams

https://ebookmeta.com/product/perilous-arrangements-a-flower-
shop-cozy-mystery-the-flower-shop-mystery-series-book-6-1st-
edition-annie-adams/

Foundations of Optical System Analysis and Design 1st


Edition Lakshminarayan Hazra

https://ebookmeta.com/product/foundations-of-optical-system-
analysis-and-design-1st-edition-lakshminarayan-hazra/

Captive on the High Seas Love Inspired Historical


Christina Rich

https://ebookmeta.com/product/captive-on-the-high-seas-love-
inspired-historical-christina-rich/

Windows Security Internals with PowerShell EARLY ACCESS


James Forshaw

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

ISBN-13 (pbk): 978-1-4842-9665-3 ISBN-13 (electronic): 978-1-4842-9666-0


https://doi.org/10.1007/978-1-4842-9666-0

Copyright © 2023 by Nicolas Modrzyk


This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with
every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an
editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the
trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not
identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to
proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of publication,
neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or
omissions that may be made. The publisher makes no warranty, express or implied, with respect to the
material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Melissa Duffy
Development Editor: Jim Markham
Coordinating Editor: Gryffin Winkler
Copy Editor: Kezia Endsley
Cover image designed by Scott Webb on unsplash (https://unsplash.com/)
Distributed to the book trade worldwide by Springer Science+Business Media LLC, 1 New York Plaza, Suite
4600, New York, NY 10004. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail orders-ny@springer-sbm.
com, or visit www.springeronline.com. Apress Media, LLC is a California LLC and the sole member (owner)
is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a Delaware
corporation.
For information on translations, please e-mail booktranslations@springernature.com; for reprint,
paperback, or audio rights, please e-mail bookpermissions@springernature.com.
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and
licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales
web page at http://www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is available to
readers on GitHub. For more detailed information, please visit https://www.apress.com/gp/services/
source-code.
Paper in this product is recyclable.
I dedicate this book to planet Earth.
Table of Contents
About the Author����������������������������������������������������������������������������������������������������� xi

About the Technical Reviewer������������������������������������������������������������������������������� xiii


Acknowledgments���������������������������������������������������������������������������������������������������xv

Introduction�����������������������������������������������������������������������������������������������������������xvii

Chapter 1: Go to the Basics�������������������������������������������������������������������������������������� 1


First Steps������������������������������������������������������������������������������������������������������������������������������������� 2
Run and Debug Your First Go Program������������������������������������������������������������������������������������ 2
A Short Note on Debugging with GoLand�������������������������������������������������������������������������������� 8
Before Talking to OpenAI: Reviewing Concepts��������������������������������������������������������������������������� 10
Read from Input��������������������������������������������������������������������������������������������������������������������� 12
Reading from a File��������������������������������������������������������������������������������������������������������������� 13
Custom Data: Go Structs�������������������������������������������������������������������������������������������������������� 14
Writing and Reading Structs from Files��������������������������������������������������������������������������������� 17
Reading a Struct from a File�������������������������������������������������������������������������������������������������� 19
Slicing Program Arguments��������������������������������������������������������������������������������������������������� 20
Using a Custom Library to Load the API Key������������������������������������������������������������������������� 21
Asynchronous Code: Go Routines������������������������������������������������������������������������������������������ 25
Asynchronous Code: Go Routines and Channels������������������������������������������������������������������� 25
Using Go Contexts����������������������������������������������������������������������������������������������������������������� 30
Putting Things Together Into a ChatGPT Client���������������������������������������������������������������������������� 34
Getting an API Key����������������������������������������������������������������������������������������������������������������� 34
First Request������������������������������������������������������������������������������������������������������������������������� 36
Customize the ChatGPT Request������������������������������������������������������������������������������������������� 38

v
Table of Contents

Create a Loop Prompt������������������������������������������������������������������������������������������������������������ 41


Streaming the Response������������������������������������������������������������������������������������������������������� 42
Query and Use a Custom Model�������������������������������������������������������������������������������������������� 43
Summary������������������������������������������������������������������������������������������������������������������������������������ 45

Chapter 2: Write a Tested HTTP Image Generator API�������������������������������������������� 47


Pour Me Some Gin!��������������������������������������������������������������������������������������������������������������������� 48
Working with Queues������������������������������������������������������������������������������������������������������������������ 56
Image Generators������������������������������������������������������������������������������������������������������������������������ 67
Image Generator in a Gin������������������������������������������������������������������������������������������������������������ 71
Quick Gin Tonic and Templates��������������������������������������������������������������������������������������������������� 76
Use a Synchronized Map������������������������������������������������������������������������������������������������������������� 80
Testing the API���������������������������������������������������������������������������������������������������������������������������� 84
Simple Go and Gin Testing����������������������������������������������������������������������������������������������������� 84
Testing the Image Generator������������������������������������������������������������������������������������������������� 90
Summary������������������������������������������������������������������������������������������������������������������������������������ 92

Chapter 3: Writing the Basics for a 2D Game in Go������������������������������������������������ 93


Some Tile Set History������������������������������������������������������������������������������������������������������������������ 93
Library Setup: Raylib������������������������������������������������������������������������������������������������������������� 94
Game Setup��������������������������������������������������������������������������������������������������������������������������� 95
Quick Game Generation with ChatGPT���������������������������������������������������������������������������������� 97
The Moyashi Game�������������������������������������������������������������������������������������������������������������������� 103
The Basic Game Loop���������������������������������������������������������������������������������������������������������� 105
Loading Textures����������������������������������������������������������������������������������������������������������������� 107
Adding a Player Texture������������������������������������������������������������������������������������������������������� 110
Using Key Inputs������������������������������������������������������������������������������������������������������������������ 113
Doing the Game Music�������������������������������������������������������������������������������������������������������� 115
Game Camera���������������������������������������������������������������������������������������������������������������������� 118
Animate Sprites������������������������������������������������������������������������������������������������������������������� 121
Animation for an Idle Moyashi��������������������������������������������������������������������������������������������� 126
Loading the World Map�������������������������������������������������������������������������������������������������������� 127

vi
Table of Contents

Loading the Full World Map������������������������������������������������������������������������������������������������� 131


Full Map and Full Screen����������������������������������������������������������������������������������������������������� 137
Summary���������������������������������������������������������������������������������������������������������������������������������� 138

Chapter 4: Trend Follower for Blockchain Trading����������������������������������������������� 139


Go Crazy or Go Home���������������������������������������������������������������������������������������������������������������� 139
Why Trade in the Financial Markets?����������������������������������������������������������������������������������� 141
Why Automate Trading?������������������������������������������������������������������������������������������������������� 144
The Secret Sauce���������������������������������������������������������������������������������������������������������������� 147
The Recipe��������������������������������������������������������������������������������������������������������������������������� 150
Utensils in the Kitchen��������������������������������������������������������������������������������������������������������� 155
Cooking�������������������������������������������������������������������������������������������������������������������������������� 160
Performance Evaluation������������������������������������������������������������������������������������������������������ 175
A Taste Before Serving the Meal����������������������������������������������������������������������������������������� 187
Dinner Is Served������������������������������������������������������������������������������������������������������������������ 193
Dessert!������������������������������������������������������������������������������������������������������������������������������� 197
Appendix������������������������������������������������������������������������������������������������������������������������������ 204

Chapter 5: Writing a Kubernetes Operator to Run EVM-Compatible


Blockchains����������������������������������������������������������������������������������������� 213
Setting Up Kubernetes on Your Machine����������������������������������������������������������������������������������� 214
Resources Overview����������������������������������������������������������������������������������������������������������������� 216
Let’s Run a Pod������������������������������������������������������������������������������������������������������������������������� 218
Demystifying Kubernetes Operators����������������������������������������������������������������������������������������� 219
Custom Resource Definition������������������������������������������������������������������������������������������������ 220
Controller����������������������������������������������������������������������������������������������������������������������������� 222
Bootstrapping the Project with Operator-SDK��������������������������������������������������������������������������� 222
Creating an API�������������������������������������������������������������������������������������������������������������������������� 223
Generating the Manifests���������������������������������������������������������������������������������������������������������� 225
Configuring the Makefile����������������������������������������������������������������������������������������������������������� 225
Implementing the Operator Reconciliation Logic���������������������������������������������������������������������� 227
Using the Kubernetes Go SDK��������������������������������������������������������������������������������������������������� 237

vii
Table of Contents

Interacting with the JSON-RPC API������������������������������������������������������������������������������������������� 246


Using Port-Forward������������������������������������������������������������������������������������������������������������� 247
Parameterizing Resources and Ports���������������������������������������������������������������������������������������� 248
Implementing the Update Logic������������������������������������������������������������������������������������������������ 250
Implementing Health Checks���������������������������������������������������������������������������������������������������� 258
Creating a Minimal Go HTTP Server������������������������������������������������������������������������������������ 259
Performing a net_peerCount Health Check������������������������������������������������������������������������� 262
Configuring the Readiness Probe���������������������������������������������������������������������������������������� 266
Summary���������������������������������������������������������������������������������������������������������������������������������� 268

Chapter 6: Go Beyond : Connecting to C for a Performance Boost����������������������� 271


C is for Change�������������������������������������������������������������������������������������������������������������������������� 272
Calling C������������������������������������������������������������������������������������������������������������������������������ 272
Calling C Code Located in a C File��������������������������������������������������������������������������������������� 273
C Code Calling Go Code������������������������������������������������������������������������������������������������������� 274
Passing Parameters������������������������������������������������������������������������������������������������������������ 275
Using a Header File������������������������������������������������������������������������������������������������������������� 277
Using a C Struct from Go����������������������������������������������������������������������������������������������������� 278
Matisse, ImageMagick, and Sepia�������������������������������������������������������������������������������������������� 284
ImageMagick on OSX���������������������������������������������������������������������������������������������������������� 285
ImageMagick on Linux�������������������������������������������������������������������������������������������������������� 288
ImageMagick on Raspberry Pi��������������������������������������������������������������������������������������������� 288
GPU Coding on OSX������������������������������������������������������������������������������������������������������������������� 289
Basics: Adding Values from Two Arrays������������������������������������������������������������������������������� 290
Back to the Plot������������������������������������������������������������������������������������������������������������������� 294
Generic GPU Processing Go Code���������������������������������������������������������������������������������������� 297
Opens ETHUSD Hourlies Quotes: Moving Average��������������������������������������������������������������� 299
Slightly Better Moving Average on the GPU������������������������������������������������������������������������� 300
Normalized Set�������������������������������������������������������������������������������������������������������������������� 302
Pearson Coefficient Moving Factor�������������������������������������������������������������������������������������� 304
Sepia Gopher����������������������������������������������������������������������������������������������������������������������� 307

viii
Table of Contents

Extreme Calling OpenCV/C++ from Go������������������������������������������������������������������������������������� 309


Summary���������������������������������������������������������������������������������������������������������������������������������� 315

Chapter 7: Alef from Plan 9���������������������������������������������������������������������������������� 317


Plan 9 from Bell Labs���������������������������������������������������������������������������������������������������������������� 319
The Network Is the Computer��������������������������������������������������������������������������������������������������� 321
The Alef Language�������������������������������������������������������������������������������������������������������������������� 323
Hello Tuple!�������������������������������������������������������������������������������������������������������������������������� 324
Channels and Processes����������������������������������������������������������������������������������������������������� 324
Proc and Task���������������������������������������������������������������������������������������������������������������������� 326
Have Fun with Plan 9���������������������������������������������������������������������������������������������������������������� 330

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

–– The code is short

–– Concurrency is not an afterthought

–– It can be compiled and run on a large variety of operating systems


and architectures

–– It’s easy to reuse bits of code from one project to the other

–– Errors are simple to handle

–– It is cloud-ready

–– It is very fast (this is probably my favorite)

xviii
Introduction

Go, as a programming language, has a clear and strong purpose: Implement


architecture based on microservices in the most convenient way possible.

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.

Run and Debug Your First Go Program


Running your first Go program using JetBrains GoLand should take approximately ten
minutes or less.
In the context of this book, the goal is to go deep into the language as quickly as
possible and become proficient in Go in a matter of hours. Within that context, it’s best
if you use JetBrains’s Go editor called GoLand. Of course, you can use any editor you
choose, but you will find it easier to follow along if you use GoLand.
You can download GoLand for individual use from the following URL:
www.jetbrains.com/go/download/
You will have 30 days of use for free, which should be enough to finish reading and
applying the lessons in this book—and to get you excited for more coding.
GoLand handles all the core Go language installers, paths, and dependencies
for you.
Once you start the editor, click New Project. You’ll see the screen in Figure 1-1.

2
Chapter 1 Go to the Basics

Figure 1-1. Creating a new project in GoLand

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

Figure 1-2. New Project window

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

Figure 1-3. Creating a new Go file

Give your new file a name (see Figure 1-4).

Figure 1-4. The new Go file

5
Chapter 1 Go to the Basics

A potential layout for your project looks like Figure 1-5.

Figure 1-5. Simple project layout

A few things to note about this GoLand window layout:

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:

fmt.Printf("Go version: %s\n", runtime.Version())

3. GoLand will auto-complete the code and do the necessary


namespace imports for you (see Figure 1-6).

4. The list of functions in the current file is shown in the


Structure tab.

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

Figure 1-6. Displaying the current Go version in a simple Go program

Your first code snippet will do just that—display the Go version of your current
installation. See Listing 1-1.

Listing 1-1. Displaying the Go Version

package main

import (
   "fmt"
   "runtime"
)

func main() {
   fmt.Printf("Go version: %s\n", runtime.Version())
}

A few explanations in this first code listing:

1. To be executable, the package name should be main.


2. You cannot have two package definitions in the same folder (even
in different files).

7
Chapter 1 Go to the Basics

3. fmt is the namespace that imports formatting functions, such as


Printf (print to screen) and Sprintf (format without printing).

4. runtime is the namespace containing functions that retrieve


information about the Go runtime, such as version, CPU, memory,
and tracing.

5. The one and only function is called main, and that is the entry
function. It is called first when running the program.

6. Once the main function exits, the program exits too.

A Short Note on Debugging with GoLand


Debugging is the process of finding and fixing errors or bugs in software or computer
systems. The goal of debugging is to identify the root cause of an issue and then apply a
solution to fix it. Debugging can be done manually, using tools like print statements and
logging, or with the help of specialized software development tools, like debuggers and
integrated development environments.
GoLand makes debugging a program a breeze. Let’s say you want to see the value of
the version while the program is running, before printing it.
In GoLand, you can click in the gutter right next the line number (as in Figure 1-7).
If you then start the execution in debug mode by clicking the debugging button, the
execution will stop at the requested place (the breakpoint).

8
Chapter 1 Go to the Basics

Figure 1-7. Execution stops at the breakpoint in debugging mode

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

Figure 1-8. Breakpoint settings while debugging

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.

Before Talking to OpenAI: Reviewing Concepts


To get a good grasp on using Go in a useful situation, you are going to write a program
straight from this first chapter. The goal: write a Go program that will ask simple
questions to ChatGPT and display its AI-looking answers.
Since this is the first chapter, I quickly review the underlying simple Go concepts
needed to write the Go code that will talk to ChatGPT.
Get the setup ready again (see Figures 1-9 and 1-10) so you can start coding.

10
Chapter 1 Go to the Basics

Figure 1-9. New project again

11
Chapter 1 Go to the Basics

Figure 1-10. New file in the new project

Read from Input


You need to read user input from a prompt for the ChatGPT program, so here is a sample
of what is to come. Listing 1-2 uses the bufio package to create a NewReader object.

Listing 1-2. Reading from Standard Input


package main

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

      line, err := reader.ReadString('\n')


      if err != nil {
         log.Fatal(err)
      }
      fmt.Printf("hello %s\n", line)
   }
}

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.

Reading from a File


Note that this is almost like reading from a file. In Listing 1-3, you open a file named
hello.txt in read mode and output all its contents, line by line.

Listing 1-3. Reading from a File

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

Custom Data: Go Structs


GoLang (the Go programming language) uses data structures, conveniently named
structs, to handle custom data objects. Basically, where you would use generic maps in
other languages, Go helps you enforce type checks when handling custom data. This
includes reading data from HTTP forms, database persistence, files, or even sockets.
Listing 1-4 defines a Message struct, with one string field named Hello, and simply
prints the struct object itself as a string using fmt.Printf.

Listing 1-4. Defining and Printing Custom Data with Structs

package main

import (
   "fmt"
)

type Message struct {


   Hello string
}

func main() {
   h := Message{Hello: "world"}
   fmt.Printf("%s\n", h)
}

Running this program produces this simple output:

; {  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

Listing 1-5. Printing a Struct with %+v

package main

import (
   "fmt"
)

type Message struct {


   Hello string
}

func main() {
   h := Message{Hello: "world"}
   fmt.Printf("%+v\n", h)
}

This code prints:

{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.

Listing 1-6. Marshalling a Struct to JSON Using Encoding/JSON


package main

import (
   "encoding/json"
   "fmt"
)

type Message struct {


   Hello string
}

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.

Consider a struct like this:

type Message struct {


   Hello   string
   ignored string
}

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

Listing 1-7. Struct with Marshalling and a Tag Line

package main

import (
   "encoding/json"
   "fmt"
)

type Hello struct {


   Message string `json:"hellooo"`
}

func main() {
   h := Hello{Message: "world"}
   b, _ := json.Marshal(h)
   fmt.Printf("%s\n", string(b))
}

This time the output of the code is as follows:

{"hellooo":"world"}

Writing and Reading Structs from Files


You have seen how to marshal a struct to JSON, and the next listing shows you how to
expand on this and write the contents of a struct and an embedded struct to a file.
Note that the code would be quite similar when marshalling via HTTP or sockets, as
shown in Listing 1-8.

Listing 1-8. Marshalling a Struct to File via JSON

package main

import (
   "encoding/json"
   "io/ioutil"
)

17
Chapter 1 Go to the Basics

type Salary struct {


   Basic float64
}

type Employee struct {


   FirstName, LastName, Email string
   Age                        int
   MonthlySalary              []Salary
}

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}},
   }

   file, _ := json.MarshalIndent(data, "", " ")


   _ = ioutil.WriteFile("my_salary.json", file, 0644)
}

The resulting output file is shown in Listing 1-9.

Listing 1-9. File Containing a Struct as JSON

{
"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
  }
]
}

Reading a Struct from a File


Now that the struct has been exported to a file, let’s see how the opposite operation—
reading the same struct from the file—works. To achieve that and to make it easier to
read batches of data from the file, you use the io/ioutil package again, as shown in
Listing 1-10.

Listing 1-10. Reading a Struct from a File Containing JSON

package main

import (
   "encoding/json"
   "fmt"
   "io/ioutil"
   "os"
)

type Salary struct {


   Basic float64
}

type Employee struct {


   FirstName, LastName, Email string
   Age                        int
   MonthlySalary              []Salary
}

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)
}

Running this code will produce the following output:

{FirstName:Nicolas LastName:Modrzyk Email:hellonico at gmail.com Age:43


MonthlySalary:[{Basic:15000} {Basic:16000} {Basic:17000}]}

Remember that you can pretty-print the content by reverting to JSON, as shown in
Listing 1-11.

Listing 1-11. JSON Again

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))
}

Slicing Program Arguments


You will also use that piece of code in the ChatGPT code. Listing 1-12 shows how to
retrieve questions from the arguments passed to the program.
The first element called os.Args is the program name, and the rest of the program
arguments. Listing 1-12 shows how you “slice” the arguments into a string array named
questions.

20
Chapter 1 Go to the Basics

Listing 1-12. Parsing of a Program Argument

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.

Using a Custom Library to Load the API Key


To connect and use ChatGPT from the code, as with other services nowadays, the user
needs to provide an API key. The API key is private and if used by somebody else can
lead to leakage, so the key itself is usually left outside the program and loaded from a
separate file at runtime.
While you can do that by loading that key using custom structs, in this case, you use
a non-standard library so the API key to access ChatGPT will later be loaded from a text
file using the dotenv library, a port of the Ruby library of the same name.
To find a library for Go, you usually head to https://pkg.go.dev/, which has a nice
web interface to search for Go packages, as shown in Figure 1-11.

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).

Figure 1-12. Looking for the dotenv library

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.

Listing 1-13. Loading Environment Variables Using the godotenv Library

package main

import (
   "fmt"
   "github.com/joho/godotenv"
   "os"
)

func main() {
   godotenv.Load()

   s3Bucket := os.Getenv("S3_BUCKET")
   secretKey := os.Getenv("SECRET_KEY")

   fmt.Printf("S3: %s and secret: %s", s3Bucket, secretKey)


}

godotenv.Load() loads environment variables from different places. This example


uses an .env file, with a potential .env file like this:

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

Figure 1-13. Looking for the dotenv library (again)

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.

Listing 1-14. Contents of the go.mod File

module listing-14

go 1.18

require github.com/joho/godotenv v1.5.1

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:

S3: s3prod and secret: secretprod

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

Asynchronous Code: Go Routines


While the programs you’ll write usually do only one thing very nicely, they may need to
achieve this one thing by running small “pieces of work” in the background. This is done
by writing asynchronous code. One of the easiest ways to run asynchronous code in Go
is to use Go routines.
Go routines are lightweight threads, processing units, that run concurrently with the
main function.
In Listing 1-15, you start the execution of the printNumbers function in the
background, using the go keyword. In parallel, you execute the same printNumbers
function on the main thread. This starts the function’s execution in a concurrent context.

Listing 1-15. Go Routines

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()
}

Asynchronous Code: Go Routines and Channels


Go routines usually communicate via another powerful concept: Go channels. Channels
allow different Go routines to communicate easily and efficiently.
Listing 1-16 shows how to send data into the channel and how to read from it.

25
Chapter 1 Go to the Basics

Listing 1-16. Using Go Routines

package main

import (
   "fmt"
   "time"
)

func printNumbers(c chan int) {


   for i := 0; i < 10; i++ {
      c <- i
      time.Sleep(100 * time.Millisecond)
   }
   close(c)
}

func main() {
   c := make(chan int)
   go printNumbers(c)

   for num := range c {


      fmt.Println(num)
   }
}

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).

Listing 1-17. For/Switch to Retrieve Values from the Go Channel

package main

import (
   "fmt"
   "time"
)

func printNumbers(c chan int) {


   for i := 0; i < 10; i++ {
      c <- i
      time.Sleep(100 * time.Millisecond)
   }
   close(c)
}

func main() {
   c := make(chan int)
   go printNumbers(c)

   for value := range c {


      switch value {
      case 0:
         fmt.Println("Received 0")
      case 1:
         fmt.Println("Received 1")

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.

Listing 1-18. Channel and Values: Even or Odd

func main() {
   c := make(chan int)
   go printNumbers(c)

   for value := range c {


      switch value % 2 {
      case 0:
         fmt.Printf("Value: %d is even\n", value)
      case 1:
         fmt.Printf("Value: %d is odd\n", value)
      default:
         fmt.Println("Received a weird value")
      }
   }
}

Listing 1-18 shows how to read values from a single channel.


To act on the values coming from different channels, Go offers the select block,
whereby you can act depending on the value read from different asynchronous channels.
The next example is packaged with Go features. Consider two inline Go routines,
each sending a string on the ch channel, after having waited for a defined short time.
The select block blocks until one of its cases is receiving a message. In Listing 1-19,
it receives the message from the two Go routines and then receives a message from the
time.After inline, then it times out.

28
Chapter 1 Go to the Basics

Listing 1-19. Select from Different Asynchronous Sources

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)
      }
   }

When executed, Listing 1-19 prints the following:

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.

Listing 1-20. Context with Timeout

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

You might also like