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)