WritingAnAppWithGo
Writing an App with Go - Instructors: Gustavo Niemeyer
1 === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: App Developer Week - Current Session: Writing an App with Go - Instructors: niemeyer http://pad.ubuntu.com/ep/pad/view/ro.vJnRUh5vWNI/latest
2 [20:00] <ClassBot> Logs for this session will be available at http://irclogs.ubuntu.com/2011/09/09/%23ubuntu-classroom.html following the conclusion of the session.
3 [20:01] <niemeyer> Hello everyone!
4 [20:01] <niemeyer> Sorry for interrupting the amazing set of questions zoopster :)
5 [20:02] <niemeyer> So, I'm here to talk about how to develop apps in Go today
6 [20:02] <niemeyer> This is the Go language not the game board obviously
7 [20:02] <niemeyer> http://golang.org
8 [20:02] <niemeyer> I'll be using an Etherpad over the conversation to put content
9 [20:03] <niemeyer> Please follow up here:
10 [20:03] <niemeyer> http://pad.ubuntu.com/ep/pad/view/ro.vJnRUh5vWNI/latest
11 [20:03] <niemeyer> nigelb, pleia2: Can we have that in the topic?
12 [20:04] <niemeyer> Please feel free to ask any questions as I go.. I'll be happy to talk
13 [20:04] <niemeyer> I don't have a specific script in mind, so I'll be happier to solve doubts and to talk to you than to be in a monologue presenting the language
14 [20:04] <niemeyer> There's plenty of material online to follow, and I'll be providing some pointers
15 [20:04] <niemeyer> So let's make the most of our time here to exchange ideas and solve questions
16 [20:05] <niemeyer> So
17 [20:05] <niemeyer> My name is Gustavo Niemeyer, and I'm responsible for the area of Amazing And Unknown Projects at Canonical
18 [20:06] <niemeyer> Was pushing Landscape for several years, and then when it started to get well known I moved to the Ensemble project
19 [20:06] <niemeyer> https://landscape.canonical.com, https://ensemble.ubuntu.com
20 [20:06] <niemeyer> Now Ensemble is getting well known, but I think I'll stick for a little longer ;-)
21 [20:07] <niemeyer> Little more than a year and a half ago I started playing with Go in my personal time
22 [20:07] <niemeyer> Not really expecting much
23 [20:07] <niemeyer> I've been doing that with every other language for a while.. Haskell, Erlang, Java, etc
24 [20:07] <niemeyer> Python was the last language to hook me up for a long time as the "preferred whenever possible" choice
25 [20:08] <niemeyer> After I started some projects with Go, though, I started to really appreciate what was there
26 [20:08] <niemeyer> It didn't really hook me up for any _specific_ feature, though
27 [20:08] <niemeyer> What's most amazing about it is really the sum of the parts
28 [20:08] <niemeyer> In fact, it's a pretty simple language
29 [20:08] <niemeyer> So most aspects you'll see there will be a "Ah, but that's done elsewhere too" moment
30 [20:08] <niemeyer> and that's surely the case
31 [20:09] <niemeyer> The detail is precisely that it's putting all of those things in _one_ language
32 [20:09] <niemeyer> In a very nice to digest fashion
33 [20:09] <niemeyer> For instance,
34 [20:09] <niemeyer> Go is statically compiled, but has good reflection capabilities
35 [20:09] <niemeyer> It also has what I like to call "static duck typing"..
36 [20:10] <niemeyer> If you've used Python or similar languages before, you know what I mean by that..
37 [20:10] <niemeyer> In Python, you just provide a value to a function, say, and expect that the function will handle it correctly
38 [20:11] <niemeyer> So any method that has, say, a read( ) method, can be provided to a method that calls value.read()
39 [20:11] <niemeyer> In Go, there are interfaces
40 [20:11] <niemeyer> But they're not like interfaces in languages like Java, for instance
41 [20:11] <niemeyer> if you declare an interface like this:
42 [20:11] <niemeyer> type Validator interface { IsValid() bool }
43 [20:12] <niemeyer> You can use that to declare a function..
44 [20:12] <niemeyer> func MyF(v Validator) { println(v.IsValid()) }
45 [20:12] <niemeyer> and any objects at all that define such a method can be used
46 [20:12] <niemeyer> they don't have to _declare_ that they implement the Validator interface.. they simply do as long as they have the right methods
47 [20:13] <niemeyer> ...
48 [20:13] <niemeyer> Anyway
49 [20:13] <niemeyer> That's called structural typing, btw.. if you fancy CS
50 [20:13] <niemeyer> A few other factors of the top of my head..
51 [20:13] <niemeyer> Go is
52 [20:13] <niemeyer> - Garbage collected
53 [20:14] <niemeyer> - Capable of producing good tracebacks
54 [20:14] <niemeyer> - Debuggable with gdb
55 [20:14] <niemeyer> - Has an easy to use module/package system
56 [20:15] <niemeyer> Hmm.. lots of leavers :)
57 [20:15] <niemeyer> Maybe I should get into some action.
58 [20:15] <niemeyer> Let's get it working then.
59 [20:16] <niemeyer> First thing, you'll need to install the language
60 [20:16] <niemeyer> It's available in Oneiric
61 [20:16] <niemeyer> If you're using an older release, there is a PPA available
62 [20:16] <niemeyer> Supporting down to Lucid
63 [20:16] <niemeyer> sudo add-apt-repository ppa:gophers/go
64 [20:17] <niemeyer> sudo apt-get update
65 [20:17] <niemeyer> sudo apt-get install golang
66 [20:17] <niemeyer> Just the last command for Oneiric
67 [20:17] <niemeyer> Now, let's produce a hello world example..
68 [20:17] <niemeyer> I'll guide you towards having a sane environment that you can evolve from, rather than just a quick and dirty one
69 [20:18] <niemeyer> So, create a directory:
70 [20:18] <niemeyer> mkdir ~/gopath
71 [20:18] <niemeyer> and export the variable:
72 [20:18] <niemeyer> export GOPATH=~/gopath
73 [20:18] <niemeyer> This instructs goinstall that you want to be using that directory for installing programs and packages
74 [20:19] <niemeyer> Now, let's create a source directory for our program
75 [20:19] <niemeyer> mkdir -p ~/gopath/src/example.com/mycmd
76 [20:19] <niemeyer> cd ~/gopath/src/example.com/mycmd
77 [20:20] <niemeyer> When you host your source code, you'll have only that last bit withing the revision control, usually
78 [20:20] <niemeyer> the example.com is just namespacing the import.. it'll become more clear as we go on
79 [20:21] <niemeyer> So, you're now within that directory
80 [20:21] <niemeyer> Let's type the following on that file (on the fly! ugh)
81 [20:21] <niemeyer> package main
82 [20:21] <niemeyer> import "fmt"
83 [20:21] <niemeyer> func main() {
84 [20:21] <niemeyer> fmt.Printf("Hello world\n")
85 [20:21] <niemeyer> }
86 [20:21] <niemeyer> Put that within a main.go file
87 [20:22] <niemeyer> The name is actually not important
88 [20:22] <niemeyer> Now, if you type this command:
89 [20:22] <niemeyer> goinstall example.com/mycmd
90 [20:22] <niemeyer> You should get mycmd within ~/gopath/bin/mycmd
91 [20:22] <niemeyer> Try to execute it
92 [20:23] <niemeyer> Congratulations!
93 [20:23] <niemeyer> You've just run your first Go program :-)
94 [20:23] <niemeyer> Let's go a bit further to understand what we're doing
95 [20:23] <niemeyer> Still within ~/gopath/example.com/mycmd
96 [20:24] <niemeyer> Let's create a second file called util.go
97 [20:24] <niemeyer> and type this within it:
98 [20:24] <niemeyer> package main
99 [20:24] <niemeyer> func Hello() {
100 [20:24] <niemeyer> println("Hello there!")
101 [20:24] <niemeyer> }
102 [20:25] <niemeyer> Now, edit your main.go, and replace the Printf(...) with this:
103 [20:25] <niemeyer> Hello()
104 [20:25] <niemeyer> and try the command again:
105 [20:25] <niemeyer> goinstall example.com/mycmd
106 [20:26] <niemeyer> You'll get an error regarding "fmt" not used.. simply remove the line import "fmt"..
107 [20:26] <niemeyer> and try again
108 [20:26] <niemeyer> Anyway.. the point I'm trying to make is this:
109 [20:26] <niemeyer> All files within a single package in Go are part of the same namespace
110 [20:27] <niemeyer> You can name files as you wish
111 [20:27] <niemeyer> They're just organizational
112 [20:27] <niemeyer> Now, let's get a bit fancier..
113 [20:27] <niemeyer> Let's introduce a package
114 [20:27] <niemeyer> Later we'll be playing with concurrency a bit too..
115 [20:28] <niemeyer> So.. let's create our package directory
116 [20:28] <niemeyer> mkdir -p ~/gopath/src/example.com/mypkg
117 [20:28] <niemeyer> cd ~/gopath/src/example.com/mypkg
118 [20:28] <niemeyer> Again, same idea
119 [20:28] <niemeyer> Files are just for organization..
120 [20:28] <niemeyer> Let's name ours as hello.go
121 [20:29] <niemeyer> Open hello.go within mypkg and put this content there:
122 [20:29] <niemeyer> package mypkg
123 [20:29] <niemeyer> func Hello(ch chan string) {
124 [20:30] <niemeyer> println("Hello", <-ch)
125 [20:30] <niemeyer> println("Hi as well", <-ch)
126 [20:30] <niemeyer> }
127 [20:30] <niemeyer> Let me copy & past locally to follow
128 [20:31] <niemeyer> Alright..
129 [20:31] <niemeyer> We have a package!
130 [20:31] <niemeyer> One very interesting detail:
131 [20:31] <niemeyer> This package is within its own namespace..
132 [20:32] <niemeyer> We can only access Hello() because it starts with a capital cased letter
133 [20:32] <niemeyer> This is the way Go differentiates private from exported variables, constants, functions, methods, etc
134 [20:32] <niemeyer> In all of those cases, capital case == exported
135 [20:32] <niemeyer> At first this feels a bit strange, but it has a pretty interesting consequence:
136 [20:33] <niemeyer> Every _usage_ of any of those things makes it clear if what's being used is public or not
137 [20:33] <niemeyer> So.. let's go..
138 [20:33] <niemeyer> Go back to our command
139 [20:33] <niemeyer> cd ~/gopath/example.com/mycmd
140 [20:33] <niemeyer> And type this new code in there:
141 [20:33] <niemeyer> Within file main.go, that is:
142 [20:33] <niemeyer> package main
143 [20:34] <niemeyer> import "example.com/mypkg"
144 [20:34] <niemeyer> func main() {
145 [20:34] <niemeyer> ch := make(chan string)
146 [20:35] <niemeyer> go mypkg.Hello(ch)
147 [20:35] <niemeyer> ch <- "Joe"
148 [20:35] <niemeyer> ch <- "Bob"
149 [20:35] <niemeyer> }
150 [20:35] <niemeyer> If I didn't screw up, you can run this now:
151 [20:36] <niemeyer> goinstall example.com/mycmd
152 [20:36] <niemeyer> and then
153 [20:36] <niemeyer> ~/gopath/bin/mycmd
154 [20:36] <niemeyer> Try that out
155 [20:37] <niemeyer> I made a mistake, which I'll mention in a bit, but first let's go over what just happened
156 [20:37] <niemeyer> We imported the package "example.com/mypkg"
157 [20:38] <niemeyer> This causes goinstall to look for this package, *download* it if necessary, compile, and install it
158 [20:38] <niemeyer> You can check that this is indeed the case by listing: ls ~/gopath/pkg/*/*
159 [20:39] <niemeyer> You should get a mypkg.a inside it
160 [20:39] <niemeyer> This is your package example.com/mypkg compiled into binary form
161 [20:40] <niemeyer> Then, we've called the Hello() function within it
162 [20:40] <niemeyer> But we haven't simply called it
163 [20:40] <niemeyer> The "go" keyword we've used ahead of the function call instructs the compiler that the function call should be put in the background
164 [20:40] <niemeyer> So mypkg.Hello() was running concurrently with your main() function
165 [20:41] <niemeyer> Then the statement
166 [20:41] <niemeyer> println(..., <-ch)
167 [20:41] <niemeyer> Will block in the channel receive expression (<-ch) before a value is available for consumption
168 [20:41] <niemeyer> which is exactly what we did next in main()
169 [20:41] <niemeyer> ch <- "Joe" sends a value
170 [20:42] <niemeyer> The mistake I made in that case, is that the main() function is not waiting for the concurrently running function to terminate
171 [20:42] <niemeyer> There are tricks that may be used for this, such as
172 [20:42] <niemeyer> select{}
173 [20:43] <niemeyer> Then, in case you wanted to actually publish that code to be easily consumable,
174 [20:43] <niemeyer> you could put the code within Launchpad or Github
175 [20:43] <niemeyer> Exactly as it is
176 [20:43] <niemeyer> Just put the content of "mypkg" for instance within the trunk of a project launchpad.net/mypkg
177 [20:43] <niemeyer> And people will be able to "goinstall launchpad.net/mypkg"
178 [20:44] <niemeyer> So.. that's a quick introduction to the language..
179 [20:44] <niemeyer> But there's a _lot_ more to talk about it
180 [20:44] <niemeyer> unfortunately I cna't type that fast and we don't have as much time :)
181 [20:44] <niemeyer> So I'll provide some resources
182 [20:44] <niemeyer> And open to questions
183 [20:45] <niemeyer> The main site is the key documentation point:
184 [20:45] <niemeyer> http://golang.org
185 [20:45] <niemeyer> There's _very_ good introductory documentation there..
186 [20:45] <niemeyer> I recommend the Getting Started, Tutorial, and Effective Go, in that order
187 [20:45] <niemeyer> You should be quite proficient after that
188 [20:45] <niemeyer> Well.. or able to use it at least..
189 [20:46] <niemeyer> Proficiency comes with practice
190 [20:46] <niemeyer> I'm one of the external contributors of the language as well, so I'll be happy to answer deeper questions which I'm happy to be familiar with in case you have any
191 [20:46] <niemeyer> So, that was it.. please shoot the questions..
192 [20:47] <niemeyer> Or maybe not.. :-)
193 [20:49] <niemeyer> Alright.. I guess I'm alone in here. :-)
194 [20:49] <niemeyer> Thanks for attending, and please drop me a message if you have questions.
195 [20:50] <niemeyer> #go-nuts in this same server is also a good place to talk about it.
196 [20:50] <niemeyer> I'll be happy to answer questions in the -chat as well
MeetingLogs/appdevweek1109/WritingAnAppWithGo (last edited 2011-09-12 15:43:21 by bl18-252-24)