SlideShare a Scribd company logo
1 of 414
Download to read offline
BUILDING AN
AWESOME CLI
APP IN GO 1
2
ASHLEY MAC
•Dev Advocate at Rackspace
•Go newbie
•Slightly sarcastic
3
–Ashley Mac
“I have no idea what
i’m doing”
4
SPF13
•Willfully Unemployed
•Builds Cool Things With Go AKA
Gopher
•Irritatingly Specific
5
–Steve
“I Kinda Know What I'm
Doing”
6
MAKE SURE YOU
HAVE GO INSTALLED
AND WORKING +
AN EDITOR
7
UX OF
CLI 8
HUMAN
INTERFACE
GUIDELINES
FOR CLIS 9
UNIx
PHILOSOPHY
10
KEN'S "UNIx
PHILOSOPHY"11
UNIx PHILOSOPHY
•Simple
•Clear
•Composable

•Extensible
•Modular
•Small
12
– Rob Pike
“Many UNIX programs do quite
trivial things in isolation,
but, combined with other
programs, become general and
useful tools.”
13
– Doug McIlroy
“The manual page, which
really used to be a manual
page, is now a small volume,
with a thousand options”
14
POSIx +
GNU 15
COMMANDS
16
WHAT ARE
COMMANDS
? 17
› ls
c:dir
COMMANDS
18
› ls
› cp
› cat
› cd
list
copy
concatenate
change directory
ABBREVIATED
19
› ls
› cp
› cat
› cd
SHORT
20
Short
Clear
&
› ls
CONTExT
21
operates in current
Directory
THE
LANGUAGE OF
COMMANDS 22
› ls
HAS A LANGUAGE
23
List the contents

of the directory I'm in
› ls
› rm
› zip
› find
COMMANDS
24
Verbs
c:dir
COMMANDS
25
Noun?
ARGS
26
WHAT ARE
ARGS?
27
› rm [file]
› cp [file] [newfile]
c:copy [file] [newfile]
INPUT
28


> rm [file] ... [fileN]
MANY INPUTS
29
Arg0 Argn


> cp [file] [newfile]
ORDER MATTERS
30
From To


> cp [file] [newfile]
SEPARATED
31
Space separates
THE
LANGUAGE
OF ARGS 32


> cp [file] [newfile]
DIRECT OBJECT
33
Verb Noun Noun


> cp [file] [newfile]
IS PROUNCABLE
34
Copy this file to here
OPTIONS
35
FLAGS
36
› rm [options] [file]
c:del [options] [file]
MODIFY ACTIONS
37


› rm -f badfile.txt
SEPARATORS
38
Space separates


› rm --force
PREFIxED
39
prefix


› rm -f
PREFIxED
40
prefix


c: del /F
PREFIxED
41
prefix


-f == --force
SHORT VS LONG
42
Common Options
shortened


› rm -r -f rm -rf
STACKABLE
43
Short options stack
THE
LANGUAGE
OF FLAGS 44


› rm --force [file]
ADVERB
45
Verb Adverb Noun


› rm --force [file]
PRONOUNCEABLE
46
Forcefully remove

this file


› rm --force [file]
PRONOUNCEABLE
47
remove this file
with Force


› ls --color /home/spf13
FLAG INPUT
48
Verb Adverb Noun


› ls --color /home/spf13
PRONOUNCEABLE
49
Colorfully list my
home directory
› ls -a
MODIFY BEHAVIOR
50
› ls -a
MODIFY BEHAVIOR
51
List all the things
ALL ISN'T
AN ADVERB
52
ADVERBS ExPRESS
•manner
•place
•time
•frequency
•degree
•level of
certainty
•etc.
53
ADVERBS ANSWER
•How?
•In what way?
•When?
•Where?
•To what
extent?
54
› ls -a
MODIFY BEHAVIOR
55
List completely
to what extent?


› ls --width=40
IMPUTABLE
56
Input
to what extent?


› ls --width 40
IMPUTABLE
57
Input
to what extent?


› ls --width 40
PREPOSITION
58
Verb Preposition Obj


› ls --width 40
PRONOUNCEABLE
59
list the directory with
a width of 40 cols
PREP PHRASE = ADVERB
•consists of a preposition and its
object
•acts as an adverb
•"Speaking at OSCON"
60
BAD FLAG
DESIGN
61
FLAGS AS
ACTIONS62


› tar -xcvf
FLAG = ACTION
63
› tar
First option must be a mode
specifier:
-c Create -r Add/Replace 

-t List -u Update -x Extract
FLAG = ACTION
64
› zip
› unzip
BETTER
65
FLAGS WITH
FLAGS
66
Extract: tar -x [options]
-k Keep existing files
-m Don't restore mod times
FLAGS HAVING SUB FLAGS
67
Create: tar -c [options]
-z, -j, -J, --lzma
Compress archive with gzip/
bzip2/xz/lzma
FLAGS HAVING SUB FLAGS
68
INCOMPATIBLE
FLAGS
69
ls [options]
-S sort by file size
-t sort by modification time
-U do not sort
...
INCOMPATIBLE FLAGS
70
ls -StU
INCOMPATIBLE FLAGS
71
What should this do?
> ls
--sort=[size,modtime,none]
BETTER
72
DOUBLE
FLAGS 73
› git pull --stat --no-stat
FLAG --NO-FLAG
74
› git pull --stat
› git pull --stat=false
BETTER
75
CLI APPS
76
› httpd
› vi
› emacs
› git
CLI APPS
77
Noun
APPS
•Launch something
•Do more than one thing
•Collection of commands
78
SUB
COMMANDS
79
› svn add
› brew install
› npm search
› apt-get upgrade
› git clone
SUB COMMANDS
80
SUB COMMANDS
•CLI apps do multiple things
•Apps are groups of commands
•(sub) Commands have flags & args
•All rules still apply
81


› brew fetch -v hugo
ExPANDED RESOURCES
82
Cmd ArgApp Flag


› brew install hugo
NOUN
83
Verb ObjectNoun


› brew install hugo
PRONOUNCABLE
84
Brew, install hugo


› brew fetch -v hugo
PRONOUNCABLE
85
Verb Object
Noun adVerb


› brew fetch -v hugo
PRONOUNCABLE
86
Brew, verbosely 

fetch hugo
GO
INTRODUCTION
87
MY
ExPERIENCE
88
GOPATH AND SETUP
•You WILL store your code in a GitHub
user folder (example: $GOPATH/src/
github.com/username/helloworld)
•This was a pain in the ass
•I was comfortable with /code /dev/
or /projects 89
GOPATH AND SETUP
•By Storing code on github, I was
able to share my many problems
•Going from “I’m working on this”
to “let’s collaborate”
90
GOPATH
•The Go toolset uses an environment variable
called GOPATH to find Go source code.
•You can set GOPATH to anything you want,
but things will be easier if it’s set in your
home directory.
91
Windows:
c: setx GOPATH %USERPROFILE%


OS X:
❯ echo 'export GOPATH=$HOMEn' >> ~/.bash_profile
Close the terminal, reopen it, and type the following:
❯ echo $GOPATH
GO PATH
92
GOPATH AND SETUP
•Typing go get github.com/user/
project will download and build a
project.
93
EDITORS
•No IDE needed - any text editor will do.
•helpful features like autocomplete and
format & import on-save
•If you’re not sure what to use, I
recommend Atom — It’s free, cross-
platform, and easy to install. 94
PLUGINS
•Atom: https://github.com/joefitzgerald/go-plus
•Vim: https://github.com/fatih/vim-go
•included in http://vim.spf13.com/
•IntelliJ: 

https://plugins.jetbrains.com/plugin/?id=5047
•Full list: 

https://github.com/golang/go/wiki/
IDEsAndTextEditorPlugins 95
YOU DON’T NEED A
FRAMEWORK!
•The standard library has tons!
•Web server
•Templates
•Database
•etc.. 96
YOU DON’T NEED A
FRAMEWORK!
•Many Packages work
well together
•Very modular &
Composable 97
STANDARD LIBRARY
Let’s be honest, you don’t want to write everything from scratch so
most programming depends on your ability to interface with existing
libraries. i.e. packages. Here are a few core packages you should
know about;
•Strings
•Input/Output (io/ioutil)
•Errors
•fmt
98
• Containers and Sort
• path/filepath
• HTTP (net/http)
• math/rand
GO
99
STATICALLY

TYPED
100
STRONGLY

TYPED
101
COMPILED
102
MEMORY
MANAGED
103
POWERFUL
CONCURRENCY

BAKED IN
104
OPEN
SOURCE105
CROSS
PLATFORM
106
LANGUAGE
DESIGN
107
108
•Ken Thompson (B,C, Unix, UTF-8)
•Rob Pike (Unix, UTF-8)
•Robert Griesmier (Hotspot, JVM, V8)
MAJOR INFLUENCES
•C & derivatives
•Pascal & derivatives
•CSP
109
IDEALS
•Expressibility
•Edibility
•Powerful
•Simple
•Scalable
110
SPEC
•Java Spec : 670 pages
•YAML Spec : 84 pages
•Go Spec : 82 pages
111
KEYWORDS
•break
•default
•func
•interface
•select
•case
•defer
•go 112
•map
•struct
•chan
•else
•goto
•package
•switch
•const
•fallthrough
•if
•range
•type
•continue
•for
•import
•return
•var
BRACES
113
Fail
BRACES
Compile Eror
114
Compile Error
/tmp/sandbox826898458/main.go:6: syntax error: unexpected
semicolon or newline before {
BRACES
What works
115
Works
VARIABLES
116
Fail
VARIABLES
117
Error
/tmp/sandbox473116179/main.go:6: one declared and not used /tmp/
sandbox473116179/main.go:7: two declared and not used /tmp/
sandbox473116179/main.go:8: three declared and not used
WHAT GO
DOESN’T
HAVE 118
CLASSES 

( * SHOCKED
EXPRESSION *)119
OBJECTS
120
COMPLExITY
121
TYPES
122
SINGLE
VALUE
TYPES 123
NUMBERS
•Integers 

(numbers without a decimal)
•Floating-Point Numbers 

(numbers that contain a decimal)
• int, int8-64, uint, uint8-64, float32,64
124
STRINGS
•A string is a sequence of
characters
•Go strings are immutable
•Go strings are made up of
individual bytes (Usually one for each character)
125
MULTI VALUE
TYPES
126
type person struct {

name string

age int

}
STRUCT
127
ARRAY
•An array is an ordered sequence
of elements of a single type
•Fixed length
•Arrays are indexed starting from 0
128
SLICE
•Segment of an array
•Dynamic length
•Can be used without thinking
about array underneath
129
MAP
•Unordered collection of key-value
pairs
•Similar to associative arrays, hash
tables, and dictionaries
•Dynamic Length 130
SOME 

OTHER
TYPES 131
FUNCTION
•Function is a type
•First class citizen in Go
•Can have multiple input values
•Can have multiple return values
132
POINTERS
•Reference a location in memory
where a value is stored
•Represented using '*'
•Memory location referenced using '&'
133
DEFINE YOUR OWN TYPES
•Composed of other types
•Not aliases
134
METHOD
•Function defined on a type
135
TOOLING
136
GO HELP
The Go toolset has many different commands and
subcommands. You can pull up a list by typing:
go help
You now have everything you need to get started
137
GO FMT
•Formats your go code for you
•Awesome to do "on save"
•End of all stylistic debates
138
GO TEST
Writing code isn’t easy and humans make
mistakes so testing is really important, luckily, Go
includes a program that makes writing tests easier:
go test
Fun Fact: The Go compiler knows to ignore code
in files ending with _test.go
139
CLOSING
THOUGHTS
140
I THINK GO
IS AWESOME
141
IT HAS
STRONG
OPINIONS 142
COMPILATION IS
VERY FAST
(USUALLY A
SECOND OR TWO)143
AWESOME
COMMUNITY
144
RESOURCES
•Getting Started, official golang page — https://golang.org/doc/
•Parse’s move from Ruby to Golang — http://blog.parse.com/
learn/how-we-moved-our-api-from-ruby-to-go-and-saved-our-sanity/
•Tutorial — Creating a Wiki — https://golang.org/doc/articles/
wiki/ (this was the first big tutorial that got me to build something
useful, take this one slow to get a grasps on its concepts)
•Golang — Concurrency is not Parallelism (Rob Pike), this video I
found super informative about go’s concurency and got me excited
to keep coding in Golang — https://youtu.be/cN_DpYBzKso
145
LET'S BUILD
AN APP
146
147
HTTP://
WWW.SLIDESH
ARE.NET/SPF13
148
HTTPS://
GITHUB.COM
/SPF13/TRI 149
1. DESIGNING
OUR APP
150
WHAT'S IN
A NAME?
151
SHOCKING
AMOUNT OF
TODO APPS 152
LET'S MAKE A
BUNCH MORE
153
I'M CALLING
MINE "TRI"
154
FEATURES
155
FEATURES
•Add Todo
•List Todos
•Mark "done"
•Search/Filter
•Priorities
•Archive
•Edit
•Create Dates
•Due Dates
•Tags
•Projects
156
INTERFACE
DESIGN
157
ADDING
158
› tri add "Add Priorities"
ADD
159
› tri add Add Priorities
ADD
160


› tri add "Add Priorities"
ADD
161
Verb Object
Noun
› tri add 

"Add Multi Todo Support" 

"Consider usage behaviors"
ADD
162
PRIORITY
163
› tri add -p1 "Add listing"





ADD WITH PRIORITY
164
› tri add -p1 "Add listing"





ADD WITH PRIORITY
165
Verb Object
Noun adVerb
› tri add -p1 "Add listing"





PRONOUNCEABLE
166
Tri, add "Add listing"
Todo with a pri of 1


› tri add "Add listing P:1"





ALTERNATE SYNTAx
167
CONSIDERATIONS
•What priority system to use?
•Numeric
•Alpha
•High, Middle, Low
•What's the default priority? 168
MY TODO
•High, Middle, Low
•H=1, L=3, M/_=2
•Default is 2
169
LISTING
170


› tri ls





LISTING
171


› tri list





LISTING
172


› tri





LISTING
173
› tri list
(1) Add Listing
Consider usage behaviors
Add Multi Todo Support
Add Priorities
LISTING OUTPUT
174
› tri list
(1) Add Listing
Add Priorities
Add Multi Todo Support
Consider usage behaviors
LISTING OUTPUT
175
› tri list
(H) Add Listing
Consider usage behaviors
Add Priorities
(L) Add Multi Todo Support
LISTING OUTPUT
176
› tri list
(H) Add Listing
Consider usage behaviors
Add Priorities
(L) Add Multi Todo Support
LISTING OUTPUT
177
› tri list
1. (H) Add Listing
2. Consider usage behaviors
3. Add Priorities
4. (L) Add Multi Todo Support
LISTING OUTPUT
178
FILTERING
179


› tri list done





TOKENS
180


› tri list -p1





FLAGS
181
› tri list -p1
› tri list --due June
› tri list --created 12/15
› tri list --done -p1
FILTER BY PROPERTY
182
› tri list -p2
2. Consider usage behaviors
3. Add Priorities
FILTER BY PRIORITY
183
› tri list "Add"
1. (H) Add Listing
3. Add Priorities
4. (L) Add Multi Todo Support
SEARCHING
184
› tri list "Add" "Pri"
3. Add Priorities
SEARCHING
185
UPDATING
186
› tri list
1. (H) Add Listing
2. Consider usage behaviors
3. Add Priorities
4. (L) Add Multi Todo Support
LISTING OUTPUT
187


› tri done 2





COMPLETING
188


› tri edit 1 "Improve Listing"




EDITING
189
› tri edit 1 -p2
› tri edit 2 --due 05/13/15
› tri edit 3 --created
12/15
EDITING
190
› tri edit 1 -p2
› tri list -p2
› tri edit 3 --created 12/15
› tri list --created 12/15
CONSISTENCY
191
› tri edit 1 2 3 -p2
BATCH EDIT?
192
2. CREATING
A PROJECT
193
COBRA
194
•A CLI Command Framework
•A tool to generate CLI apps & commands
•Powers Kubernetes, Dropbox, Git Lfs,
CoreOS, Docker, Delve ...
195
› go get -u 
github.com/spf13/cobra/cobra

GET & INSTALL COBRA
196
› cobra
Cobra is a Cli library for Go that empowers applications. This

application is a tool to generate the needed files to quickly

create a Cobra application.
Usage:
cobra [command]
Available Commands:
add Add a command to a Cobra Application
COBRA
197
COBRA
APP
BUILDER 198
› cobra init 

github.com/<handle>/tri 
-a "<Your Name>"
COBRA INIT
199
Replace with your url,

project name & Name
› cobra init ...
Your Cobra application is
ready at
/Users/spf13/gopath/src/
github.com/spf13/tri
COBRA
200
› cd $GOPATH/src/
github.com/<name>/tri
CD TO PROJECT
201
Replace with your url,
project name & Name
› tree
.
├── LICENSE
├── cmd
│   └── root.go
└── main.go
LOOK AT YOUR PROJECT
202
› go build
› ./tri


A longer description that spans multiple lines
and likely contains examples
and usage of using your application. For
example...
BUILD & RUN IT
203
YOU'VE JUST
CREATED YOUR
1ST GO APP
204
IT'S ALL
UPHILL FROM
HERE 205
LET'S WRITE
SOME CODE
206
OPEN THE
PROJECT IN
AN EDITOR 207
208
LiteIDE
209
HTTPS://SOURCEFORGE.NET/PROJECTS/
LITEIDE/FILES/X29/ 210
WORKING
WITH THE
ROOT 211
package cmd



import (

"fmt"

"os"



"github.com/spf13/cobra"

"github.com/spf13/viper"

)
CMD/ROOT.GO
212
package cmd



import (

"fmt"

"os"



"github.com/spf13/cobra"

"github.com/spf13/viper"

)
CMD/ROOT.GO
213
Notice package
name
Matches Dir
// This represents the base command when called
without any subcommands

var RootCmd = &cobra.Command{

Use: "tri",

Short: "A brief description of your
application",

Long: `A longer description that spans multiple
lines and likely ... application.`,

}
CMD/ROOT.GO
214
// This represents the base command when called
without any subcommands

var RootCmd = &cobra.Command{

Use: "tri",

Short: "Tri is a todo application",

Long: `Tri will help you get more done in less time.

It's designed to be as simple as possible to help you
accomplish your goals.`,
}
CMD/ROOT.GO
215
var RootCmd = &cobra.Command{

Use: "tri",

...
CMD/ROOT.GO
216
Package level variable
& Exported
MAIN
217
MAIN MAIN MAIN
•Go programs are all about "main"
•main.go (convention)
•main package
•main()
218
package main



import "github.com/<yours>/tri/cmd"



func main() {

cmd.Execute()

}
MAIN.GO
219
package main



import "github.com/<yours>/tri/cmd"



func main() {

cmd.Execute()

}
MAIN.GO
220
Package
Name
package main



import "github.com/<yours>/tri/cmd"



func main() {

cmd.Execute()

}
MAIN.GO
221
Function
Name
func Execute() {

if err := RootCmd.Execute(); err !=
nil {

fmt.Println(err)

os.Exit(-1)

}

}
CMD/ROOT.GO
222
Package level

variable
>go run main.go
Tri will help you get more done in
less time.
It's designed to be as simple as
possible to help you accomplish
your goals.
RUN IT
223
3. CREATING
OUR ADD
COMMAND 224
ADD
"ADD" 225
> cd $GOPATH/src/
github.com/spf13/tri
CD TO PROJECT
226
Replace with your url,
project name & Name
> cobra add add
add created at $GOPATH/src/
github.com/spf13/tri/cmd/
add.go
COBRA ADD ADD
227
> go run main.go add
add called
RUN "ADD"
228
Bill wants me to replace go run with 

go build

./tri
MAKE 

"ADD" ADD229
package cmd
CMD/ADD.GO
230
var addCmd = &cobra.Command{

Use: "add",

Short: "A brief description of your command",

Long: `A longer description that spans multiple
lines and likely...`,

Run: func(cmd *cobra.Command, args []string) {

// TODO: Work your own magic here

fmt.Println("add called")

},

}
CMD/ADD.GO
231
var addCmd = &cobra.Command{

Use: "add",

Short: "Add a new todo",

Long: `Add will create a new todo item to the list`,

Run: func(cmd *cobra.Command, args []string) {

// TODO: Work your own magic here

fmt.Println("add called")

},

}
CMD/ADD.GO
232
func addRun(cmd *cobra.Command,
args []string){
fmt.Println("add called")
}
CMD/ADD.GO
233
var addCmd = &cobra.Command{

Use: "add",

Short: "Add a new todo",

Long: `Add will create a new todo
item to the list`,

Run: addRun,

}
CMD/ADD.GO
234
func addRun(cmd *cobra.Command,
args []string) {

for _, x := range args {

fmt.Println(x)

}

}
CMD/ADD.GO
235
FOR x, Y := RANGE
•Provides a way to iterate over an array,
slice, string, map, or channel.
•Like Foreach or Each in other languages
•x is index/key, y is value
•_ allows you to ignore naming variables
236


func init() {

RootCmd.AddCommand(addCmd)

}
CMD/ADD.GO
237
INIT()
•Special function
•Called after package variable declarations
•Called prior to main.main()
•Each package may have multiple init()
•init() order un-guaranteed
238
> go run main.go add 
"one two" three


one two
three
RUNNING ADD
239
4. CREATING
OUR DATA
MODEL 240
CREATE A
NEW
PACKAGE 241
242
New Folder
New File
package todo



type Item struct {

Text string

}

TODO/TODO.GO
243
NAMED TYPES
•Can be any known type (struct,
string, int, slice, a new type you’ve
declared, etc)
•Methods can be declared on it
•Not an alias - Explicit type 244
USING OUR
NEW TYPE
245


import (

"fmt"



"github.com/spf13/cobra"

"github.com/<yourname>/tri/todo"

)
CMD/ADD.GO
246
Replace with
yourS
func addRun(...) {

items := []todo.Item{}

for _, x := range args {

items = append(items, todo.Item{Text:x})

}

fmt.Println(items)

}
CMD/ADD.GO
247
func addRun(...) {

items := []todo.Item{}

for _, x := range args {

items = append(items, todo.Item{Text:x})

}

fmt.Println(items)

}
CMD/ADD.GO
248
APPEND
•Append adds new values to a slice
•Append will grow a slice as
needed
249
func addRun(...) {

items := []todo.Item{}

for _, x := range args {

items = append(items, todo.Item{Text:x})

}

fmt.Println(items)

}
CMD/ADD.GO
250
func addRun(...) {

items := []todo.Item{}

for _, x := range args {

items = append(items, todo.Item{Text:x})

}

fmt.Println(items)

}
CMD/ADD.GO
251
>go run main.go add 

"one two" three
[{one two} {three}]
GO RUN
252
func addRun(...) {

var items = []todo.Item{}

for _,x := range args {

items = append(items, todo.Item{Text:x})

}

fmt.Printf("%#vn", items)

}
CMD/ADD.GO
253
>go run main.go add 

"one two" three
[]todo.Item{todo.Item{Text:
"one two"},
todo.Item{Text:"three"}}
GO RUN
254
5. PERSISTING
OUR DATA
255
SAVING
DATA 256
func SaveItems(filename string,

items []Item) error {



return nil

}
TODO/TODO.GO
257
JSON
258
import (

"encoding/json"

)
TODO/TODO.GO
259
func SaveItems(filename string, items []Item) error {

b, err := json.Marshal(items)

if err != nil {

return err

}

fmt.Println(string(b))



return nil

}
TODO/TODO.GO
260
func SaveItems(filename string, items []Item) error {

b, err := json.Marshal(items)

if err != nil {

return err

}

fmt.Println(string(b))



return nil

}
TODO/TODO.GO
261
func SaveItems(filename string, items []Item) error {

b, err := json.Marshal(items)

if err != nil {

return err

}

fmt.Println(string(b))



return nil

}
TODO/TODO.GO
262
ERROR HANDLING
•Errors are not exceptional, they
are just values
•No exceptions in Go
•Errors should be handled when
they occur 263
( DON’T) PANIC
•Only use when:
1. You want to shut down your program AND
2. You need a stack trace
•Packages should never call Panic (only applications)
•Do not use as pseudo-exception handling
•Only recover a panic if you know you can properly
recover from it 264
func SaveItems(filename string, items []Item) error {

b, err := json.Marshal(items)

if err != nil {

return err

}

fmt.Println(string(b))



return nil

}
TODO/TODO.GO
265
func addRun(cmd *cobra.Command, 

args []string) {

var items = []todo.Item{}

for _, x := range args {

items = append(items, todo.Item{Text: x})

}

todo.SaveItems("x", items)

}
CMD/ADD.GO
266
>go run main.go add 
"one two" three
[{"Text":"one two"},
{"Text":"three"}]
CHECK JSON CREATION
267
WRITING
TO FILES268
import (

"io/ioutil"

"encoding/json"

)
TODO/TODO.GO
269
func SaveItems(filename string, items []Item) error {

...

err = ioutil.WriteFile(filename, b, 0644)

if err != nil {

return err

}



return nil

}
TODO/TODO.GO
270
func addRun(cmd *cobra.Command, 

args []string) {

var items = []todo.Item{}

for _, x := range args {

items = append(items, todo.Item{Text: x})

}


err := todo.SaveItems("/Users/spf13/.tridos.json", items);
if err != nil {

fmt.Errorf("%v", err)

}

}
CMD/ADD.GO
271
› go run main.go add "one two" three
› cat ~/.tridos.json
[{"Text":"one two"},
{"Text":"three"}]
CHECK FILE CREATION
272
READING

DATA 273
func ReadItems(filename
string) ([]Item, error) {



return []Item{}, nil

}
TODO/TODO.GO
274
func ReadItems(filename
string) ([]Item, error) {



return []Item{}, nil

}
TODO/TODO.GO
275
func ReadItems(filename string)
([]Item, error) {

b, err := ioutil.ReadFile(filename)

if err != nil {

return []Item{}, err

}
...
TODO/TODO.GO
276
func ReadItems(filename string)
([]Item, error) {

b, err := ioutil.ReadFile(filename)

if err != nil {

return []Item{}, err

}
...
TODO/TODO.GO
277
func ReadItems(filename string) ([]Item, error) {
...

var items []Item

if err := json.Unmarshal(b, &items); err != nil {

return []Item{}, err

}

return items, nil
}
TODO/TODO.GO
278
func ReadItems(filename string) ([]Item, error) {
...

var items []Item

if err := json.Unmarshal(b, &items); err != nil {

return []Item{}, err

}

return items, nil
}
TODO/TODO.GO
279
func ReadItems(filename string) ([]Item, error) {
...

var items []Item

if err := json.Unmarshal(b, &items); err != nil {

return []Item{}, err

}

return items, nil
}
TODO/TODO.GO
280
func ReadItems(filename string) ([]Item, error) {
...

var items []Item

if err := json.Unmarshal(b, &items); err != nil {

return []Item{}, err

}

return items, nil
}
TODO/TODO.GO
281
func ReadItems(filename string) ([]Item, error) {
...

var items []Item

if err := json.Unmarshal(b, &items); err != nil {

return []Item{}, err

}

return items, nil
}
TODO/TODO.GO
282
LIST
COMMAND
283
› cobra add list
list created at $GOPATH/
src/github.com/spf13/tri/
cmd/list.go
ADD LIST COMMAND
284
Run: func(cmd *cobra.Command, args []string) {

items, err := todo.ReadItems("/Users/
spf13/.tridos.json")


if err != nil {

log.Printf("%v", err)

}

fmt.Println(items)

},
CMD/LIST.GO
285
Run: func(cmd *cobra.Command, args []string) {

items, err := todo.ReadItems("/Users/
spf13/.tridos.json")


if err != nil {

log.Printf("%v", err)

}

fmt.Println(items)

},
CMD/LIST.GO
286
Run: func(cmd *cobra.Command, args []string) {

items, err := todo.ReadItems("/Users/
spf13/.tridos.json")


if err != nil {

log.Printf("%v", err)

}

fmt.Println(items)

},
CMD/LIST.GO
287
› go run main.go list
[{one two} {three}]
RUN LIST
288
func addRun(cmd *cobra.Command, args []string) {

var items = []todo.Item{}




for _, x := range args {

items = append(items, todo.Item{Text: x})

}
...
CMD/ADD.GO
289
func addRun(cmd *cobra.Command, args []string) {

items, err := todo.ReadItems("/Users/spf13/.tridos.json")

if err != nil {

log.Printf("%v", err)

}
for _, x := range args {

items = append(items, todo.Item{Text: x})

}
...
CMD/ADD.GO
290
6. ADDING
ROOT 

(GLOBAL)
FLAGS 291
USING
$HOME 292
› go get github.com/
mitchellh/go-homedir
GO GET
293
package cmd



import (

...

"github.com/mitchellh/go-homedir"

)
CMD/ROOT.GO
294


var dataFile string
CMD/ROOT.GO
295
func init() {

// Here you will define your flags and configuration settings

// Cobra supports Persistent Flags which if defined here will
be global for your application



home, err := homedir.Dir()

if err != nil {

log.Println("Unable to detect home directory. Please set
data file using --datafile.")

}
...
CMD/ROOT.GO
296
ADDING
A FLAG297
func init() {
...

RootCmd.PersistentFlags().StringVar(&dataFile,

"datafile",

home+string(os.PathSeparator)+".tridos.json",

"data file to store todos")
...
CMD/ROOT.GO
298
func init() {
...


RootCmd.PersistentFlags().StringVar(&dataFile,

"datafile",

home+string(os.PathSeparator)+".tridos.json",

"data file to store todos")
CMD/ROOT.GO
299
func init() {
...


RootCmd.PersistentFlags().StringVar(&dataFile,

"datafile",

home+string(os.PathSeparator)+".tridos.json",

"data file to store todos")
CMD/ROOT.GO
300
func init() {
...


RootCmd.PersistentFlags().StringVar(&dataFile,

"datafile",

home+string(os.PathSeparator)+".tridos.json",

"data file to store todos")
CMD/ROOT.GO
301
items, err := todo.ReadItems(dataFile)
...

err := todo.SaveItems(dataFile, items)
CMD/ADD.GO
302


items, err := todo.ReadItems(dataFile)
CMD/LIST.GO
303
› go build
› ./tri
...
Flags:
--datafile string data file to store todos (default "/
Users/spf13/.tridos.json")
-h, --help help for tri
Use "tri [command] --help" for more information about a
command.
SEE THE FLAG
304
› go build
› ./tri add "Add priorities" 

--datafile $HOME/.next.json
› ./tri list --datafile $HOME/.next.json
[{Add priorities}]
USE THE FLAG
305
7. ADDING
PRIORITIES
306
› go run main.go add 
"add priorities" 

"order by priority"
ADD SOME TODOS
307
ADJUSTING
OUR TYPE
308
type Item struct {

Text string

Priority int

}
TODO/TODO.GO
309
VALIDATING
INPUT
310
func (i *Item) SetPriority(pri int) {

switch pri {

case 1:

i.Priority = 1

case 3:

i.Priority = 3

default:

i.Priority = 2

}

}
TODO/TODO.GO
311
func (i *Item) SetPriority(pri int) {

switch pri {

case 1:

i.Priority = 1

case 3:

i.Priority = 3

default:

i.Priority = 2

}

}
TODO/TODO.GO
312
func (i *Item) SetPriority (pri int) {

switch pri {

case 1:

i.Priority = 1

case 3:

i.Priority = 3

default:

i.Priority = 2

}

}
TODO/TODO.GO
313
ADDING
FLAG 314
var priority int
...

func init() {

RootCmd.AddCommand(addCmd)



addCmd.Flags().IntVarP(&priority, 

"priority", "p", 2, "Priority:1,2,3")
...
CMD/ADD.GO
315
var priority int
...

func init() {

RootCmd.AddCommand(addCmd)



addCmd.Flags().IntVarP(&priority, 

"priority", "p", 2, "Priority:1,2,3")
...
CMD/ADD.GO
316
› go build
› ./tri help add
Add will create a new todo item to the list
Usage:
tri add [flags]
Flags:
-p, --priority int Priority:1,2,3 (default 2)
HELP ADD
317
SETTING
PRIORITY318
func addRun(cmd *cobra.Command, args []string) {

...

for _, x := range args {

item := todo.Item{Text: x}

item.SetPriority(priority)

items = append(items, item)

}

CMD/ADD.GO
319
func addRun(cmd *cobra.Command, args []string) {

...

for _, x := range args {

item := todo.Item{Text: x}

item.SetPriority(priority)

items = append(items, item)

}

CMD/ADD.GO
320
› ./tri add "format list" -p1
› ./tri list
[{add priorities 0} {order by
priority 0} {format list 1}]
ADD WITH PRIORITY
321
8. MAKING
OUR LIST
PRETTY 322
BREAK OUT
LISTRUN
323
// listCmd respresents the list command

var listCmd = &cobra.Command{

Use: "list",

Short: "List the todos",

Long: `Listing the todos`,

Run: listRun,

}



func listRun(cmd *cobra.Command, args []string) {
...
}
CMD/LIST.GO
324
TAB-
WRITER325
func listRun(cmd *cobra.Command, args []string) {
...
w := tabwriter.NewWriter(os.Stdout, 3, 0, 1, ' ', 0)

for _, i := range items {

fmt.Fprintln(w, strconv.Itoa(i.Priority)+"t"+i.Text+"t")

}



w.Flush()
}
CMD/LIST.GO
326
func listRun(cmd *cobra.Command, args []string) {
...
w := tabwriter.NewWriter(os.Stdout, 3, 0, 1, ' ', 0)

for _, i := range items {

fmt.Fprintln(w, strconv.Itoa(i.Priority)+"t"+i.Text+"t")

}



w.Flush()
}
CMD/LIST.GO
327
func listRun(cmd *cobra.Command, args []string) {
...
w := tabwriter.NewWriter(os.Stdout, 3, 0, 1, ' ', 0)

for _, i := range items {

fmt.Fprintln(w, strconv.Itoa(i.Priority)+"t"+i.Text+"t")

}



w.Flush()
}
CMD/LIST.GO
328
func listRun(cmd *cobra.Command, args []string) {
...
w := tabwriter.NewWriter(os.Stdout, 3, 0, 1, ' ', 0)

for _, i := range items {

fmt.Fprintln(w, strconv.Itoa(i.Priority)+"t"+i.Text+"t")

}



w.Flush()
}
CMD/LIST.GO
329
func listRun(cmd *cobra.Command, args []string) {
...
w := tabwriter.NewWriter(os.Stdout, 3, 0, 1, ' ', 0)

for _, i := range items {

fmt.Fprintln(w, strconv.Itoa(i.Priority)+"t"+i.Text+"t")

}



w.Flush()
}
CMD/LIST.GO
330
› go run main.go list
0 add priorities
0 order by priority
1 format list
LIST W/PRIORITY
331
PRETTIER
PRIORITY

PRINTING 332
func (i *Item) PrettyP() string {

if i.Priority == 1 {

return "(1)"

}

if i.Priority == 3 {

return "(3)"

}



return " "

}
TODO/TODO.GO
333
func listRun(cmd *cobra.Command, args []string) {
...
w := tabwriter.NewWriter(os.Stdout, 3, 0, 1, ' ', 0)

for _, i := range items {

fmt.Fprintln(w, i.PrettyP()+"t"+i.Text+"t")

}



w.Flush()
}
CMD/LIST.GO
334
› go run main.go list
add priorities
order by priority
(1) format list
LIST W/PRIORITY
335
LABELS
336
type Item struct {

Text string

Priority int

position int

}
TODO/TODO.GO
337
type Item struct {

Text string

Priority int

position int

}
TODO/TODO.GO
338
Notice
Lowercase p
func (i *Item) Label() string {

return strconv.Itoa(i.position) + "."

}
TODO/TODO.GO
339
func ReadItems(filename string) ([]Item, error) {

...



for i, _ := range items {

items[i].position = i + 1

}



return items, nil

}
TODO/TODO.GO
340
› go run main.go list
1. add priorities
2. order by priority
3. (1) format list
LIST W/PRIORITY
341
SORT
342
// ByPri implements sort.Interface for []Item based on

// the Priority & position field.

type ByPri []Item



func (s ByPri) Len() int { return len(s) }

func (s ByPri) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s ByPri) Less(i, j int) bool {

if s[i].Priority == s[j].Priority {

return s[i].position < s[j].position

}

return s[i].Priority < s[j].Priority

}
TODO/TODO.GO
343
// ByPri implements sort.Interface for []Item based on

// the Priority & position field.

type ByPri []Item



func (s ByPri) Len() int { return len(s) }

func (s ByPri) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s ByPri) Less(i, j int) bool {

if s[i].Priority == s[j].Priority {

return s[i].position < s[j].position

}

return s[i].Priority < s[j].Priority

}
TODO/TODO.GO
344
// ByPri implements sort.Interface for []Item based on

// the Priority & position field.

type ByPri []Item



func (s ByPri) Len() int { return len(s) }

func (s ByPri) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s ByPri) Less(i, j int) bool {

if s[i].Priority == s[j].Priority {

return s[i].position < s[j].position

}

return s[i].Priority < s[j].Priority

}
TODO/TODO.GO
345
// ByPri implements sort.Interface for []Item based on

// the Priority & position field.

type ByPri []Item



func (s ByPri) Len() int { return len(s) }

func (s ByPri) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s ByPri) Less(i, j int) bool {

if s[i].Priority == s[j].Priority {

return s[i].position < s[j].position

}

return s[i].Priority < s[j].Priority

}
TODO/TODO.GO
346
// ByPri implements sort.Interface for []Item based on

// the Priority & position field.

type ByPri []Item



func (s ByPri) Len() int { return len(s) }

func (s ByPri) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s ByPri) Less(i, j int) bool {

if s[i].Priority == s[j].Priority {

return s[i].position < s[j].position

}

return s[i].Priority < s[j].Priority

}
TODO/TODO.GO
347
// ByPri implements sort.Interface for []Item based on

// the Priority & position field.

type ByPri []Item



func (s ByPri) Len() int { return len(s) }

func (s ByPri) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s ByPri) Less(i, j int) bool {

if s[i].Priority == s[j].Priority {

return s[i].position < s[j].position

}

return s[i].Priority < s[j].Priority

}
TODO/TODO.GO
348


func listRun(cmd *cobra.Command, args []string) {

...



sort.Sort(todo.ByPri(items))



w := tabwriter.NewWriter(os.Stdout, 3, 0, 1, ' ', 0)
...
CMD/LIST.GO
349
› go run main.go list
3. (1) format list
1. add priorities
2. order by priority
LIST W/PRIORITY
350
9. DONE-ING

TODOS
351
ADD
DONE 352
› cobra add done
done created at $GOPATH/
src/github.com/spf13/tri/
cmd/done.go
COBRA ADD DONE
353
// doneCmd represents the done command

var doneCmd = &cobra.Command{

Use: "done",

Aliases: []string{"do"},

Short: "Mark Item as Done",

Run: doneRun,

}
CMD/DONE.GO
354
ADD 

.DONE 355
type Item struct {

Text string

Priority int

position int

Done bool

}
TODO/TODO.GO
356
TRI DONE 

SET 

.DONE 357
func doneRun(cmd *cobra.Command, args []string) {

items, err := todo.ReadItems(dataFile)

i, err := strconv.Atoi(args[0])



if err != nil {

log.Fatalln(args[0], "is not a valid labeln", err)

}
...
CMD/DONE.GO
358
Break out still
func doneRun(cmd *cobra.Command, args []string) {

...
if i > 0 && i < len(items) {

items[i-1].Done = true

fmt.Printf("%q %vn", items[i-1].Text, "marked done")


sort.Sort(todo.ByPri(items))

todo.SaveItems(dataFile, items)

} else {

log.Println(i, "doesn't match any items")

}

}
CMD/DONE.GO
359
Break out slide
› go run main.go done a
2016/05/14 22:22:03 a is not
a valid label
strconv.ParseInt: parsing
"a": invalid syntax
DONE WRONG
360
› go run main.go done 13
2016/05/14 22:44:06 13
doesn't match any items
DONE WRONG
361
› go run main.go done 1
DONE RIGHT
362
UPDATE
LISTING363
func (i *Item) PrettyDone() string {

if i.Done {

return "X"

}

return ""

}
TODO/TODO.GO
364
fmt.Fprintln(w, i.Label()
+"t"+i.PrettyDone()
+"t"+i.PrettyP()
+"t"+i.Text+"t")

CMD/LIST.GO
365
func (s ByPri) Less(i, j int) bool {

if s[i].Done == s[j].Done {

if s[i].Priority == s[j].Priority {

return s[i].position < s[j].position

}

return s[i].Priority < s[j].Priority

}

return !s[i].Done

}
TODO/TODO.GO
366
› go run main.go list
1. (1) format list
2. X order by priority
3. X add priorities
LIST
367
ADD
--DONE
FLAG 368
› go run main.go add "hide
done items"
ADD NEW TODO
369
fmt.Fprintln(w, i.Label()
+"t"+i.PrettyDone()
+"t"+i.PrettyP()
+"t"+i.Text+"t")

CMD/LIST.GO
370
var (

doneOpt bool

)
CMD/LIST.GO
371
func init() {

RootCmd.AddCommand(listCmd)



listCmd.Flags().BoolVar(&doneOpt,
"done", false, "Show 'Done' Todos ")
}
CMD/LIST.GO
372
func listRun(cmd *cobra.Command, args []string) {

...
for _, i := range items {

if i.Done == doneOpt {

fmt.Fprintln(w, i.Label()...)

}

}
CMD/LIST.GO
373
› go run main.go list --done
3. X order by priority
4. X add priorities
TRY --DONE
374
SHOW
ALL 375
var (

doneOpt bool

allOpt bool

)
CMD/LIST.GO
376
func init() {

...
listCmd.Flags().BoolVar(&allOpt,
"all", false, "Show all Todos")
}
CMD/LIST.GO
377
func listRun(cmd *cobra.Command, args []string) {

...
for _, i := range items {

if allOpt || i.Done == doneOpt {

fmt.Fprintln(w, i.Label()...)

}

}
CMD/LIST.GO
378
› go run main.go list --all --done
1. (1) format list
2. hide done items
3. X order by priority
4. X add priorities
TRY --ALL
379
10.
CONFIG380
›./tri list --datafile 
$HOME/Dropbox/Sync/tridos.json
›./tri add "Add config/ENV support" 
--datafile $HOME/Dropbox/Sync/tridos.json
USING DIFFERENT DATA FILE
381
CONFIG
FTW 382
•A configuration manager
•Registry for application settings
•Works well with Cobra
383
VIPER SUPPORTS
•YAML, TOML, JSON or HCL
•Etcd, Consul
•Config LiveReloading
•default < KeyVal < config < env < flag
•Aliases & Nested values 384
var cfgFile string
func init() {

cobra.OnInitialize(initConfig)
...

RootCmd.PersistentFlags().StringVar(&cfgFile,
"config", "", "config file (default is
$HOME/.tri.yaml)")

...
CMD/ROOT.GO
385
Already There
// Read in config file and ENV variables if set.

func initConfig() {

viper.SetConfigName(".tri") 

viper.AddConfigPath("$HOME")

viper.AutomaticEnv() 



// If a config file is found, read it in.

if err := viper.ReadInConfig(); err == nil {

fmt.Println("Using config file:", viper.ConfigFileUsed())

}
}
CMD/ROOT.GO
386
Already There
12 FACTOR
APPS
387
STRICT
SEPARATION OF
CONFIG FROM
CODE 388
CONFIG IS STUFF
THAT VARIES IN
DIFFERENT
ENVIRONMENTS 389
CODE IS STUFF
THAT STAYS THE
SAME
EVERYWHERE 390
THE 12 FACTOR
APP STORES
CONFIG IN ENV
VARS 391
READ
FROM
VIPER 392


func addRun(cmd *cobra.Command, args []string) {

items, err := todo.ReadItems(dataFile))
...
if err := todo.SaveItems(dataFile), items); err != nil {
CMD/ADD.GO
393


func addRun(cmd *cobra.Command, args []string) {

items, err := todo.ReadItems(viper.GetString("datafile"))
...
if err := todo.SaveItems(viper.GetString("datafile"), items);
err != nil {
CMD/ADD.GO
394


func doneRun(cmd *cobra.Command, args []string) {
...
items, err := todo.ReadItems(viper.GetString("datafile"))
...


todo.SaveItems(viper.GetString("datafile"), items)
CMD/DONE.GO
395


func listRun(cmd *cobra.Command, args []string) {
items, err := todo.ReadItems(viper.GetString("datafile"))
...
CMD/LIST.GO
396
ENV
397
›./tri list --datafile 
$HOME/Dropbox/Sync/tridos.json
›./tri add "Add config/ENV support" 
--datafile $HOME/Dropbox/Sync/tridos.json
USING DIFFERENT DATA FILE
398
› DATAFILE=$HOME/Dropbox/Sync/trido.json 
./tri list
› DATAFILE=$HOME/Dropbox/Sync/trido.json 
./tri add "Add config/ENV support"
USING ENV
399
› export DATAFILE=$HOME/Dropbox/Sync/
trido.json
› ./tri list
1. Add config/ENV support
2. Add config/ENV support
ExPORT FTW
400
PLAYING
NICE WITH
OTHERS 401
// Read in config file and ENV variables if set.

func initConfig() {

viper.SetConfigName(".tri") 

viper.AddConfigPath("$HOME")

viper.AutomaticEnv()
viper.SetEnvPrefix("tri")





// If a config file is found, read it in.

if err := viper.ReadInConfig(); err == nil {

fmt.Println("Using config file:", viper.ConfigFileUsed())

}
CMD/ROOT.GO
402
› export TRI_DATAFILE=$HOME/Dropbox/
Sync/trido.json
› ./tri list
1. Add config/ENV support
2. Add config/ENV support
ExPORT FTW
403
CONFIG
FILES 404
GOOD
FOR APPS405
› echo "datafile: /Users/
spf13/Dropbox/Sync/
trido.json" >
$HOME/.tri.yaml
CREATE CONFIG FILE
406
› go run main.go list
Using config file: /Users/
spf13/.tri.yaml
1. Add config/ENV support
2. Add config/ENV support
USE CONFIG FILE
407
11. WORKING
AHEAD
408
TRY TO
IMPLEMENT
ExTRA FEATURES
409
EDITING
410
SEARCH
411
FOLLOW US ON
TWITTER
@ASHLEYMCNAMARA
@SPF13
412
ADDITIONAL RESOURCES
•Ashley's Learn to Code Resources
•Steve's Blog
•Go Girls Who Code
413
END
414

More Related Content

What's hot

Extending kubernetes with CustomResourceDefinitions
Extending kubernetes with CustomResourceDefinitionsExtending kubernetes with CustomResourceDefinitions
Extending kubernetes with CustomResourceDefinitionsStefan Schimanski
 
ksqlDB: A Stream-Relational Database System
ksqlDB: A Stream-Relational Database SystemksqlDB: A Stream-Relational Database System
ksqlDB: A Stream-Relational Database Systemconfluent
 
JavaScript guide 2020 Learn JavaScript
JavaScript guide 2020 Learn JavaScriptJavaScript guide 2020 Learn JavaScript
JavaScript guide 2020 Learn JavaScriptLaurence Svekis ✔
 
Walking through the Spring Stack for Apache Kafka with Soby Chacko | Kafka S...
 Walking through the Spring Stack for Apache Kafka with Soby Chacko | Kafka S... Walking through the Spring Stack for Apache Kafka with Soby Chacko | Kafka S...
Walking through the Spring Stack for Apache Kafka with Soby Chacko | Kafka S...HostedbyConfluent
 
Python Deserialization Attacks
Python Deserialization AttacksPython Deserialization Attacks
Python Deserialization AttacksNSConclave
 
Developing Microservices with Apache Camel
Developing Microservices with Apache CamelDeveloping Microservices with Apache Camel
Developing Microservices with Apache CamelClaus Ibsen
 
톰캣 운영 노하우
톰캣 운영 노하우톰캣 운영 노하우
톰캣 운영 노하우jieunsys
 
Terraform Introduction
Terraform IntroductionTerraform Introduction
Terraform Introductionsoniasnowfrog
 
Multi cluster, multitenant and hierarchical kafka messaging service slideshare
Multi cluster, multitenant and hierarchical kafka messaging service   slideshareMulti cluster, multitenant and hierarchical kafka messaging service   slideshare
Multi cluster, multitenant and hierarchical kafka messaging service slideshareAllen (Xiaozhong) Wang
 
Go Programming language, golang
Go Programming language, golangGo Programming language, golang
Go Programming language, golangBasil N G
 
AEM (CQ) Dispatcher Security and CDN+Browser Caching
AEM (CQ) Dispatcher Security and CDN+Browser CachingAEM (CQ) Dispatcher Security and CDN+Browser Caching
AEM (CQ) Dispatcher Security and CDN+Browser CachingAndrew Khoury
 
Golang - Overview of Go (golang) Language
Golang - Overview of Go (golang) LanguageGolang - Overview of Go (golang) Language
Golang - Overview of Go (golang) LanguageAniruddha Chakrabarti
 
Introduction to Kafka Streams
Introduction to Kafka StreamsIntroduction to Kafka Streams
Introduction to Kafka StreamsGuozhang Wang
 
Typescript: Beginner to Advanced
Typescript: Beginner to AdvancedTypescript: Beginner to Advanced
Typescript: Beginner to AdvancedTalentica Software
 

What's hot (20)

Extending kubernetes with CustomResourceDefinitions
Extending kubernetes with CustomResourceDefinitionsExtending kubernetes with CustomResourceDefinitions
Extending kubernetes with CustomResourceDefinitions
 
ksqlDB: A Stream-Relational Database System
ksqlDB: A Stream-Relational Database SystemksqlDB: A Stream-Relational Database System
ksqlDB: A Stream-Relational Database System
 
JavaScript guide 2020 Learn JavaScript
JavaScript guide 2020 Learn JavaScriptJavaScript guide 2020 Learn JavaScript
JavaScript guide 2020 Learn JavaScript
 
Walking through the Spring Stack for Apache Kafka with Soby Chacko | Kafka S...
 Walking through the Spring Stack for Apache Kafka with Soby Chacko | Kafka S... Walking through the Spring Stack for Apache Kafka with Soby Chacko | Kafka S...
Walking through the Spring Stack for Apache Kafka with Soby Chacko | Kafka S...
 
Python Deserialization Attacks
Python Deserialization AttacksPython Deserialization Attacks
Python Deserialization Attacks
 
Kafka presentation
Kafka presentationKafka presentation
Kafka presentation
 
Developing Microservices with Apache Camel
Developing Microservices with Apache CamelDeveloping Microservices with Apache Camel
Developing Microservices with Apache Camel
 
톰캣 운영 노하우
톰캣 운영 노하우톰캣 운영 노하우
톰캣 운영 노하우
 
Terraform Introduction
Terraform IntroductionTerraform Introduction
Terraform Introduction
 
Multi cluster, multitenant and hierarchical kafka messaging service slideshare
Multi cluster, multitenant and hierarchical kafka messaging service   slideshareMulti cluster, multitenant and hierarchical kafka messaging service   slideshare
Multi cluster, multitenant and hierarchical kafka messaging service slideshare
 
Go Programming language, golang
Go Programming language, golangGo Programming language, golang
Go Programming language, golang
 
AEM (CQ) Dispatcher Security and CDN+Browser Caching
AEM (CQ) Dispatcher Security and CDN+Browser CachingAEM (CQ) Dispatcher Security and CDN+Browser Caching
AEM (CQ) Dispatcher Security and CDN+Browser Caching
 
Event-sourced architectures with Akka
Event-sourced architectures with AkkaEvent-sourced architectures with Akka
Event-sourced architectures with Akka
 
Golang - Overview of Go (golang) Language
Golang - Overview of Go (golang) LanguageGolang - Overview of Go (golang) Language
Golang - Overview of Go (golang) Language
 
Apache Kafka
Apache KafkaApache Kafka
Apache Kafka
 
Ansible
AnsibleAnsible
Ansible
 
laravel.pptx
laravel.pptxlaravel.pptx
laravel.pptx
 
Ansible
AnsibleAnsible
Ansible
 
Introduction to Kafka Streams
Introduction to Kafka StreamsIntroduction to Kafka Streams
Introduction to Kafka Streams
 
Typescript: Beginner to Advanced
Typescript: Beginner to AdvancedTypescript: Beginner to Advanced
Typescript: Beginner to Advanced
 

Viewers also liked

Getting Started with Go
Getting Started with GoGetting Started with Go
Getting Started with GoSteven Francia
 
Painless Data Storage with MongoDB & Go
Painless Data Storage with MongoDB & Go Painless Data Storage with MongoDB & Go
Painless Data Storage with MongoDB & Go Steven Francia
 
Go for Object Oriented Programmers or Object Oriented Programming without Obj...
Go for Object Oriented Programmers or Object Oriented Programming without Obj...Go for Object Oriented Programmers or Object Oriented Programming without Obj...
Go for Object Oriented Programmers or Object Oriented Programming without Obj...Steven Francia
 
The Future of the Operating System - Keynote LinuxCon 2015
The Future of the Operating System -  Keynote LinuxCon 2015The Future of the Operating System -  Keynote LinuxCon 2015
The Future of the Operating System - Keynote LinuxCon 2015Steven Francia
 
7 Common mistakes in Go and when to avoid them
7 Common mistakes in Go and when to avoid them7 Common mistakes in Go and when to avoid them
7 Common mistakes in Go and when to avoid themSteven Francia
 
What every successful open source project needs
What every successful open source project needsWhat every successful open source project needs
What every successful open source project needsSteven Francia
 
MongoDB, Hadoop and Humongous Data
MongoDB, Hadoop and Humongous DataMongoDB, Hadoop and Humongous Data
MongoDB, Hadoop and Humongous DataSteven Francia
 
Build your first MongoDB App in Ruby @ StrangeLoop 2013
Build your first MongoDB App in Ruby @ StrangeLoop 2013Build your first MongoDB App in Ruby @ StrangeLoop 2013
Build your first MongoDB App in Ruby @ StrangeLoop 2013Steven Francia
 
Introduction to MongoDB and Hadoop
Introduction to MongoDB and HadoopIntroduction to MongoDB and Hadoop
Introduction to MongoDB and HadoopSteven Francia
 
Replication, Durability, and Disaster Recovery
Replication, Durability, and Disaster RecoveryReplication, Durability, and Disaster Recovery
Replication, Durability, and Disaster RecoverySteven Francia
 
Time series with apache cassandra strata
Time series with apache cassandra   strataTime series with apache cassandra   strata
Time series with apache cassandra strataPatrick McFadin
 
NoSQL into E-Commerce: lessons learned
NoSQL into E-Commerce: lessons learnedNoSQL into E-Commerce: lessons learned
NoSQL into E-Commerce: lessons learnedLa FeWeb
 
NoSQL databases and managing big data
NoSQL databases and managing big dataNoSQL databases and managing big data
NoSQL databases and managing big dataSteven Francia
 
Building a Pluggable Analytics Stack with Cassandra (Jim Peregord, Element Co...
Building a Pluggable Analytics Stack with Cassandra (Jim Peregord, Element Co...Building a Pluggable Analytics Stack with Cassandra (Jim Peregord, Element Co...
Building a Pluggable Analytics Stack with Cassandra (Jim Peregord, Element Co...DataStax
 
OSCON 2012 MongoDB Tutorial
OSCON 2012 MongoDB TutorialOSCON 2012 MongoDB Tutorial
OSCON 2012 MongoDB TutorialSteven Francia
 
Write microservice in golang
Write microservice in golangWrite microservice in golang
Write microservice in golangBo-Yi Wu
 
From NASA to Startups to Big Commerce
From NASA to Startups to Big CommerceFrom NASA to Startups to Big Commerce
From NASA to Startups to Big CommerceDaniel Greenfeld
 
Big Data Testing: Ensuring MongoDB Data Quality
Big Data Testing: Ensuring MongoDB Data QualityBig Data Testing: Ensuring MongoDB Data Quality
Big Data Testing: Ensuring MongoDB Data QualityRTTS
 
Python Tricks That You Can't Live Without
Python Tricks That You Can't Live WithoutPython Tricks That You Can't Live Without
Python Tricks That You Can't Live WithoutAudrey Roy
 
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...Matt Harrison
 

Viewers also liked (20)

Getting Started with Go
Getting Started with GoGetting Started with Go
Getting Started with Go
 
Painless Data Storage with MongoDB & Go
Painless Data Storage with MongoDB & Go Painless Data Storage with MongoDB & Go
Painless Data Storage with MongoDB & Go
 
Go for Object Oriented Programmers or Object Oriented Programming without Obj...
Go for Object Oriented Programmers or Object Oriented Programming without Obj...Go for Object Oriented Programmers or Object Oriented Programming without Obj...
Go for Object Oriented Programmers or Object Oriented Programming without Obj...
 
The Future of the Operating System - Keynote LinuxCon 2015
The Future of the Operating System -  Keynote LinuxCon 2015The Future of the Operating System -  Keynote LinuxCon 2015
The Future of the Operating System - Keynote LinuxCon 2015
 
7 Common mistakes in Go and when to avoid them
7 Common mistakes in Go and when to avoid them7 Common mistakes in Go and when to avoid them
7 Common mistakes in Go and when to avoid them
 
What every successful open source project needs
What every successful open source project needsWhat every successful open source project needs
What every successful open source project needs
 
MongoDB, Hadoop and Humongous Data
MongoDB, Hadoop and Humongous DataMongoDB, Hadoop and Humongous Data
MongoDB, Hadoop and Humongous Data
 
Build your first MongoDB App in Ruby @ StrangeLoop 2013
Build your first MongoDB App in Ruby @ StrangeLoop 2013Build your first MongoDB App in Ruby @ StrangeLoop 2013
Build your first MongoDB App in Ruby @ StrangeLoop 2013
 
Introduction to MongoDB and Hadoop
Introduction to MongoDB and HadoopIntroduction to MongoDB and Hadoop
Introduction to MongoDB and Hadoop
 
Replication, Durability, and Disaster Recovery
Replication, Durability, and Disaster RecoveryReplication, Durability, and Disaster Recovery
Replication, Durability, and Disaster Recovery
 
Time series with apache cassandra strata
Time series with apache cassandra   strataTime series with apache cassandra   strata
Time series with apache cassandra strata
 
NoSQL into E-Commerce: lessons learned
NoSQL into E-Commerce: lessons learnedNoSQL into E-Commerce: lessons learned
NoSQL into E-Commerce: lessons learned
 
NoSQL databases and managing big data
NoSQL databases and managing big dataNoSQL databases and managing big data
NoSQL databases and managing big data
 
Building a Pluggable Analytics Stack with Cassandra (Jim Peregord, Element Co...
Building a Pluggable Analytics Stack with Cassandra (Jim Peregord, Element Co...Building a Pluggable Analytics Stack with Cassandra (Jim Peregord, Element Co...
Building a Pluggable Analytics Stack with Cassandra (Jim Peregord, Element Co...
 
OSCON 2012 MongoDB Tutorial
OSCON 2012 MongoDB TutorialOSCON 2012 MongoDB Tutorial
OSCON 2012 MongoDB Tutorial
 
Write microservice in golang
Write microservice in golangWrite microservice in golang
Write microservice in golang
 
From NASA to Startups to Big Commerce
From NASA to Startups to Big CommerceFrom NASA to Startups to Big Commerce
From NASA to Startups to Big Commerce
 
Big Data Testing: Ensuring MongoDB Data Quality
Big Data Testing: Ensuring MongoDB Data QualityBig Data Testing: Ensuring MongoDB Data Quality
Big Data Testing: Ensuring MongoDB Data Quality
 
Python Tricks That You Can't Live Without
Python Tricks That You Can't Live WithoutPython Tricks That You Can't Live Without
Python Tricks That You Can't Live Without
 
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...
 

Similar to Building Awesome CLI apps in Go

Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboyKenneth Geisshirt
 
Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboyKenneth Geisshirt
 
Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboyKenneth Geisshirt
 
Tanel Poder Oracle Scripts and Tools (2010)
Tanel Poder Oracle Scripts and Tools (2010)Tanel Poder Oracle Scripts and Tools (2010)
Tanel Poder Oracle Scripts and Tools (2010)Tanel Poder
 
LINUX_admin_commands.pptx
LINUX_admin_commands.pptxLINUX_admin_commands.pptx
LINUX_admin_commands.pptxGuhanSenthil2
 
Holy PowerShell, BATman! - dogfood edition
Holy PowerShell, BATman! - dogfood editionHoly PowerShell, BATman! - dogfood edition
Holy PowerShell, BATman! - dogfood editionDave Diehl
 
The Ultimate IBM and Lotus on Linux Workshop for Windows Admins
The Ultimate IBM and Lotus on Linux Workshop for Windows AdminsThe Ultimate IBM and Lotus on Linux Workshop for Windows Admins
The Ultimate IBM and Lotus on Linux Workshop for Windows AdminsBill Malchisky Jr.
 
24HOP Introduction to Linux for SQL Server DBAs
24HOP Introduction to Linux for SQL Server DBAs24HOP Introduction to Linux for SQL Server DBAs
24HOP Introduction to Linux for SQL Server DBAsKellyn Pot'Vin-Gorman
 
Docker 102 - Immutable Infrastructure
Docker 102 - Immutable InfrastructureDocker 102 - Immutable Infrastructure
Docker 102 - Immutable InfrastructureAdrian Otto
 
Automated Deployment and Configuration Engines. Ansible
Automated Deployment and Configuration Engines. AnsibleAutomated Deployment and Configuration Engines. Ansible
Automated Deployment and Configuration Engines. AnsibleAlberto Molina Coballes
 
On the Edge Systems Administration with Golang
On the Edge Systems Administration with GolangOn the Edge Systems Administration with Golang
On the Edge Systems Administration with GolangChris McEniry
 
Improve Your IBM Domino Designer Experience
Improve Your IBM Domino Designer ExperienceImprove Your IBM Domino Designer Experience
Improve Your IBM Domino Designer Experiencepanagenda
 
Tanel Poder - Scripts and Tools short
Tanel Poder - Scripts and Tools shortTanel Poder - Scripts and Tools short
Tanel Poder - Scripts and Tools shortTanel Poder
 
Linux container internals
Linux container internalsLinux container internals
Linux container internalsAshwin Bilgi
 

Similar to Building Awesome CLI apps in Go (20)

Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboy
 
redhat_by_Cbitss.ppt
redhat_by_Cbitss.pptredhat_by_Cbitss.ppt
redhat_by_Cbitss.ppt
 
Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboy
 
Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboy
 
Tanel Poder Oracle Scripts and Tools (2010)
Tanel Poder Oracle Scripts and Tools (2010)Tanel Poder Oracle Scripts and Tools (2010)
Tanel Poder Oracle Scripts and Tools (2010)
 
LINUX_admin_commands.pptx
LINUX_admin_commands.pptxLINUX_admin_commands.pptx
LINUX_admin_commands.pptx
 
#WeSpeakLinux Session
#WeSpeakLinux Session#WeSpeakLinux Session
#WeSpeakLinux Session
 
Holy PowerShell, BATman! - dogfood edition
Holy PowerShell, BATman! - dogfood editionHoly PowerShell, BATman! - dogfood edition
Holy PowerShell, BATman! - dogfood edition
 
The Ultimate IBM and Lotus on Linux Workshop for Windows Admins
The Ultimate IBM and Lotus on Linux Workshop for Windows AdminsThe Ultimate IBM and Lotus on Linux Workshop for Windows Admins
The Ultimate IBM and Lotus on Linux Workshop for Windows Admins
 
24HOP Introduction to Linux for SQL Server DBAs
24HOP Introduction to Linux for SQL Server DBAs24HOP Introduction to Linux for SQL Server DBAs
24HOP Introduction to Linux for SQL Server DBAs
 
Docker 102 - Immutable Infrastructure
Docker 102 - Immutable InfrastructureDocker 102 - Immutable Infrastructure
Docker 102 - Immutable Infrastructure
 
Automated Deployment and Configuration Engines. Ansible
Automated Deployment and Configuration Engines. AnsibleAutomated Deployment and Configuration Engines. Ansible
Automated Deployment and Configuration Engines. Ansible
 
Ansible - A 'crowd' introduction
Ansible - A 'crowd' introductionAnsible - A 'crowd' introduction
Ansible - A 'crowd' introduction
 
On the Edge Systems Administration with Golang
On the Edge Systems Administration with GolangOn the Edge Systems Administration with Golang
On the Edge Systems Administration with Golang
 
SolrCloud on Hadoop
SolrCloud on HadoopSolrCloud on Hadoop
SolrCloud on Hadoop
 
Improve Your IBM Domino Designer Experience
Improve Your IBM Domino Designer ExperienceImprove Your IBM Domino Designer Experience
Improve Your IBM Domino Designer Experience
 
DevOps for database
DevOps for databaseDevOps for database
DevOps for database
 
Tanel Poder - Scripts and Tools short
Tanel Poder - Scripts and Tools shortTanel Poder - Scripts and Tools short
Tanel Poder - Scripts and Tools short
 
Rustbridge
RustbridgeRustbridge
Rustbridge
 
Linux container internals
Linux container internalsLinux container internals
Linux container internals
 

More from Steven Francia

State of the Gopher Nation - Golang - August 2017
State of the Gopher Nation - Golang - August 2017State of the Gopher Nation - Golang - August 2017
State of the Gopher Nation - Golang - August 2017Steven Francia
 
Modern Database Systems (for Genealogy)
Modern Database Systems (for Genealogy)Modern Database Systems (for Genealogy)
Modern Database Systems (for Genealogy)Steven Francia
 
MongoDB, Hadoop and humongous data - MongoSV 2012
MongoDB, Hadoop and humongous data - MongoSV 2012MongoDB, Hadoop and humongous data - MongoSV 2012
MongoDB, Hadoop and humongous data - MongoSV 2012Steven Francia
 
Big data for the rest of us
Big data for the rest of usBig data for the rest of us
Big data for the rest of usSteven Francia
 
Multi Data Center Strategies
Multi Data Center StrategiesMulti Data Center Strategies
Multi Data Center StrategiesSteven Francia
 
Hybrid MongoDB and RDBMS Applications
Hybrid MongoDB and RDBMS ApplicationsHybrid MongoDB and RDBMS Applications
Hybrid MongoDB and RDBMS ApplicationsSteven Francia
 
Building your first application w/mongoDB MongoSV2011
Building your first application w/mongoDB MongoSV2011Building your first application w/mongoDB MongoSV2011
Building your first application w/mongoDB MongoSV2011Steven Francia
 
MongoDB, E-commerce and Transactions
MongoDB, E-commerce and TransactionsMongoDB, E-commerce and Transactions
MongoDB, E-commerce and TransactionsSteven Francia
 
MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011Steven Francia
 
MongoDB and PHP ZendCon 2011
MongoDB and PHP ZendCon 2011MongoDB and PHP ZendCon 2011
MongoDB and PHP ZendCon 2011Steven Francia
 
Blending MongoDB and RDBMS for ecommerce
Blending MongoDB and RDBMS for ecommerceBlending MongoDB and RDBMS for ecommerce
Blending MongoDB and RDBMS for ecommerceSteven Francia
 
Augmenting RDBMS with MongoDB for ecommerce
Augmenting RDBMS with MongoDB for ecommerceAugmenting RDBMS with MongoDB for ecommerce
Augmenting RDBMS with MongoDB for ecommerceSteven Francia
 
MongoDB and Ecommerce : A perfect combination
MongoDB and Ecommerce : A perfect combinationMongoDB and Ecommerce : A perfect combination
MongoDB and Ecommerce : A perfect combinationSteven Francia
 

More from Steven Francia (17)

State of the Gopher Nation - Golang - August 2017
State of the Gopher Nation - Golang - August 2017State of the Gopher Nation - Golang - August 2017
State of the Gopher Nation - Golang - August 2017
 
Modern Database Systems (for Genealogy)
Modern Database Systems (for Genealogy)Modern Database Systems (for Genealogy)
Modern Database Systems (for Genealogy)
 
Future of data
Future of dataFuture of data
Future of data
 
MongoDB, Hadoop and humongous data - MongoSV 2012
MongoDB, Hadoop and humongous data - MongoSV 2012MongoDB, Hadoop and humongous data - MongoSV 2012
MongoDB, Hadoop and humongous data - MongoSV 2012
 
Big data for the rest of us
Big data for the rest of usBig data for the rest of us
Big data for the rest of us
 
Multi Data Center Strategies
Multi Data Center StrategiesMulti Data Center Strategies
Multi Data Center Strategies
 
MongoDB and hadoop
MongoDB and hadoopMongoDB and hadoop
MongoDB and hadoop
 
MongoDB for Genealogy
MongoDB for GenealogyMongoDB for Genealogy
MongoDB for Genealogy
 
Hybrid MongoDB and RDBMS Applications
Hybrid MongoDB and RDBMS ApplicationsHybrid MongoDB and RDBMS Applications
Hybrid MongoDB and RDBMS Applications
 
Building your first application w/mongoDB MongoSV2011
Building your first application w/mongoDB MongoSV2011Building your first application w/mongoDB MongoSV2011
Building your first application w/mongoDB MongoSV2011
 
MongoDB, E-commerce and Transactions
MongoDB, E-commerce and TransactionsMongoDB, E-commerce and Transactions
MongoDB, E-commerce and Transactions
 
MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011
 
MongoDB and PHP ZendCon 2011
MongoDB and PHP ZendCon 2011MongoDB and PHP ZendCon 2011
MongoDB and PHP ZendCon 2011
 
MongoDB
MongoDBMongoDB
MongoDB
 
Blending MongoDB and RDBMS for ecommerce
Blending MongoDB and RDBMS for ecommerceBlending MongoDB and RDBMS for ecommerce
Blending MongoDB and RDBMS for ecommerce
 
Augmenting RDBMS with MongoDB for ecommerce
Augmenting RDBMS with MongoDB for ecommerceAugmenting RDBMS with MongoDB for ecommerce
Augmenting RDBMS with MongoDB for ecommerce
 
MongoDB and Ecommerce : A perfect combination
MongoDB and Ecommerce : A perfect combinationMongoDB and Ecommerce : A perfect combination
MongoDB and Ecommerce : A perfect combination
 

Recently uploaded

Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 

Recently uploaded (20)

Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 

Building Awesome CLI apps in Go