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

Hive on Spark の設計指針を読んでみた
Hive on Spark の設計指針を読んでみたHive on Spark の設計指針を読んでみた
Hive on Spark の設計指針を読んでみたRecruit Technologies
 
Getting the most out of MariaDB MaxScale
Getting the most out of MariaDB MaxScaleGetting the most out of MariaDB MaxScale
Getting the most out of MariaDB MaxScaleMariaDB plc
 
Git Lab Introduction
Git Lab IntroductionGit Lab Introduction
Git Lab IntroductionKrunal Doshi
 
Introducing GitLab (June 2018)
Introducing GitLab (June 2018)Introducing GitLab (June 2018)
Introducing GitLab (June 2018)Noa Harel
 
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트OpenStack Korea Community
 
Kubernetes Architecture and Introduction
Kubernetes Architecture and IntroductionKubernetes Architecture and Introduction
Kubernetes Architecture and IntroductionStefan Schimanski
 
Improving Apache Spark for Dynamic Allocation and Spot Instances
Improving Apache Spark for Dynamic Allocation and Spot InstancesImproving Apache Spark for Dynamic Allocation and Spot Instances
Improving Apache Spark for Dynamic Allocation and Spot InstancesDatabricks
 
A Practical Introduction to Apache Solr
A Practical Introduction to Apache SolrA Practical Introduction to Apache Solr
A Practical Introduction to Apache SolrAngel Borroy López
 
Best Practices of HA and Replication of PostgreSQL in Virtualized Environments
Best Practices of HA and Replication of PostgreSQL in Virtualized EnvironmentsBest Practices of HA and Replication of PostgreSQL in Virtualized Environments
Best Practices of HA and Replication of PostgreSQL in Virtualized EnvironmentsJignesh Shah
 
Top 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark ApplicationsTop 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark ApplicationsSpark Summit
 
OpenStackをさらに”使う”技術 概要と基礎操作
OpenStackをさらに”使う”技術 概要と基礎操作OpenStackをさらに”使う”技術 概要と基礎操作
OpenStackをさらに”使う”技術 概要と基礎操作irix_jp
 
K8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals TrainingK8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals TrainingPiotr Perzyna
 
Design cube in Apache Kylin
Design cube in Apache KylinDesign cube in Apache Kylin
Design cube in Apache KylinYang Li
 
Boomi Molecule Migration to the Cloud: Top 5 Strategies Revealed
Boomi Molecule Migration to the Cloud: Top 5 Strategies RevealedBoomi Molecule Migration to the Cloud: Top 5 Strategies Revealed
Boomi Molecule Migration to the Cloud: Top 5 Strategies RevealedKellton Tech Solutions Ltd
 
Pi Day 2022 - from IoT to MySQL HeatWave Database Service
Pi Day 2022 -  from IoT to MySQL HeatWave Database ServicePi Day 2022 -  from IoT to MySQL HeatWave Database Service
Pi Day 2022 - from IoT to MySQL HeatWave Database ServiceFrederic Descamps
 
The journey to GitOps
The journey to GitOpsThe journey to GitOps
The journey to GitOpsNicola Baldi
 
Automation with ansible
Automation with ansibleAutomation with ansible
Automation with ansibleKhizer Naeem
 
오픈스택: 구석구석 파헤쳐보기
오픈스택: 구석구석 파헤쳐보기오픈스택: 구석구석 파헤쳐보기
오픈스택: 구석구석 파헤쳐보기Jaehwa Park
 

What's hot (20)

Hive on Spark の設計指針を読んでみた
Hive on Spark の設計指針を読んでみたHive on Spark の設計指針を読んでみた
Hive on Spark の設計指針を読んでみた
 
Gitlab CI/CD
Gitlab CI/CDGitlab CI/CD
Gitlab CI/CD
 
Getting the most out of MariaDB MaxScale
Getting the most out of MariaDB MaxScaleGetting the most out of MariaDB MaxScale
Getting the most out of MariaDB MaxScale
 
Git Lab Introduction
Git Lab IntroductionGit Lab Introduction
Git Lab Introduction
 
Introducing GitLab (June 2018)
Introducing GitLab (June 2018)Introducing GitLab (June 2018)
Introducing GitLab (June 2018)
 
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트
[OpenStack Days Korea 2016] Track3 - 오픈스택 환경에서 공유 파일 시스템 구현하기: 마닐라(Manila) 프로젝트
 
Kubernetes Architecture and Introduction
Kubernetes Architecture and IntroductionKubernetes Architecture and Introduction
Kubernetes Architecture and Introduction
 
Improving Apache Spark for Dynamic Allocation and Spot Instances
Improving Apache Spark for Dynamic Allocation and Spot InstancesImproving Apache Spark for Dynamic Allocation and Spot Instances
Improving Apache Spark for Dynamic Allocation and Spot Instances
 
A Practical Introduction to Apache Solr
A Practical Introduction to Apache SolrA Practical Introduction to Apache Solr
A Practical Introduction to Apache Solr
 
Best Practices of HA and Replication of PostgreSQL in Virtualized Environments
Best Practices of HA and Replication of PostgreSQL in Virtualized EnvironmentsBest Practices of HA and Replication of PostgreSQL in Virtualized Environments
Best Practices of HA and Replication of PostgreSQL in Virtualized Environments
 
Top 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark ApplicationsTop 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark Applications
 
Introduction to git
Introduction to gitIntroduction to git
Introduction to git
 
OpenStackをさらに”使う”技術 概要と基礎操作
OpenStackをさらに”使う”技術 概要と基礎操作OpenStackをさらに”使う”技術 概要と基礎操作
OpenStackをさらに”使う”技術 概要と基礎操作
 
K8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals TrainingK8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals Training
 
Design cube in Apache Kylin
Design cube in Apache KylinDesign cube in Apache Kylin
Design cube in Apache Kylin
 
Boomi Molecule Migration to the Cloud: Top 5 Strategies Revealed
Boomi Molecule Migration to the Cloud: Top 5 Strategies RevealedBoomi Molecule Migration to the Cloud: Top 5 Strategies Revealed
Boomi Molecule Migration to the Cloud: Top 5 Strategies Revealed
 
Pi Day 2022 - from IoT to MySQL HeatWave Database Service
Pi Day 2022 -  from IoT to MySQL HeatWave Database ServicePi Day 2022 -  from IoT to MySQL HeatWave Database Service
Pi Day 2022 - from IoT to MySQL HeatWave Database Service
 
The journey to GitOps
The journey to GitOpsThe journey to GitOps
The journey to GitOps
 
Automation with ansible
Automation with ansibleAutomation with ansible
Automation with ansible
 
오픈스택: 구석구석 파헤쳐보기
오픈스택: 구석구석 파헤쳐보기오픈스택: 구석구석 파헤쳐보기
오픈스택: 구석구석 파헤쳐보기
 

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
 
7 Common Mistakes in Go (2015)
7 Common Mistakes in Go (2015)7 Common Mistakes in Go (2015)
7 Common Mistakes in Go (2015)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
 

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...
 
7 Common Mistakes in Go (2015)
7 Common Mistakes in Go (2015)7 Common Mistakes in Go (2015)
7 Common Mistakes in Go (2015)
 
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
 

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

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
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
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
🐬 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
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
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
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 

Recently uploaded (20)

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
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
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
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
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 

Building Awesome CLI apps in Go